mirror of
https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation.git
synced 2026-08-27 15:51:34 +02:00
Rust fmt
This commit is contained in:
parent
1b8f503986
commit
1764665f37
15 changed files with 456 additions and 367 deletions
2
build.rs
2
build.rs
|
|
@ -13,4 +13,4 @@ fn main() {
|
|||
println!("cargo:rustc-link-lib=static=stdc++");
|
||||
println!("cargo:rustc-link-lib=static=winpthread");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
pub mod sync;
|
||||
pub mod theme;
|
||||
pub mod uad_lists;
|
||||
pub mod utils;
|
||||
pub mod theme;
|
||||
194
src/core/sync.rs
194
src/core/sync.rs
|
|
@ -1,15 +1,14 @@
|
|||
use std::process::Command;
|
||||
use std::collections::{HashSet};
|
||||
use regex::Regex;
|
||||
use crate::core::uad_lists::{PackageState};
|
||||
use crate::core::uad_lists::PackageState;
|
||||
use crate::gui::views::settings::Settings;
|
||||
use crate::gui::widgets::package_row::PackageRow;
|
||||
use static_init::{dynamic};
|
||||
use regex::Regex;
|
||||
use static_init::dynamic;
|
||||
use std::collections::HashSet;
|
||||
use std::process::Command;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::os::windows::process::CommandExt;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Phone {
|
||||
pub model: String,
|
||||
|
|
@ -35,36 +34,27 @@ pub struct User {
|
|||
|
||||
impl std::fmt::Display for User {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
format!("user {}", self.id),
|
||||
)
|
||||
write!(f, "{}", format!("user {}", self.id),)
|
||||
}
|
||||
}
|
||||
pub fn adb_shell_command(args: &str) -> Result<String,String> {
|
||||
|
||||
}
|
||||
pub fn adb_shell_command(args: &str) -> Result<String, String> {
|
||||
#[cfg(target_os = "windows")]
|
||||
let output = Command::new("adb")
|
||||
.args(&["shell", args])
|
||||
.creation_flags(0x08000000) // do not open a cmd window
|
||||
.output();
|
||||
let output = Command::new("adb")
|
||||
.args(&["shell", args])
|
||||
.creation_flags(0x08000000) // do not open a cmd window
|
||||
.output();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let output = Command::new("adb")
|
||||
.args(&["shell", args])
|
||||
.output();
|
||||
let output = Command::new("adb").args(&["shell", args]).output();
|
||||
|
||||
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
||||
let output = Command::new("adb")
|
||||
.args(&["shell", args])
|
||||
.output();
|
||||
let output = Command::new("adb").args(&["shell", args]).output();
|
||||
|
||||
match output {
|
||||
Err(e) => {
|
||||
error!("ADB: {}", e);
|
||||
Err("ADB was not found".to_string())
|
||||
},
|
||||
}
|
||||
Ok(o) => {
|
||||
if !o.status.success() {
|
||||
let stdout = String::from_utf8(o.stdout).unwrap().trim_end().to_string();
|
||||
|
|
@ -77,11 +67,9 @@ pub fn adb_shell_command(args: &str) -> Result<String,String> {
|
|||
Ok(String::from_utf8(o.stdout).unwrap().trim_end().to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn list_all_system_packages(user_id: &Option<&User>) -> String {
|
||||
let action = match user_id {
|
||||
Some(user_id) => format!("pm list packages -s -u --user {}", user_id.id),
|
||||
|
|
@ -96,7 +84,7 @@ pub fn list_all_system_packages(user_id: &Option<&User>) -> String {
|
|||
pub fn hashset_system_packages(state: PackageState, user_id: &Option<&User>) -> HashSet<String> {
|
||||
let user = match user_id {
|
||||
Some(user_id) => format!(" --user {}", user_id.id),
|
||||
None => "".to_string()
|
||||
None => "".to_string(),
|
||||
};
|
||||
|
||||
let action = match state {
|
||||
|
|
@ -113,80 +101,105 @@ pub fn hashset_system_packages(state: PackageState, user_id: &Option<&User>) ->
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn action_handler(selected_user: &User, package: &PackageRow, phone: &Phone, settings: &Settings) -> Result<bool, bool> {
|
||||
pub fn action_handler(
|
||||
selected_user: &User,
|
||||
package: &PackageRow,
|
||||
phone: &Phone,
|
||||
settings: &Settings,
|
||||
) -> Result<bool, bool> {
|
||||
let actions: Vec<String> = match package.state {
|
||||
PackageState::Enabled => {
|
||||
match settings.disable_mode {
|
||||
true => {
|
||||
if phone.android_sdk < 21 {
|
||||
vec![
|
||||
format!("am force-stop {}", package.name),
|
||||
format!("pm disable-user {}", package.name),
|
||||
format!("pm clear {}", package.name)
|
||||
]
|
||||
} else if settings.multi_user_mode{
|
||||
phone.user_list
|
||||
.iter()
|
||||
.flat_map(
|
||||
|u| [
|
||||
format!("am force-stop --user {} {}", u.id, package.name),
|
||||
format!("pm disable-user --user {} {}", u.id, package.name),
|
||||
format!("pm clear --user {} {}", u.id, package.name)
|
||||
])
|
||||
.collect()
|
||||
} else {
|
||||
vec![
|
||||
format!("am force-stop --user {} {}", selected_user.id, package.name),
|
||||
format!("pm disable-user --user {} {}", selected_user.id, package.name),
|
||||
format!("pm clear --user {} {}", selected_user.id, package.name)
|
||||
]
|
||||
}
|
||||
}
|
||||
false => {
|
||||
if phone.android_sdk < 21 {
|
||||
vec![format!("pm uninstall {}", package.name)]
|
||||
} else if settings.multi_user_mode {
|
||||
phone.user_list
|
||||
.iter()
|
||||
.map(|u| format!("pm uninstall --user {} {}", u.id, package.name))
|
||||
.collect()
|
||||
} else {
|
||||
vec![format!("pm uninstall --user {} {}", selected_user.id, package.name)]
|
||||
}
|
||||
PackageState::Enabled => match settings.disable_mode {
|
||||
true => {
|
||||
if phone.android_sdk < 21 {
|
||||
vec![
|
||||
format!("am force-stop {}", package.name),
|
||||
format!("pm disable-user {}", package.name),
|
||||
format!("pm clear {}", package.name),
|
||||
]
|
||||
} else if settings.multi_user_mode {
|
||||
phone
|
||||
.user_list
|
||||
.iter()
|
||||
.flat_map(|u| {
|
||||
[
|
||||
format!("am force-stop --user {} {}", u.id, package.name),
|
||||
format!("pm disable-user --user {} {}", u.id, package.name),
|
||||
format!("pm clear --user {} {}", u.id, package.name),
|
||||
]
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
vec![
|
||||
format!("am force-stop --user {} {}", selected_user.id, package.name),
|
||||
format!(
|
||||
"pm disable-user --user {} {}",
|
||||
selected_user.id, package.name
|
||||
),
|
||||
format!("pm clear --user {} {}", selected_user.id, package.name),
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
false => {
|
||||
if phone.android_sdk < 21 {
|
||||
vec![format!("pm uninstall {}", package.name)]
|
||||
} else if settings.multi_user_mode {
|
||||
phone
|
||||
.user_list
|
||||
.iter()
|
||||
.map(|u| format!("pm uninstall --user {} {}", u.id, package.name))
|
||||
.collect()
|
||||
} else {
|
||||
vec![format!(
|
||||
"pm uninstall --user {} {}",
|
||||
selected_user.id, package.name
|
||||
)]
|
||||
}
|
||||
}
|
||||
},
|
||||
PackageState::Uninstalled => {
|
||||
if phone.android_sdk < 21 {
|
||||
Vec::new() // action already prevented by the GUI
|
||||
} else if settings.multi_user_mode {
|
||||
phone.user_list
|
||||
phone
|
||||
.user_list
|
||||
.iter()
|
||||
.map(|u| format!("cmd package install-existing --user {} {}", u.id, package.name))
|
||||
.map(|u| {
|
||||
format!(
|
||||
"cmd package install-existing --user {} {}",
|
||||
u.id, package.name
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
vec![format!("cmd package install-existing --user {} {}", selected_user.id, package.name)]
|
||||
vec![format!(
|
||||
"cmd package install-existing --user {} {}",
|
||||
selected_user.id, package.name
|
||||
)]
|
||||
}
|
||||
},
|
||||
}
|
||||
PackageState::Disabled => {
|
||||
if phone.android_sdk < 21 {
|
||||
vec![format!("pm enable {}", package.name)]
|
||||
} else if settings.multi_user_mode {
|
||||
phone.user_list
|
||||
phone
|
||||
.user_list
|
||||
.iter()
|
||||
.map(|u| format!("pm enable --user {} {}", u.id, package.name))
|
||||
.collect()
|
||||
} else {
|
||||
vec![format!("pm enable --user {} {}", selected_user.id, package.name)]
|
||||
vec![format!(
|
||||
"pm enable --user {} {}",
|
||||
selected_user.id, package.name
|
||||
)]
|
||||
}
|
||||
},
|
||||
}
|
||||
PackageState::All => vec![], // This can't happen (like... never)
|
||||
};
|
||||
|
||||
for action in actions {
|
||||
match adb_shell_command(&action) {
|
||||
Ok(_) => {
|
||||
info!("[{}] {}", package.removal , action);
|
||||
Ok(_) => {
|
||||
info!("[{}] {}", package.removal, action);
|
||||
}
|
||||
Err(err) => {
|
||||
if err.contains("[not installed for") {
|
||||
|
|
@ -211,21 +224,22 @@ pub fn get_phone_model() -> String {
|
|||
err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_android_sdk() -> u8 {
|
||||
match adb_shell_command("getprop ro.build.version.sdk") {
|
||||
Ok(sdk) => sdk.parse().unwrap(),
|
||||
Err(_) => 0,
|
||||
Err(_) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn get_phone_brand() -> String {
|
||||
format!("{} {}",
|
||||
adb_shell_command("getprop ro.product.brand").unwrap_or_else(|_| "".to_string()).trim(),
|
||||
format!(
|
||||
"{} {}",
|
||||
adb_shell_command("getprop ro.product.brand")
|
||||
.unwrap_or_else(|_| "".to_string())
|
||||
.trim(),
|
||||
get_phone_model()
|
||||
)
|
||||
}
|
||||
|
|
@ -235,10 +249,14 @@ pub fn get_user_list() -> Vec<User> {
|
|||
static RE: Regex = Regex::new(r"\{([0-9]+)").unwrap();
|
||||
|
||||
match adb_shell_command("pm list users") {
|
||||
Ok(users) => RE.find_iter(&users)
|
||||
.enumerate()
|
||||
.map(|(i,u)| User { id: u.as_str()[1..].parse().unwrap(), index: i})
|
||||
.collect(),
|
||||
Ok(users) => RE
|
||||
.find_iter(&users)
|
||||
.enumerate()
|
||||
.map(|(i, u)| User {
|
||||
id: u.as_str()[1..].parse().unwrap(),
|
||||
index: i,
|
||||
})
|
||||
.collect(),
|
||||
Err(_) => vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use std::cmp::Ordering;
|
||||
use iced::Color;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Theme {
|
||||
|
|
@ -38,11 +38,7 @@ pub struct ColorPalette {
|
|||
|
||||
impl Theme {
|
||||
pub fn all() -> Vec<Theme> {
|
||||
vec![
|
||||
Theme::dark(),
|
||||
Theme::light(),
|
||||
Theme::lupin(),
|
||||
]
|
||||
vec![Theme::dark(), Theme::light(), Theme::lupin()]
|
||||
}
|
||||
|
||||
pub fn dark() -> Theme {
|
||||
|
|
@ -116,7 +112,6 @@ impl Theme {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl PartialEq for Theme {
|
||||
|
|
@ -173,4 +168,4 @@ fn hex_to_color(hex: &str) -> Option<Color> {
|
|||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use serde::{Deserialize};
|
||||
use serde::Deserialize;
|
||||
use serde_json;
|
||||
//use std::fs;
|
||||
use std::{collections::HashMap};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Deserialize, Debug, Clone, PartialEq, Hash, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
|
@ -16,7 +15,6 @@ pub struct Package {
|
|||
pub removal: Removal,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum UadList {
|
||||
All,
|
||||
|
|
@ -90,7 +88,6 @@ impl PackageState {
|
|||
];
|
||||
}
|
||||
|
||||
|
||||
impl std::fmt::Display for PackageState {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
|
|
@ -114,8 +111,12 @@ impl Opposite for PackageState {
|
|||
fn opposite(&self, disable: bool) -> PackageState {
|
||||
match self {
|
||||
PackageState::Enabled => {
|
||||
if disable {PackageState::Disabled} else {PackageState::Uninstalled}
|
||||
},
|
||||
if disable {
|
||||
PackageState::Disabled
|
||||
} else {
|
||||
PackageState::Uninstalled
|
||||
}
|
||||
}
|
||||
PackageState::Uninstalled => PackageState::Enabled,
|
||||
PackageState::Disabled => PackageState::Enabled,
|
||||
PackageState::All => PackageState::All,
|
||||
|
|
@ -151,7 +152,6 @@ impl Removal {
|
|||
];
|
||||
}
|
||||
|
||||
|
||||
impl std::fmt::Display for Removal {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
|
|
@ -169,7 +169,6 @@ impl std::fmt::Display for Removal {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn load_debloat_lists() -> HashMap<String, Package> {
|
||||
const DATA: &str = include_str!("../../ressources/assets/uad_lists.json");
|
||||
let mut package_lists = HashMap::new();
|
||||
|
|
@ -185,6 +184,3 @@ pub fn load_debloat_lists() -> HashMap<String, Package> {
|
|||
|
||||
package_lists
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
use crate::core::uad_lists::{UadList, PackageState, Package, Removal};
|
||||
use crate::gui::widgets::package_row::PackageRow;
|
||||
use crate::core::sync::{hashset_system_packages, list_all_system_packages, User};
|
||||
use crate::core::uad_lists::{Package, PackageState, Removal, UadList};
|
||||
use crate::gui::views::list::Selection;
|
||||
use crate::core::sync::{list_all_system_packages, hashset_system_packages, User};
|
||||
use crate::gui::widgets::package_row::PackageRow;
|
||||
use crate::gui::ICONS;
|
||||
|
||||
use iced::{Text, alignment, Length};
|
||||
use iced::{alignment, Length, Text};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::fs;
|
||||
use std::io::{self, prelude::*, BufReader};
|
||||
|
||||
pub fn fetch_packages(uad_lists: &'static HashMap<String, Package>, user_id: &Option<&User>) -> Vec<PackageRow> {
|
||||
pub fn fetch_packages(
|
||||
uad_lists: &'static HashMap<String, Package>,
|
||||
user_id: &Option<&User>,
|
||||
) -> Vec<PackageRow> {
|
||||
let all_system_packages = list_all_system_packages(user_id); // installed and uninstalled packages
|
||||
let enabled_system_packages = hashset_system_packages(PackageState::Enabled, user_id);
|
||||
let disabled_system_packages = hashset_system_packages(PackageState::Disabled, user_id);
|
||||
|
|
@ -27,46 +30,49 @@ pub fn fetch_packages(uad_lists: &'static HashMap<String, Package>, user_id: &Op
|
|||
|
||||
if uad_lists.contains_key(p_name) {
|
||||
description = match &uad_lists.get(p_name).unwrap().description {
|
||||
Some(descr) => descr,
|
||||
None => "[No description]",
|
||||
};
|
||||
Some(descr) => descr,
|
||||
None => "[No description]",
|
||||
};
|
||||
uad_list = uad_lists.get(p_name).unwrap().list;
|
||||
removal = uad_lists.get(p_name).unwrap().removal;
|
||||
}
|
||||
|
||||
if enabled_system_packages.contains(p_name) {
|
||||
state = PackageState::Enabled;
|
||||
state = PackageState::Enabled;
|
||||
} else if disabled_system_packages.contains(p_name) {
|
||||
state = PackageState::Disabled;
|
||||
}
|
||||
|
||||
let package_row = PackageRow::new(
|
||||
p_name,
|
||||
state,
|
||||
description,
|
||||
uad_list,
|
||||
removal,
|
||||
false,
|
||||
);
|
||||
let package_row = PackageRow::new(p_name, state, description, uad_list, removal, false);
|
||||
user_package.push(package_row);
|
||||
}
|
||||
user_package.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
|
||||
user_package
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn update_selection_count(selection: &mut Selection, p_state: PackageState, add: bool) {
|
||||
match p_state {
|
||||
PackageState::Enabled => {
|
||||
if add { selection.enabled += 1 } else { selection.enabled -= 1 };
|
||||
},
|
||||
if add {
|
||||
selection.enabled += 1
|
||||
} else {
|
||||
selection.enabled -= 1
|
||||
};
|
||||
}
|
||||
PackageState::Disabled => {
|
||||
if add { selection.disabled += 1 } else { selection.disabled -= 1 };
|
||||
},
|
||||
if add {
|
||||
selection.disabled += 1
|
||||
} else {
|
||||
selection.disabled -= 1
|
||||
};
|
||||
}
|
||||
PackageState::Uninstalled => {
|
||||
if add { selection.uninstalled += 1 } else { selection.uninstalled -= 1 };
|
||||
},
|
||||
if add {
|
||||
selection.uninstalled += 1
|
||||
} else {
|
||||
selection.uninstalled -= 1
|
||||
};
|
||||
}
|
||||
PackageState::All => {}
|
||||
};
|
||||
}
|
||||
|
|
@ -81,12 +87,15 @@ pub async fn export_selection(packages: Vec<PackageRow>) -> Result<bool, String>
|
|||
|
||||
match fs::write("uad_exported_selection.txt", selected) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(err) => Err(err.to_string())
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_collect)] // false positive: https://github.com/rust-lang/rust-clippy/issues/6164
|
||||
pub fn import_selection(packages: &mut Vec<PackageRow>, selection: &mut Selection) -> io::Result<()> {
|
||||
pub fn import_selection(
|
||||
packages: &mut Vec<PackageRow>,
|
||||
selection: &mut Selection,
|
||||
) -> io::Result<()> {
|
||||
let file = fs::File::open("uad_exported_selection.txt")?;
|
||||
let reader = BufReader::new(file);
|
||||
let imported_selection: Vec<String> = reader
|
||||
|
|
@ -96,7 +105,7 @@ pub fn import_selection(packages: &mut Vec<PackageRow>, selection: &mut Selectio
|
|||
|
||||
*selection = Selection::default(); // should already be empty normally
|
||||
|
||||
for (i,p) in packages.iter_mut().enumerate() {
|
||||
for (i, p) in packages.iter_mut().enumerate() {
|
||||
if imported_selection.contains(&p.name) {
|
||||
p.selected = true;
|
||||
selection.selected_packages.push(i);
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ pub mod style;
|
|||
pub mod views;
|
||||
pub mod widgets;
|
||||
|
||||
pub use crate::core::sync::Phone;
|
||||
pub use crate::core::uad_lists::Package;
|
||||
use crate::core::utils::icon;
|
||||
pub use views::about::About as AboutView;
|
||||
pub use views::list::{List as AppsView, Message as AppsMessage};
|
||||
pub use views::settings::{Settings as SettingsView, Message as SettingsMessage};
|
||||
pub use crate::core::uad_lists::Package;
|
||||
pub use crate::core::sync::{Phone};
|
||||
use crate::core::utils::icon;
|
||||
pub use views::settings::{Message as SettingsMessage, Settings as SettingsView};
|
||||
|
||||
use iced::{
|
||||
button, Alignment, Application, Button, Column, Command, Space, Font,
|
||||
Container, Element, Length, Row, Settings, Text, window::Settings as Window,
|
||||
button, window::Settings as Window, Alignment, Application, Button, Column, Command, Container,
|
||||
Element, Font, Length, Row, Settings, Space, Text,
|
||||
};
|
||||
|
||||
pub const ICONS: Font = Font::External {
|
||||
|
|
@ -19,12 +19,11 @@ pub const ICONS: Font = Font::External {
|
|||
bytes: include_bytes!("../../ressources/assets/icons.ttf"),
|
||||
};
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum View {
|
||||
List,
|
||||
About,
|
||||
Settings,
|
||||
Settings,
|
||||
}
|
||||
|
||||
impl Default for View {
|
||||
|
|
@ -78,14 +77,20 @@ impl Application for UadGui {
|
|||
fn update(&mut self, message: Message) -> Command<Message> {
|
||||
match message {
|
||||
Message::Init(_) => {
|
||||
info!("ANDROID_SDK: {} | PHONE: {}", self.phone.android_sdk, self.phone.model);
|
||||
info!(
|
||||
"ANDROID_SDK: {} | PHONE: {}",
|
||||
self.phone.android_sdk, self.phone.model
|
||||
);
|
||||
Command::perform(Self::load_phone_packages(), Message::AppsAction)
|
||||
}
|
||||
Message::AppsRefreshPress => {
|
||||
self.phone = Phone::default();
|
||||
self.settings_view = SettingsView::default();
|
||||
info!("{:-^65}", "-");
|
||||
info!("ANDROID_SDK: {} | PHONE: {}", self.phone.android_sdk, self.phone.model);
|
||||
info!(
|
||||
"ANDROID_SDK: {} | PHONE: {}",
|
||||
self.phone.android_sdk, self.phone.model
|
||||
);
|
||||
self.apps_view = AppsView::default();
|
||||
self.view = View::List;
|
||||
Command::perform(Self::load_phone_packages(), Message::AppsAction)
|
||||
|
|
@ -102,9 +107,10 @@ impl Application for UadGui {
|
|||
self.view = View::Settings;
|
||||
Command::none()
|
||||
}
|
||||
Message::AppsAction(msg) => {
|
||||
self.apps_view.update(&self.settings_view, &mut self.phone, msg).map(Message::AppsAction)
|
||||
}
|
||||
Message::AppsAction(msg) => self
|
||||
.apps_view
|
||||
.update(&self.settings_view, &mut self.phone, msg)
|
||||
.map(Message::AppsAction),
|
||||
Message::SettingsAction(msg) => {
|
||||
self.settings_view.update(msg);
|
||||
Command::none()
|
||||
|
|
@ -153,7 +159,10 @@ impl Application for UadGui {
|
|||
.style(style::NavigationContainer(self.settings_view.theme.palette));
|
||||
|
||||
let main_container = match self.view {
|
||||
View::List => self.apps_view.view(&self.settings_view, &self.phone).map(Message::AppsAction),
|
||||
View::List => self
|
||||
.apps_view
|
||||
.view(&self.settings_view, &self.phone)
|
||||
.map(Message::AppsAction),
|
||||
View::About => self.about_view.view(&self.settings_view),
|
||||
View::Settings => self.settings_view.view().map(Message::SettingsAction),
|
||||
};
|
||||
|
|
@ -166,7 +175,6 @@ impl Application for UadGui {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl UadGui {
|
||||
pub fn start() {
|
||||
let settings: Settings<()> = Settings {
|
||||
|
|
@ -187,7 +195,6 @@ impl UadGui {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fn refresh_icon() -> Text {
|
||||
icon('\u{E900}')
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
use iced::{
|
||||
button, container, scrollable, Background, Color, checkbox,
|
||||
text_input, pick_list,
|
||||
};
|
||||
use crate::core::theme::ColorPalette;
|
||||
use iced::{button, checkbox, container, pick_list, scrollable, text_input, Background, Color};
|
||||
|
||||
pub struct Content(pub ColorPalette);
|
||||
impl container::StyleSheet for Content {
|
||||
|
|
@ -80,7 +77,6 @@ impl button::StyleSheet for RefreshButton {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub enum PackageButton {
|
||||
Uninstall(ColorPalette),
|
||||
Restore(ColorPalette),
|
||||
|
|
@ -137,8 +133,8 @@ impl button::StyleSheet for PackageButton {
|
|||
match self {
|
||||
Self::Restore(palette) => button::Style {
|
||||
background: Some(Background::Color(Color {
|
||||
a: 0.05,
|
||||
..palette.normal.primary
|
||||
a: 0.05,
|
||||
..palette.normal.primary
|
||||
})),
|
||||
text_color: Color {
|
||||
a: 0.50,
|
||||
|
|
@ -148,8 +144,8 @@ impl button::StyleSheet for PackageButton {
|
|||
},
|
||||
Self::Uninstall(palette) => button::Style {
|
||||
background: Some(Background::Color(Color {
|
||||
a: 0.01,
|
||||
..palette.bright.error
|
||||
a: 0.01,
|
||||
..palette.bright.error
|
||||
})),
|
||||
text_color: Color {
|
||||
a: 0.50,
|
||||
|
|
@ -184,12 +180,12 @@ impl button::StyleSheet for PackageRow {
|
|||
}
|
||||
}
|
||||
fn pressed(&self) -> button::Style {
|
||||
button::Style {
|
||||
background: Some(Background::Color(Color::from_rgb(0.35, 0.43, 0.46))),
|
||||
text_color: self.0.bright.primary,
|
||||
..self.active()
|
||||
}
|
||||
button::Style {
|
||||
background: Some(Background::Color(Color::from_rgb(0.35, 0.43, 0.46))),
|
||||
text_color: self.0.bright.primary,
|
||||
..self.active()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Description(pub ColorPalette);
|
||||
|
|
@ -276,10 +272,9 @@ impl scrollable::StyleSheet for Scrollable {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub enum SelectionCheckBox {
|
||||
Enabled(ColorPalette),
|
||||
Disabled(ColorPalette)
|
||||
Disabled(ColorPalette),
|
||||
}
|
||||
|
||||
impl checkbox::StyleSheet for SelectionCheckBox {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::gui::style;
|
||||
use crate::gui::Message;
|
||||
use crate::gui::views::settings::Settings;
|
||||
use crate::gui::Message;
|
||||
use iced::{Alignment, Column, Container, Element, Length, Text};
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
|
|
@ -25,4 +25,4 @@ impl About {
|
|||
.style(style::Content(settings.theme.palette))
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,39 @@
|
|||
use crate::gui::style;
|
||||
use crate::core::sync::{Phone, action_handler, User};
|
||||
use crate::core::sync::{action_handler, Phone, User};
|
||||
use crate::core::uad_lists::{
|
||||
UadList, PackageState, Package, Removal, Opposite, load_debloat_lists
|
||||
load_debloat_lists, Opposite, Package, PackageState, Removal, UadList,
|
||||
};
|
||||
use crate::core::utils::{
|
||||
import_selection, export_selection, update_selection_count, fetch_packages,
|
||||
export_selection, fetch_packages, import_selection, update_selection_count,
|
||||
};
|
||||
use std::{collections::HashMap};
|
||||
use static_init::{dynamic};
|
||||
use crate::gui::style;
|
||||
use static_init::dynamic;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::gui::views::settings::Settings;
|
||||
use crate::gui::widgets::package_row::{ PackageRow, Message as RowMessage };
|
||||
use crate::gui::widgets::package_row::{Message as RowMessage, PackageRow};
|
||||
use iced::{
|
||||
scrollable, Alignment, alignment, Column, Container, Element, Space,
|
||||
Length, Row, Scrollable, Text, text_input, TextInput, Command,//Svg,
|
||||
PickList, pick_list, Button, button,
|
||||
alignment,
|
||||
button,
|
||||
pick_list,
|
||||
scrollable,
|
||||
text_input,
|
||||
Alignment,
|
||||
Button,
|
||||
Column,
|
||||
Command, //Svg,
|
||||
Container,
|
||||
Element,
|
||||
Length,
|
||||
PickList,
|
||||
Row,
|
||||
Scrollable,
|
||||
Space,
|
||||
Text,
|
||||
TextInput,
|
||||
};
|
||||
|
||||
|
||||
#[dynamic]
|
||||
static UAD_LISTS: HashMap<String, Package> = load_debloat_lists();
|
||||
static UAD_LISTS: HashMap<String, Package> = load_debloat_lists();
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Selection {
|
||||
|
|
@ -60,7 +74,6 @@ pub struct List {
|
|||
description: String,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Message {
|
||||
SearchInputChanged(String),
|
||||
|
|
@ -76,22 +89,27 @@ pub enum Message {
|
|||
ExportedSelection(Result<bool, String>),
|
||||
}
|
||||
|
||||
|
||||
impl List {
|
||||
pub fn update(&mut self, settings: &Settings, phone: &mut Phone, message: Message) -> Command<Message> {
|
||||
let i_user = &self.selected_user.unwrap_or(User {id: 0, index: 0}).index; // for readability
|
||||
pub fn update(
|
||||
&mut self,
|
||||
settings: &Settings,
|
||||
phone: &mut Phone,
|
||||
message: Message,
|
||||
) -> Command<Message> {
|
||||
let i_user = &self.selected_user.unwrap_or(User { id: 0, index: 0 }).index; // for readability
|
||||
match message {
|
||||
Message::LoadPackages => {
|
||||
self.selected_package_state = Some(PackageState::Enabled);
|
||||
self.selected_list = Some(UadList::All);
|
||||
self.selected_removal = Some(Removal::Recommended);
|
||||
self.selected_user = Some(User {id: 0, index: 0});
|
||||
self.selected_user = Some(User { id: 0, index: 0 });
|
||||
|
||||
match phone.user_list.len() {
|
||||
0|1 => self.phone_packages.push(fetch_packages(&UAD_LISTS, &None)),
|
||||
0 | 1 => self.phone_packages.push(fetch_packages(&UAD_LISTS, &None)),
|
||||
_ => {
|
||||
for user in &phone.user_list {
|
||||
self.phone_packages.push(fetch_packages(&UAD_LISTS, &Some(user)));
|
||||
self.phone_packages
|
||||
.push(fetch_packages(&UAD_LISTS, &Some(user)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -111,7 +129,6 @@ impl List {
|
|||
Command::none()
|
||||
}
|
||||
Message::ListSelected(list) => {
|
||||
|
||||
self.selected_list = Some(list);
|
||||
Self::filter_package_lists(self);
|
||||
Command::none()
|
||||
|
|
@ -127,77 +144,97 @@ impl List {
|
|||
Command::none()
|
||||
}
|
||||
Message::List(i, row_message) => {
|
||||
self.phone_packages[*i_user][i].update(row_message.clone()).map(move |row_message| Message::List(i, row_message));
|
||||
|
||||
self.phone_packages[*i_user][i]
|
||||
.update(row_message.clone())
|
||||
.map(move |row_message| Message::List(i, row_message));
|
||||
|
||||
match row_message {
|
||||
RowMessage::ToggleSelection(toggle) => {
|
||||
if self.phone_packages[*i_user][i].removal == Removal::Unsafe && !settings.expert_mode {
|
||||
if self.phone_packages[*i_user][i].removal == Removal::Unsafe
|
||||
&& !settings.expert_mode
|
||||
{
|
||||
self.phone_packages[*i_user][i].selected = false;
|
||||
} else {
|
||||
self.phone_packages[*i_user][i].selected = toggle;
|
||||
|
||||
if self.phone_packages[*i_user][i].selected {
|
||||
self.selection.selected_packages.push(i);
|
||||
update_selection_count(&mut self.selection, self.phone_packages[*i_user][i].state, true);
|
||||
update_selection_count(
|
||||
&mut self.selection,
|
||||
self.phone_packages[*i_user][i].state,
|
||||
true,
|
||||
);
|
||||
} else {
|
||||
self.selection.selected_packages.drain_filter(|s_i| *s_i == i);
|
||||
update_selection_count(&mut self.selection, self.phone_packages[*i_user][i].state, false);
|
||||
self.selection
|
||||
.selected_packages
|
||||
.drain_filter(|s_i| *s_i == i);
|
||||
update_selection_count(
|
||||
&mut self.selection,
|
||||
self.phone_packages[*i_user][i].state,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
RowMessage::ActionPressed => {
|
||||
let success = action_handler(
|
||||
&self.selected_user.unwrap(),
|
||||
&self.phone_packages[*i_user][i],
|
||||
phone,
|
||||
settings,
|
||||
).unwrap_or_else(|err| err);
|
||||
|
||||
&self.selected_user.unwrap(),
|
||||
&self.phone_packages[*i_user][i],
|
||||
phone,
|
||||
settings,
|
||||
)
|
||||
.unwrap_or_else(|err| err);
|
||||
|
||||
if success {
|
||||
let i = self.phone_packages[*i_user]
|
||||
.iter()
|
||||
.position(|p| p.name == self.phone_packages[*i_user][i].name)
|
||||
.unwrap();
|
||||
if self.phone_packages[*i_user][i].selected {
|
||||
update_selection_count(&mut self.selection, self.phone_packages[*i_user][i].state, false);
|
||||
update_selection_count(
|
||||
&mut self.selection,
|
||||
self.phone_packages[*i_user][i].state,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
self.phone_packages[*i_user][i].state = self.phone_packages[*i_user][i].state
|
||||
|
||||
self.phone_packages[*i_user][i].state = self.phone_packages[*i_user][i]
|
||||
.state
|
||||
.opposite(settings.disable_mode);
|
||||
|
||||
if settings.multi_user_mode {
|
||||
for u in &phone.user_list {
|
||||
self.phone_packages[u.index][i].state = self.phone_packages[*i_user][i].state;
|
||||
self.phone_packages[u.index][i].state =
|
||||
self.phone_packages[*i_user][i].state;
|
||||
self.phone_packages[u.index][i].selected = false;
|
||||
}
|
||||
}
|
||||
self.selection.selected_packages.drain_filter(|s_i| *s_i == i);
|
||||
self.selection
|
||||
.selected_packages
|
||||
.drain_filter(|s_i| *s_i == i);
|
||||
self.phone_packages[*i_user][i].selected = false;
|
||||
Self::filter_package_lists(self);
|
||||
}
|
||||
},
|
||||
}
|
||||
RowMessage::PackagePressed => {
|
||||
self.description = self.phone_packages[*i_user][i].clone().description;
|
||||
},
|
||||
}
|
||||
}
|
||||
Command::none()
|
||||
},
|
||||
}
|
||||
Message::ApplyActionOnSelection(action) => {
|
||||
let mut selected_packages = self.selection.selected_packages.clone();
|
||||
|
||||
|
||||
match action {
|
||||
Action::Remove => {
|
||||
selected_packages.drain_filter(
|
||||
|i|
|
||||
selected_packages.drain_filter(|i| {
|
||||
self.phone_packages[*i_user][*i].state != PackageState::Enabled
|
||||
);
|
||||
});
|
||||
}
|
||||
Action::Restore => {
|
||||
selected_packages.drain_filter(
|
||||
|i|
|
||||
selected_packages.drain_filter(|i| {
|
||||
self.phone_packages[*i_user][*i].state == PackageState::Enabled
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -206,52 +243,62 @@ impl List {
|
|||
&self.selected_user.unwrap(),
|
||||
&self.phone_packages[*i_user][i],
|
||||
phone,
|
||||
settings
|
||||
).unwrap_or_else(|err| err);
|
||||
|
||||
settings,
|
||||
)
|
||||
.unwrap_or_else(|err| err);
|
||||
|
||||
if success {
|
||||
update_selection_count(
|
||||
&mut self.selection,
|
||||
self.phone_packages[*i_user][i].state,
|
||||
false
|
||||
&mut self.selection,
|
||||
self.phone_packages[*i_user][i].state,
|
||||
false,
|
||||
);
|
||||
if !settings.multi_user_mode {
|
||||
self.phone_packages[*i_user][i].state = self.phone_packages[*i_user][i].state
|
||||
self.phone_packages[*i_user][i].state = self.phone_packages[*i_user][i]
|
||||
.state
|
||||
.opposite(settings.disable_mode);
|
||||
self.phone_packages[*i_user][i].selected = false;
|
||||
}
|
||||
|
||||
for u in &phone.user_list {
|
||||
self.phone_packages[u.index][i].state = self.phone_packages[u.index][i].state
|
||||
self.phone_packages[u.index][i].state = self.phone_packages[u.index][i]
|
||||
.state
|
||||
.opposite(settings.disable_mode);
|
||||
self.phone_packages[u.index][i].selected = false;
|
||||
}
|
||||
self.selection.selected_packages.drain_filter(|s_i| *s_i == i);
|
||||
self.selection
|
||||
.selected_packages
|
||||
.drain_filter(|s_i| *s_i == i);
|
||||
}
|
||||
}
|
||||
Self::filter_package_lists(self);
|
||||
Command::none()
|
||||
},
|
||||
}
|
||||
Message::SelectAllPressed => {
|
||||
for i in self.filtered_packages.clone() {
|
||||
self.phone_packages[*i_user][i].selected = true;
|
||||
if !self.selection.selected_packages.contains(&i) {
|
||||
self.selection.selected_packages.push(i);
|
||||
update_selection_count(&mut self.selection, self.phone_packages[*i_user][i].state, true);
|
||||
update_selection_count(
|
||||
&mut self.selection,
|
||||
self.phone_packages[*i_user][i].state,
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
Command::none()
|
||||
},
|
||||
Message::ExportSelectionPressed => {
|
||||
Command::perform(export_selection(self.phone_packages[*i_user].clone()), Message::ExportedSelection)
|
||||
},
|
||||
}
|
||||
Message::ExportSelectionPressed => Command::perform(
|
||||
export_selection(self.phone_packages[*i_user].clone()),
|
||||
Message::ExportedSelection,
|
||||
),
|
||||
Message::ExportedSelection(export) => {
|
||||
match export {
|
||||
Ok(_) => info!("Selection exported"),
|
||||
Err(err) => error!("Selection export: {}", err),
|
||||
};
|
||||
Command::none()
|
||||
},
|
||||
Command::none()
|
||||
}
|
||||
Message::UserSelected(user) => {
|
||||
for p in &mut self.phone_packages[*i_user] {
|
||||
p.selected = false;
|
||||
|
|
@ -262,7 +309,7 @@ impl List {
|
|||
}
|
||||
self.filtered_packages = (0..self.phone_packages[user.index].len()).collect();
|
||||
Self::filter_package_lists(self);
|
||||
Command::none()
|
||||
Command::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -279,42 +326,41 @@ impl List {
|
|||
.style(style::SearchInput(settings.theme.palette));
|
||||
|
||||
// let package_amount = Text::new(format!("{} packages found", packages.len()));
|
||||
|
||||
|
||||
let user_picklist = PickList::new(
|
||||
&mut self.user_picklist,
|
||||
phone.user_list.clone(),
|
||||
self.selected_user,
|
||||
Message::UserSelected,
|
||||
)
|
||||
.width(Length::Units(85))
|
||||
.style(style::PickList(settings.theme.palette));
|
||||
&mut self.user_picklist,
|
||||
phone.user_list.clone(),
|
||||
self.selected_user,
|
||||
Message::UserSelected,
|
||||
)
|
||||
.width(Length::Units(85))
|
||||
.style(style::PickList(settings.theme.palette));
|
||||
|
||||
let divider = Space::new(Length::Fill, Length::Shrink);
|
||||
|
||||
let list_picklist = PickList::new(
|
||||
&mut self.list_picklist,
|
||||
&UadList::ALL[..],
|
||||
self.selected_list,
|
||||
Message::ListSelected,
|
||||
)
|
||||
.style(style::PickList(settings.theme.palette));
|
||||
&mut self.list_picklist,
|
||||
&UadList::ALL[..],
|
||||
self.selected_list,
|
||||
Message::ListSelected,
|
||||
)
|
||||
.style(style::PickList(settings.theme.palette));
|
||||
|
||||
let package_state_picklist = PickList::new(
|
||||
&mut self.package_state_picklist,
|
||||
&PackageState::ALL[..],
|
||||
self.selected_package_state,
|
||||
Message::PackageStateSelected,
|
||||
)
|
||||
.style(style::PickList(settings.theme.palette));
|
||||
|
||||
&mut self.package_state_picklist,
|
||||
&PackageState::ALL[..],
|
||||
self.selected_package_state,
|
||||
Message::PackageStateSelected,
|
||||
)
|
||||
.style(style::PickList(settings.theme.palette));
|
||||
|
||||
let removal_picklist = PickList::new(
|
||||
&mut self.removal_picklist,
|
||||
&Removal::ALL[..],
|
||||
self.selected_removal,
|
||||
Message::RemovalSelected,
|
||||
)
|
||||
.style(style::PickList(settings.theme.palette));
|
||||
&mut self.removal_picklist,
|
||||
&Removal::ALL[..],
|
||||
self.selected_removal,
|
||||
Message::RemovalSelected,
|
||||
)
|
||||
.style(style::PickList(settings.theme.palette));
|
||||
|
||||
let control_panel = Row::new()
|
||||
.width(Length::Fill)
|
||||
|
|
@ -330,9 +376,12 @@ impl List {
|
|||
let packages = self.phone_packages[self.selected_user.unwrap().index]
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.filter(|(i,_)| self.filtered_packages.contains(i))
|
||||
.fold(Column::new().spacing(6), |col, (i,p)| {
|
||||
col.push(p.view(settings, phone).map(move |msg| Message::List(i, msg)))
|
||||
.filter(|(i, _)| self.filtered_packages.contains(i))
|
||||
.fold(Column::new().spacing(6), |col, (i, p)| {
|
||||
col.push(
|
||||
p.view(settings, phone)
|
||||
.map(move |msg| Message::List(i, msg)),
|
||||
)
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
@ -363,38 +412,56 @@ impl List {
|
|||
.width(Length::Fill)
|
||||
.style(style::Description(settings.theme.palette));
|
||||
|
||||
let restore_action = if settings.disable_mode {"Enable/Restore"} else {"Restore"};
|
||||
let remove_action = if settings.disable_mode {"Disable"} else {"Uninstall"};
|
||||
let restore_action = if settings.disable_mode {
|
||||
"Enable/Restore"
|
||||
} else {
|
||||
"Restore"
|
||||
};
|
||||
let remove_action = if settings.disable_mode {
|
||||
"Disable"
|
||||
} else {
|
||||
"Uninstall"
|
||||
};
|
||||
|
||||
let apply_restore_selection = Button::new(
|
||||
&mut self.apply_restore_selection,
|
||||
Text::new(format!("{} selection ({})",
|
||||
restore_action,
|
||||
self.selection.uninstalled + self.selection.disabled)
|
||||
)
|
||||
)
|
||||
.on_press(Message::ApplyActionOnSelection(Action::Restore))
|
||||
.padding(5)
|
||||
.style(style::PrimaryButton(settings.theme.palette));
|
||||
&mut self.apply_restore_selection,
|
||||
Text::new(format!(
|
||||
"{} selection ({})",
|
||||
restore_action,
|
||||
self.selection.uninstalled + self.selection.disabled
|
||||
)),
|
||||
)
|
||||
.on_press(Message::ApplyActionOnSelection(Action::Restore))
|
||||
.padding(5)
|
||||
.style(style::PrimaryButton(settings.theme.palette));
|
||||
|
||||
let apply_remove_selection = Button::new(
|
||||
&mut self.apply_remove_selection,
|
||||
Text::new(format!("{} selection ({})", remove_action, self.selection.enabled)))
|
||||
.on_press(Message::ApplyActionOnSelection(Action::Remove))
|
||||
.padding(5)
|
||||
.style(style::PrimaryButton(settings.theme.palette));
|
||||
&mut self.apply_remove_selection,
|
||||
Text::new(format!(
|
||||
"{} selection ({})",
|
||||
remove_action, self.selection.enabled
|
||||
)),
|
||||
)
|
||||
.on_press(Message::ApplyActionOnSelection(Action::Remove))
|
||||
.padding(5)
|
||||
.style(style::PrimaryButton(settings.theme.palette));
|
||||
|
||||
let select_all_btn = Button::new(&mut self.select_all_btn_state, Text::new("Select all"))
|
||||
.padding(5)
|
||||
.on_press(Message::SelectAllPressed)
|
||||
.style(style::PrimaryButton(settings.theme.palette));
|
||||
let select_all_btn =
|
||||
Button::new(&mut self.select_all_btn_state, Text::new("Select all"))
|
||||
.padding(5)
|
||||
.on_press(Message::SelectAllPressed)
|
||||
.style(style::PrimaryButton(settings.theme.palette));
|
||||
|
||||
let export_selection_btn = Button::new(
|
||||
&mut self.export_selection_btn_state,
|
||||
Text::new(format!("Export current selection ({})", self.selection.selected_packages.len())))
|
||||
.padding(5)
|
||||
.on_press(Message::ExportSelectionPressed)
|
||||
.style(style::PrimaryButton(settings.theme.palette));
|
||||
&mut self.export_selection_btn_state,
|
||||
Text::new(format!(
|
||||
"Export current selection ({})",
|
||||
self.selection.selected_packages.len()
|
||||
)),
|
||||
)
|
||||
.padding(5)
|
||||
.on_press(Message::ExportSelectionPressed)
|
||||
.style(style::PrimaryButton(settings.theme.palette));
|
||||
|
||||
let action_row = Row::new()
|
||||
.width(Length::Fill)
|
||||
|
|
@ -427,7 +494,6 @@ impl List {
|
|||
}
|
||||
|
||||
fn filter_package_lists(&mut self) {
|
||||
|
||||
let list_filter: UadList = self.selected_list.unwrap();
|
||||
let package_filter: PackageState = self.selected_package_state.unwrap();
|
||||
let removal_filter: Removal = self.selected_removal.unwrap();
|
||||
|
|
@ -435,19 +501,17 @@ impl List {
|
|||
self.filtered_packages = self.phone_packages[self.selected_user.unwrap().index]
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(
|
||||
|(_,p)|
|
||||
(list_filter == UadList::All || p.uad_list == list_filter) &&
|
||||
(package_filter == PackageState::All || p.state == package_filter) &&
|
||||
(removal_filter == Removal::All || p.removal == removal_filter) &&
|
||||
(self.input_value.is_empty() || p.name.contains(&self.input_value))
|
||||
)
|
||||
.map(|(i,_)| i)
|
||||
.filter(|(_, p)| {
|
||||
(list_filter == UadList::All || p.uad_list == list_filter)
|
||||
&& (package_filter == PackageState::All || p.state == package_filter)
|
||||
&& (removal_filter == Removal::All || p.removal == removal_filter)
|
||||
&& (self.input_value.is_empty() || p.name.contains(&self.input_value))
|
||||
})
|
||||
.map(|(i, _)| i)
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn loading_data<'a>(settings: &Settings) -> Element<'a, Message> {
|
||||
Container::new(
|
||||
Text::new("Pulling packages from the phone. Please wait...")
|
||||
|
|
@ -461,4 +525,4 @@ fn loading_data<'a>(settings: &Settings) -> Element<'a, Message> {
|
|||
.center_x()
|
||||
.style(style::Content(settings.theme.palette))
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
pub mod about;
|
||||
pub mod list;
|
||||
pub mod settings;
|
||||
pub mod about;
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
use crate::gui::style;
|
||||
use crate::core::theme::{Theme};
|
||||
use crate::core::sync::get_android_sdk;
|
||||
use iced::{Checkbox, Column, Container, Element, Length, Text, Space,
|
||||
pick_list, PickList,
|
||||
};
|
||||
use crate::core::theme::Theme;
|
||||
use crate::gui::style;
|
||||
use iced::{pick_list, Checkbox, Column, Container, Element, Length, PickList, Space, Text};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Settings {
|
||||
|
|
@ -21,7 +19,7 @@ impl Default for Settings {
|
|||
disable_mode: get_android_sdk() < 26,
|
||||
multi_user_mode: get_android_sdk() > 21,
|
||||
theme: Theme::lupin(),
|
||||
theme_picklist: pick_list::State::default()
|
||||
theme_picklist: pick_list::State::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -38,17 +36,26 @@ impl Settings {
|
|||
pub fn update(&mut self, msg: Message) {
|
||||
match msg {
|
||||
Message::ExpertMode(toggled) => {
|
||||
info!("Expert mode {}", if toggled {"enabled"} else {"disabled"});
|
||||
info!(
|
||||
"Expert mode {}",
|
||||
if toggled { "enabled" } else { "disabled" }
|
||||
);
|
||||
self.expert_mode = toggled;
|
||||
},
|
||||
}
|
||||
Message::DisableMode(toggled) => {
|
||||
info!("Disable mode {}", if toggled {"enabled"} else {"disabled"});
|
||||
info!(
|
||||
"Disable mode {}",
|
||||
if toggled { "enabled" } else { "disabled" }
|
||||
);
|
||||
self.disable_mode = toggled;
|
||||
},
|
||||
}
|
||||
Message::MultiUserMode(toggled) => {
|
||||
info!("Multi-user mode {}", if toggled {"enabled"} else {"disabled"});
|
||||
info!(
|
||||
"Multi-user mode {}",
|
||||
if toggled { "enabled" } else { "disabled" }
|
||||
);
|
||||
self.multi_user_mode = toggled;
|
||||
},
|
||||
}
|
||||
Message::ApplyTheme(theme) => {
|
||||
self.theme = theme;
|
||||
}
|
||||
|
|
@ -63,19 +70,20 @@ impl Settings {
|
|||
Theme::all(),
|
||||
Some(self.theme.clone()),
|
||||
Message::ApplyTheme,
|
||||
)
|
||||
.style(style::PickList(self.theme.palette));
|
||||
)
|
||||
.style(style::PickList(self.theme.palette));
|
||||
|
||||
let uad_category_text = Text::new("UAD").size(25);
|
||||
|
||||
let expert_mode_descr = Text::new("Most of unsafe packages are known to bootloop the device if removed.")
|
||||
.size(15)
|
||||
.color(self.theme.palette.normal.surface);
|
||||
let expert_mode_descr =
|
||||
Text::new("Most of unsafe packages are known to bootloop the device if removed.")
|
||||
.size(15)
|
||||
.color(self.theme.palette.normal.surface);
|
||||
|
||||
let expert_mode_checkbox = Checkbox::new(
|
||||
self.expert_mode,
|
||||
"Allow to uninstall packages marked as \"unsafe\" (I KNOW WHAT I AM DOING)",
|
||||
Message::ExpertMode
|
||||
self.expert_mode,
|
||||
"Allow to uninstall packages marked as \"unsafe\" (I KNOW WHAT I AM DOING)",
|
||||
Message::ExpertMode,
|
||||
);
|
||||
|
||||
let disable_mode_descr = Text::new("Default mode on older phone (< Android 8.0) where uninstalled packages can't be restored.")
|
||||
|
|
@ -83,19 +91,20 @@ impl Settings {
|
|||
.color(self.theme.palette.normal.surface);
|
||||
|
||||
let disable_mode_checkbox = Checkbox::new(
|
||||
self.disable_mode,
|
||||
self.disable_mode,
|
||||
"Clear and disable packages instead of uninstalling them",
|
||||
Message::DisableMode
|
||||
Message::DisableMode,
|
||||
);
|
||||
|
||||
let multi_user_mode_descr = Text::new("Disabling this setting will typically prevent affecting your work profile")
|
||||
.size(15)
|
||||
.color(self.theme.palette.normal.surface);
|
||||
let multi_user_mode_descr =
|
||||
Text::new("Disabling this setting will typically prevent affecting your work profile")
|
||||
.size(15)
|
||||
.color(self.theme.palette.normal.surface);
|
||||
|
||||
let multi_user_mode_checkbox = Checkbox::new(
|
||||
self.multi_user_mode,
|
||||
self.multi_user_mode,
|
||||
"Affect all the users of the phone (not only the selected user)",
|
||||
Message::MultiUserMode
|
||||
Message::MultiUserMode,
|
||||
);
|
||||
|
||||
let content = Column::new()
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
pub mod package_row;
|
||||
pub mod package_row;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
use crate::core::uad_lists::{UadList, PackageState, Removal};
|
||||
use crate::core::sync::Phone;
|
||||
use crate::core::uad_lists::{PackageState, Removal, UadList};
|
||||
|
||||
use crate::gui::style;
|
||||
use crate::gui::views::settings::Settings;
|
||||
|
||||
use iced::{
|
||||
Alignment, alignment, Command, Element, Space, Length, Row, Text, Button,
|
||||
button, Checkbox,
|
||||
alignment, button, Alignment, Button, Checkbox, Command, Element, Length, Row, Space, Text,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -36,7 +35,6 @@ impl PackageRow {
|
|||
uad_list: UadList,
|
||||
removal: Removal,
|
||||
selected: bool,
|
||||
|
||||
) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
|
|
@ -62,10 +60,13 @@ impl PackageRow {
|
|||
let action_btn;
|
||||
let selection_checkbox;
|
||||
|
||||
|
||||
match self.state {
|
||||
PackageState::Enabled => {
|
||||
action_text = if settings.disable_mode { "Disable" } else { "Uninstall" };
|
||||
action_text = if settings.disable_mode {
|
||||
"Disable"
|
||||
} else {
|
||||
"Uninstall"
|
||||
};
|
||||
button_style = style::PackageButton::Uninstall(settings.theme.palette);
|
||||
}
|
||||
PackageState::Disabled => {
|
||||
|
|
@ -81,13 +82,11 @@ impl PackageRow {
|
|||
button_style = style::PackageButton::Restore(settings.theme.palette);
|
||||
warn!("Incredible! Something impossible happenned!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (self.state != PackageState::Uninstalled && settings.expert_mode) ||
|
||||
(self.removal != Removal::Unsafe && phone.android_sdk >= 26)
|
||||
if (self.state != PackageState::Uninstalled && settings.expert_mode)
|
||||
|| (self.removal != Removal::Unsafe && phone.android_sdk >= 26)
|
||||
{
|
||||
|
||||
selection_checkbox = Checkbox::new(self.selected, "", Message::ToggleSelection)
|
||||
.style(style::SelectionCheckBox::Enabled(settings.theme.palette));
|
||||
|
||||
|
|
@ -96,7 +95,6 @@ impl PackageRow {
|
|||
Text::new(action_text).horizontal_alignment(alignment::Horizontal::Center),
|
||||
)
|
||||
.on_press(Message::ActionPressed);
|
||||
|
||||
} else {
|
||||
selection_checkbox = Checkbox::new(self.selected, "", Message::ToggleSelection)
|
||||
.style(style::SelectionCheckBox::Disabled(settings.theme.palette));
|
||||
|
|
@ -108,24 +106,22 @@ impl PackageRow {
|
|||
}
|
||||
|
||||
Row::new()
|
||||
.push(Button::new(
|
||||
&mut self.package_btn_state,
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(selection_checkbox)
|
||||
.push(Text::new(&self.name).width(Length::FillPortion(8)))
|
||||
.push(action_btn.width(Length::FillPortion(1))
|
||||
.style(button_style)
|
||||
)
|
||||
.push(
|
||||
Button::new(
|
||||
&mut self.package_btn_state,
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(selection_checkbox)
|
||||
.push(Text::new(&self.name).width(Length::FillPortion(8)))
|
||||
.push(action_btn.width(Length::FillPortion(1)).style(button_style)),
|
||||
)
|
||||
.padding(8)
|
||||
.style(style::PackageRow(settings.theme.palette))
|
||||
.width(Length::Fill)
|
||||
.on_press(Message::PackagePressed)
|
||||
|
||||
.on_press(Message::PackagePressed),
|
||||
)
|
||||
.push(Space::with_width(Length::Units(15)))
|
||||
.align_items(Alignment::Center)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
18
src/main.rs
18
src/main.rs
|
|
@ -1,10 +1,14 @@
|
|||
#![windows_subsystem = "windows"]
|
||||
#![feature(drain_filter)]
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::{fs::OpenOptions, fmt::Arguments};
|
||||
use fern::{FormatCallback, colors::{Color, ColoredLevelConfig}};
|
||||
use fern::{
|
||||
colors::{Color, ColoredLevelConfig},
|
||||
FormatCallback,
|
||||
};
|
||||
use log::Record;
|
||||
use std::{fmt::Arguments, fs::OpenOptions};
|
||||
|
||||
mod core;
|
||||
mod gui;
|
||||
|
|
@ -15,7 +19,6 @@ fn main() {
|
|||
}
|
||||
|
||||
pub fn setup_logger() -> Result<(), fern::InitError> {
|
||||
|
||||
let colors = ColoredLevelConfig::new().info(Color::Green);
|
||||
|
||||
let make_formatter = |use_colors: bool| {
|
||||
|
|
@ -29,10 +32,7 @@ pub fn setup_logger() -> Result<(), fern::InitError> {
|
|||
format!("{:5}", record.level().to_string())
|
||||
},
|
||||
record.file().unwrap_or("?"),
|
||||
record
|
||||
.line()
|
||||
.map(|l| l.to_string())
|
||||
.unwrap_or_default(),
|
||||
record.line().map(|l| l.to_string()).unwrap_or_default(),
|
||||
message
|
||||
))
|
||||
}
|
||||
|
|
@ -64,4 +64,4 @@ pub fn setup_logger() -> Result<(), fern::InitError> {
|
|||
.apply()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue