Merge branch 'main' into patch-2

This commit is contained in:
qumuq-til 2024-03-18 17:22:14 +03:00 committed by GitHub
commit d7bbed124d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 894 additions and 873 deletions

1241
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -29,7 +29,7 @@ toml = "^0"
dirs = "^5.0.0"
ureq = { version = "*", features = ["json"] }
retry = "^2.0.0"
iced = { version = "^0.10.0", features = ["advanced", "image"] }
iced = { version = "^0.12.0", features = ["advanced", "image"] }
[target.'cfg(not(target_os = "windows"))'.dependencies]
flate2 = { version = "^1", optional = true }

View file

@ -3543,7 +3543,7 @@
},
"com.knox.vpn.proxyhandler": {
"list": "Oem",
"description": "Third-party package that provides caller profile information to help consumers identify incoming calls and block unwanted ones.\nhttps://en.wikipedia.org/wiki/Hiya_(company)\nhttps://hiya.com/\nNOTE: Never trust a company that promotes spam blocking features.\nhttps://itmunch.com/robocall-caught-sending-customers-confidential-data-without-consent/\nHave a look at their privacy policy. It's... pretty scary: https://hiya.com/fr/hiya-data-policy\nNeeded for Samsung Smart Call (com.samsung.android.smartcallprovider)\nSamsung Knox allows business and personal content to \"securely\" coexist on the same handset.\nThis package handles proxies alongside KNOX.",
"description": "Samsung Knox allows business and personal content to \"securely\" coexist on the same handset.\nThis package handles proxies alongside KNOX.",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -3999,7 +3999,7 @@
},
"com.samsung.android.app.sharelive": {
"list": "Oem",
"description": "Samsung Quick Share from the Galaxy Store\nDoesn't break anything if you remove it. But obviously you can't use Quick Share.",
"description": "Samsung Quick Share (from the Galaxy Store)\nBreaks Quick Share if you remove it.",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -4111,7 +4111,7 @@
},
"com.samsung.android.easysetup": {
"list": "Oem",
"description": "Samsung Connect Easy Setup (now SmartThings)\nUsed to connect every Samsung device you have in your house.\nWhat's weird is that Galaxy S10 has this package (available nowhere) but S9 has com.samsung.android.oneconnect\navailable on the Playstore (https://play.google.com/store/apps/details?id=com.samsung.android.oneconnect)\n#\nNeeds \"com.samsung.android.beaconmanager\" to be useful.\n",
"description": "Samsung Nearby device scanning\nRequires \"com.samsung.android.beaconmanager\" to be useful.",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -4319,7 +4319,7 @@
},
"com.samsung.android.mdx.kit": {
"list": "Oem",
"description": "MDE Service Framework / Quick Share Connectivity\nMDE = Multi Devices Experience (https://www.samsung.com/levant/multi-device-experience/)\nFramework for IoT stuff.\nAsks for a LOT of dangerous permissions\nInteracts with \"com.samsung.android.mobileservice\" and \"com.osp.app.signin\"\n",
"description": "Quick Share Connectivity / MDE Service Framework\nMDX = Multi Devices Experience (https://www.samsung.com/levant/multi-device-experience/)\nFramework for IoT stuff.\nAsks for a LOT of dangerous permissions\nInteracts with \"com.samsung.android.mobileservice\" and \"com.osp.app.signin\"\n",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -4335,7 +4335,7 @@
},
"com.samsung.android.mobileservice": {
"list": "Oem",
"description": "Group Sharing (earlier Samsung Experience Service, before One UI 1.0). The legacy version was similar to Samsung Core Services (citation needed).\nCan remove safely if you don't use any group sharing features (shared albums in gallery, etc.).\nHandles your Samsung account and is needed to use some Samsung apps features.\nIt allows you to use multiple Samsung apps, such as Samsung Health, Samsung Pay, Galaxy Apps, Samsung Members, and SmartThings, \nwith your Samsung account credentials.\nhttps://techshift.net/what-is-samsung-group-sharing/",
"description": "Group Sharing (earlier Samsung Experience Service). The legacy version was similar to Samsung Core Services (citation needed).\nCan remove safely if you don't use any group sharing features (shared albums in gallery, etc.).\nHandles your Samsung account and is needed to use some Samsung apps features.\nIt allows you to use Samsung apps, such as Samsung Health, Samsung Pay, Galaxy Apps, Samsung Members, and SmartThings with your Samsung account credentials.\nhttps://techshift.net/what-is-samsung-group-sharing/",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -5098,11 +5098,11 @@
},
"com.samsung.ucs.agent.boot": {
"list": "Oem",
"description": "Boot agent\nUCS is a company which has partnered with Samsung to provide licenses for Samsung Knox\nhttps://www.ucssolutions.com/blog/samsung-knox/\nI don't have precise information about the package itself but there are chances that it verifies some files on boot. If theses files are not verified\nthen it prevent the phone to boot \n",
"description": "Boot agent\nUCS is a company which has partnered with Samsung to provide licenses for Samsung Knox\nhttps://www.ucssolutions.com/blog/samsung-knox/\nI don't have precise information about the package itself but there are chances that it verifies some files on boot. If these files are not verified then it may prevent the phone from booting.",
"dependencies": [],
"neededBy": [],
"labels": [],
"removal": "Recommended"
"removal": "Unsafe"
},
"com.samsung.ucs.agent.ese": {
"list": "Oem",
@ -5178,7 +5178,7 @@
},
"com.sec.android.app.bluetoothtest": {
"list": "Oem",
"description": "Bluetooth Test\nHidden feature accessible by entering *#*#232331#*#* in the samsung dialer\nWas calling home back in 2015 (https://forum.xda-developers.com/galaxy-s5/help/bluetoothtest-apk-calling-home-t3035182)\n",
"description": "Bluetooth Test\nHidden feature accessible by entering *#*#232331#*#* in the Samsung dialer.\nIt was found to be calling home back in 2015:\nhttps://forum.xda-developers.com/galaxy-s5/help/bluetoothtest-apk-calling-home-t3035182",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -5210,11 +5210,11 @@
},
"com.sec.android.diagmonagent": {
"list": "Oem",
"description": "Diagnostic Monitoring Agent\nUsed to send diagnostic data to Samsung\nData collection from Settings > Biometrics and security > Send diagnostic data\nDisabling this causes scheduled services to aggressively launch it every second, spamming the android crash log and overheating the device, thus draining battery. More info is needed on the dependencies that trigger this behavior. Version tested: 9.0.11.",
"description": "Diagnostic Monitoring Agent\nUsed to send diagnostic data to Samsung\nData collection from Settings > Biometrics and security > Send diagnostic data\nWARNING: disabling this causes scheduled services to aggressively launch it every second, spamming the Android crash log and overheating the device, thus draining battery. More info is needed on the dependencies that trigger this behavior. Version tested: 9.0.11.",
"dependencies": [],
"neededBy": [],
"labels": [],
"removal": "Recommended"
"removal": "Advanced"
},
"com.sec.android.app.dictionary": {
"list": "Oem",
@ -6068,7 +6068,7 @@
},
"com.samsung.android.app.galaxyfinder": {
"list": "Oem",
"description": "S Finder is a search application that allows you to find what you want in an instant by searching the content on your Galaxy smartphone and on the web as well. (https://www.samsung.com/global/galaxy/what-is/s-finder/)\nNOTE: Removing this will remove the search in the app drawer.\n",
"description": "Samsung Finder is a search application that allows you to find what you want in an instant by searching the content on your Galaxy smartphone and on the web as well. (https://www.samsung.com/global/galaxy/what-is/s-finder/)\nNOTE: Removing this will remove the search in the app drawer.\n",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -6092,7 +6092,7 @@
},
"com.samsung.android.app.smartcapture": {
"list": "Oem",
"description": "Lets you group widgets on OneUI 4",
"description": "Samsung Capture\nSamsung's implementation of screenshot. Show the bottom toolbar after taking a screenshot\nLets you group widgets on OneUI 4 (?)",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -6108,7 +6108,7 @@
},
"com.sec.android.app.soundalive": {
"list": "Oem",
"description": "Responsible for Dolby Atmos and other pre-programmed equalizer stuff (accessible from the Settings app)\nNeeded by Adapt Sound (com.sec.hearingadjust) which a pretty useful but little known feature.",
"description": "Responsible for Dolby Atmos and other equalizer stuff (accessible from the Settings app).\nNeeded by Adapt Sound (com.sec.hearingadjust) which is a pretty useful feature.",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -6116,7 +6116,7 @@
},
"com.samsung.android.mcfserver": {
"list": "Oem",
"description": "Samsung Multi Connectivity (starting from Galaxy S20)\nSee https://gitlab.com/W1nst0n/universal-android-debloater/-/issues/12\n",
"description": "Samsung Multi Connectivity\n\nSee https://gitlab.com/W1nst0n/universal-android-debloater/-/issues/12\n",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -6132,7 +6132,7 @@
},
"com.sec.epdg": {
"list": "Oem",
"description": "Huh... that's hard to explain quickly. Let's try : \nFirst you need to know that there is a standards organization which develops protocols for mobile telephony called 3GPP (mobile network : 2G/3G/4G/5G).\nRAT (physical connection method to a wireless communication network) non specified by the 3GPP is called non-3GPP. RAT Wifi is non-3GPP.\n\nePDG means Evolved Packet Data Gateway. The main role of the ePDG is to provide security mechanisms such as IPsec tunnelling of connections \nwith the device over an untrusted non-3GPP access. It is mainly use for VoWifi (Voice over wifi).\nFor further information : \n- https://www.3gpp.org/technologies/keywords-acronyms/100-the-evolved-packet-core\n- https://www.aptilo.com/solutions/mobile-data-offloading/3gpp-wifi-access/\n- https://en.wikipedia.org/wiki/System_Architecture_Evolution#Evolved_Packet_Core_(EPC)\n#\nSafe to remove if not using VoWifi.\n",
"description": "Safe to remove if you're not using VoWifi.\nYou need to know that:\n3GPP is a standards organization for mobile telephony (2G/3G/4G/5G).\nNon-3GPP RAT refers to wireless connection methods not specified by 3GPP, including Wi-Fi.\nePDG (evolved Packet Data Gateway) secures connections over untrusted non-3GPP access, commonly used for VoWiFi (Voice over Wi-Fi). For more information:\n- https://www.3gpp.org/technologies/keywords-acronyms/100-the-evolved-packet-core\n- https://www.aptilo.com/solutions/mobile-data-offloading/3gpp-wifi-access/\n- https://en.wikipedia.org/wiki/System_Architecture_Evolution#Evolved_Packet_Core_(EPC)\n",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -6180,7 +6180,7 @@
},
"com.samsung.android.app.contacts": {
"list": "Oem",
"description": "Samsung contacts app\nSafe to debloat if you use another contacts app. NOTE: if you do, you will no longer be able to access Contacts from the Samsung dialer app.\nRemoving the contacts app will disable the user from being able to modify the Safety and emergency tab within the Samsung Android native settings app. Specifically the Medical info & Emergency contacts. This information is pulled on the lockscreen by first responders or in emergency sharing mode for emergency contacts.",
"description": "Samsung Contacts\nSafe to debloat if you use another contacts app. NOTE: if you do, you will no longer be able to access Contacts from the Samsung dialer app.\nRemoving the contacts app will disable the user from being able to modify the Safety and emergency tab within the Samsung Android native settings app. Specifically the Medical info & Emergency contacts. This information is pulled on the lockscreen by first responders or in emergency sharing mode for emergency contacts.",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -6196,7 +6196,7 @@
},
"com.samsung.android.lool": {
"list": "Oem",
"description": "Samsung Device Care (phone optimizer) (https://play.google.com/store/apps/details?id=com.samsung.android.lool)\nThis package phone home (China, Qihoo 360)\nThe clean feature (in storage setting) is provided by Qihoo 360 which is a shady company (https://en.wikipedia.org/wiki/Qihoo_360)\nhttps://www.reddit.com/r/Android/comments/ektg8u/chinese_spyware_preinstalled_on_all_samsung/\nhttps://www.virustotal.com/gui/file/048ead2be8d18bbe2b05651380069b3740dd05703e9bd66630da986026518398/details\n\nWARNING:Disabling/Removing this package may remove the option to manage Power Saving, Fast Charging & Battery Protection on some devices\nNOTE : If you don't want to delete this package, at least use a firewall (Netguard/AfWall+) to block internet access\n",
"description": "Samsung Device Care\n(https://play.google.com/store/apps/details?id=com.samsung.android.lool)\nThis package phone home (China, Qihoo 360)\nThe clean feature (in storage setting) is provided by Qihoo 360 which is a shady company (https://en.wikipedia.org/wiki/Qihoo_360)\nhttps://www.reddit.com/r/Android/comments/ektg8u/chinese_spyware_preinstalled_on_all_samsung/\nhttps://www.virustotal.com/gui/file/048ead2be8d18bbe2b05651380069b3740dd05703e9bd66630da986026518398/details\n\nWARNING:Disabling/Removing this package may remove the option to manage Power Saving, Fast Charging & Battery Protection on some devices\nNOTE : If you don't want to delete this package, at least use a firewall (Netguard/AfWall+) to block internet access\n",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -8994,7 +8994,7 @@
},
"com.oneplus.camera.service": {
"list": "Oem",
"description": "Runs in the background on some phones.\nNot sure what it does; camera functions fine without it. Could be related to photo backup?",
"description": "Runs in the background on some phones.\nNot sure what it does; camera functions fine without it. Could be related to photo backup? WARNING: may cause a bootloop when using a custom ROM on Android 14 (in this case, Nameless AOSP). Does not affect users running OxygenOS.",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -16074,7 +16074,7 @@
},
"com.fido.xiaomi.uafclient": {
"list": "Oem",
"description": "UAF client for FIDO.\nFido is a set of open technical specifications for mechanisms of authenticating users to online services that do not depend on passwords.\nhttps://fidoalliance.org/specs/u2f-specs-1.0-bt-nfc-id-amendment/fido-glossary.html\nhttps://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-overview-v2.0-rd-20170927.html\nThe UAF protocol is designed to enable online services to offer passwordless and multi-factor security by allowing users to register their device to the online service and using a local authentication mechanism such as iris or fingerprint recognition.\nhttps://developers.google.com/identity/fido/android/native-apps\nSafe to remove if you don't use password-less authentification to access online services.",
"description": "UAF client for FIDO.\nFido is a set of open technical specifications for mechanisms of authenticating users to online services that do not depend on passwords.\nhttps://fidoalliance.org/specs/u2f-specs-1.0-bt-nfc-id-amendment/fido-glossary.html\nhttps://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-overview-v2.0-rd-20170927.html\nThe UAF protocol is designed to enable online services to offer passwordless and multi-factor security by allowing users to register their device to the online service and using a local authentication mechanism such as iris or fingerprint recognition.\nhttps://developers.google.com/identity/fido/android/native-apps\nSafe to remove if you don't use password-less authentication to access online services.",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -23612,7 +23612,7 @@
"labels": []
},
"com.hoffnung": {
"description": "TPMS\nRemote Config Test. Instead Uninstall better Disable this app\nbecause it uninstalling cause screen flicker",
"description": "TPMS\nRemote Config Test. WARNING: you should DISABLE this package instead of uninstalling, because uninstalling causes screen flicker",
"removal": "Recommended",
"list": "Oem",
"dependencies": [],
@ -26705,7 +26705,7 @@
},
"com.google.android.apps.authenticator2": {
"list": "Google",
"description": "Google authentificator app (https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2)\n",
"description": "Google Authenticator app (https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2)\n",
"dependencies": [],
"neededBy": [],
"labels": [],
@ -27353,7 +27353,7 @@
},
"com.google.android.tts": {
"list": "Google",
"description": "Speech Services by Google (https://play.google.com/store/apps/details?id=com.google.android.tts)\nDefault Text To Speech (TTS) engine on most of Android devices. It enables apps to convert text into voice.\n\nPithus analysis: https://beta.pithus.org/report/08f97758fbfae1e17c4a8e5ee1a1e6d2726ce6b0b4931d5452f2376d60f1b4fb\n\nNote: many apps like navigation and health/sport apps rely on a TTS engine to provide speech services. Open-source TTS engines available on Android exists but, as of the end of 2022, there is only RHVoice (https://f-droid.org/en/packages/com.github.olga_yakovleva.rhvoice.android/) and it doesn't support a lot of languages. Mimic3 (https://mycroft.ai/mimic-3/) is probably the future of IoT open-source TTS engine but there is no Android support yet",
"description": "Speech Recognition and Synthesis from Google (https://play.google.com/store/apps/details?id=com.google.android.tts)\nDefault Text To Speech (TTS) engine on most of Android devices. It enables apps to convert text into voice.\n\nPithus analysis (2024-03-03): https://beta.pithus.org/report/f0a2303e1c1bd049bf1cdc5a3454dfe19b2aaf26008662c7a307aaec2538558b\n\nNote: Many navigation and health/sports apps rely on a TTS engine to provide speech services. Open-source TTS engines available on Android exists but, as of the end of 2022, there is only RHVoice (https://f-droid.org/en/packages/com.github.olga_yakovleva.rhvoice.android/) and it doesn't support a lot of languages. Mimic3 (https://mycroft.ai/mimic-3/) is probably the future of IoT open-source TTS engine but there is no Android support yet",
"dependencies": [],
"neededBy": [],
"labels": [],

View file

@ -70,8 +70,7 @@ pub fn adb_shell_command(shell: bool, args: &str) -> Result<String, String> {
Err(e) => {
// TODO: better error handling with anyhow + thiserror
error!("ADB: {}", e);
error!("ADB was not found");
std::process::exit(1);
Err("ADB was not found".to_string())
}
Ok(o) => {
if o.status.success() {
@ -331,3 +330,10 @@ pub async fn get_devices_list() -> Vec<Phone> {
)
.unwrap_or_default()
}
pub async fn initial_load() -> bool {
match adb_shell_command(false, "devices") {
Ok(_devices) => true,
Err(_err) => false,
}
}

View file

@ -65,7 +65,7 @@ impl Theme {
foreground: color!(0xE0E0E0),
},
normal: NormalColors {
primary: color!(0x230F08),
primary: color!(0x818181),
secondary: color!(0xF9D659),
surface: color!(0x818181),
error: color!(0x992B2B),

View file

@ -2,7 +2,7 @@ pub mod style;
pub mod views;
pub mod widgets;
use crate::core::sync::{get_devices_list, perform_adb_commands, CommandType, Phone};
use crate::core::sync::{get_devices_list, initial_load, perform_adb_commands, CommandType, Phone};
use crate::core::theme::Theme;
use crate::core::uad_lists::UadListState;
use crate::core::update::{get_latest_release, Release, SelfUpdateState, SelfUpdateStatus};
@ -69,6 +69,7 @@ pub enum Message {
GetLatestRelease(Result<Option<Release>, ()>),
FontLoaded(Result<(), iced::font::Error>),
Nothing,
ADBSatisfied(bool),
}
impl Application for UadGui {
@ -84,6 +85,7 @@ impl Application for UadGui {
// Used in crate::gui::widgets::navigation_menu::ICONS. Name is `icomoon`.
font::load(include_bytes!("../../resources/assets/icons.ttf").as_slice())
.map(Message::FontLoaded),
Command::perform(initial_load(), Message::ADBSatisfied),
Command::perform(get_devices_list(), Message::LoadDevices),
Command::perform(
async move { get_latest_release() },
@ -119,6 +121,8 @@ impl Application for UadGui {
#[allow(unused_must_use)]
{
self.update(Message::SettingsAction(SettingsMessage::LoadDeviceSettings));
self.update(Message::AppsAction(AppsMessage::ToggleAllSelected(false)));
self.update(Message::AppsAction(AppsMessage::ClearSelectedPackages));
}
self.update(Message::AppsAction(AppsMessage::LoadUadList(true)))
@ -328,11 +332,15 @@ impl Application for UadGui {
Command::none()
}
Message::ADBSatisfied(result) => match result {
true => self.update(Message::AppsAction(AppsMessage::ADBSatisfied(true))),
false => self.update(Message::AppsAction(AppsMessage::ADBSatisfied(false))),
},
Message::Nothing => Command::none(),
}
}
fn view(&self) -> Element<Self::Message, Renderer<Self::Theme>> {
fn view(&self) -> Element<Self::Message, Self::Theme, Renderer> {
let navigation_container = nav_menu(
&self.devices_list,
self.selected_device.clone(),
@ -369,13 +377,16 @@ impl UadGui {
Self::run(Settings {
window: Window {
size: (820, 640),
size: iced::Size {
width: 1000.0,
height: 820.0,
},
resizable: true,
decorations: true,
icon: icon::from_file_data(logo, Some(ImageFormat::Png)).ok(),
..iced::window::Settings::default()
},
default_text_size: 16.0,
default_text_size: iced::Pixels(16.0),
..Settings::default()
})
}

View file

@ -3,7 +3,7 @@ use iced::overlay::menu;
use iced::widget::{
button, checkbox, container, pick_list, radio, rule, scrollable, text, text_input,
};
use iced::{application, Background, Color};
use iced::{application, Background, Border, Color, Shadow};
#[derive(Default, Debug, Clone, Copy)]
pub enum Application {
@ -41,28 +41,42 @@ impl container::StyleSheet for Theme {
Container::Frame => container::Appearance {
background: Some(Background::Color(self.palette().base.foreground)),
text_color: Some(self.palette().bright.surface),
border_radius: 5.0.into(),
border: Border {
color: Color::TRANSPARENT,
width: 0.0,
radius: 5.0.into(),
},
..container::Appearance::default()
},
Container::BorderedFrame => container::Appearance {
background: Some(Background::Color(self.palette().base.foreground)),
text_color: Some(self.palette().bright.surface),
border_radius: 5.0.into(),
border_width: 1.0,
border_color: self.palette().normal.error,
border: Border {
color: self.palette().normal.error,
width: 1.0,
radius: 5.0.into(),
},
shadow: Shadow::default(),
},
Container::Tooltip => container::Appearance {
background: Some(Background::Color(self.palette().base.foreground)),
text_color: Some(self.palette().bright.surface),
border_radius: 8.0.into(),
border_width: 1.0,
border_color: self.palette().normal.primary,
border: Border {
color: self.palette().normal.primary,
width: 1.0,
radius: 8.0.into(),
},
shadow: Shadow::default(),
},
Container::Background => container::Appearance {
background: Some(Background::Color(self.palette().base.background)),
text_color: Some(self.palette().bright.surface),
border_radius: 5.0.into(),
border: Border {
color: Color::TRANSPARENT,
width: 0.0,
radius: 5.0.into(),
},
..container::Appearance::default()
},
}
@ -90,14 +104,21 @@ impl button::StyleSheet for Theme {
let p = self.palette();
let appearance = button::Appearance {
border_width: 1.0,
border_radius: 2.0.into(),
border: Border {
color: self.palette().normal.primary,
width: 1.0,
radius: 2.0.into(),
},
..button::Appearance::default()
};
let active_appearance = |bg: Option<Color>, mc| button::Appearance {
background: Some(Background::Color(bg.unwrap_or(p.base.foreground))),
border_color: Color { a: 0.5, ..mc },
border: Border {
color: Color { a: 0.5, ..mc },
width: 1.0,
radius: 2.0.into(),
},
text_color: mc,
..appearance
};
@ -110,9 +131,11 @@ impl button::StyleSheet for Theme {
Button::NormalPackage => button::Appearance {
background: Some(Background::Color(p.base.foreground)),
text_color: p.bright.surface,
border_radius: 5.0.into(),
border_width: 0.0,
border_color: p.base.background,
border: Border {
color: p.base.background,
width: 0.0,
radius: 5.0.into(),
},
..appearance
},
Button::SelectedPackage => button::Appearance {
@ -121,9 +144,11 @@ impl button::StyleSheet for Theme {
..p.normal.primary
})),
text_color: p.bright.primary,
border_radius: 5.0.into(),
border_width: 0.0,
border_color: p.normal.primary,
border: Border {
color: p.normal.primary,
width: 0.0,
radius: 5.0.into(),
},
..appearance
},
Button::Unavailable | Button::UninstallPackage => {
@ -132,9 +157,11 @@ impl button::StyleSheet for Theme {
Button::Hidden => button::Appearance {
background: Some(Background::Color(Color::TRANSPARENT)),
text_color: Color::TRANSPARENT,
border_radius: 5.0.into(),
border_width: 0.0,
border_color: Color::TRANSPARENT,
border: Border {
color: Color::TRANSPARENT,
width: 0.0,
radius: 5.0.into(),
},
..appearance
},
}
@ -200,17 +227,25 @@ pub enum Scrollable {
impl scrollable::StyleSheet for Theme {
type Style = Scrollable;
fn active(&self, style: &Self::Style) -> scrollable::Scrollbar {
let from_appearance = |c: Color| scrollable::Scrollbar {
background: Some(Background::Color(Color::TRANSPARENT)),
border_radius: 5.0.into(),
border_width: 0.0,
border_color: Color::TRANSPARENT,
scroller: scrollable::Scroller {
color: c,
border_radius: 5.0.into(),
border_width: 1.0,
border_color: Color::TRANSPARENT,
fn active(&self, style: &Self::Style) -> scrollable::Appearance {
let from_appearance = |c: Color| scrollable::Appearance {
container: container::Appearance::default(),
gap: Some(Background::Color(Color::TRANSPARENT)),
scrollbar: scrollable::Scrollbar {
background: Some(Background::Color(Color::TRANSPARENT)),
border: Border {
color: Color::TRANSPARENT,
width: 0.0,
radius: 5.0.into(),
},
scroller: scrollable::Scroller {
color: c,
border: Border {
color: Color::TRANSPARENT,
width: 1.0,
radius: 5.0.into(),
},
},
},
};
@ -220,17 +255,17 @@ impl scrollable::StyleSheet for Theme {
}
}
fn hovered(&self, style: &Self::Style, _mouse_over_scrollbar: bool) -> scrollable::Scrollbar {
scrollable::Scrollbar {
scroller: self.active(style).scroller,
fn hovered(&self, style: &Self::Style, _mouse_over_scrollbar: bool) -> scrollable::Appearance {
scrollable::Appearance {
scrollbar: self.active(style).scrollbar,
..self.active(style)
}
}
fn dragging(&self, style: &Self::Style) -> scrollable::Scrollbar {
fn dragging(&self, style: &Self::Style) -> scrollable::Appearance {
let hovered = self.hovered(style, true);
scrollable::Scrollbar {
scroller: hovered.scroller,
scrollable::Appearance {
scrollbar: hovered.scrollbar,
..hovered
}
}
@ -253,9 +288,11 @@ impl checkbox::StyleSheet for Theme {
CheckBox::PackageEnabled => checkbox::Appearance {
background: Background::Color(self.palette().base.background),
icon_color: self.palette().bright.primary,
border_radius: 5.0.into(),
border_width: 1.0,
border_color: self.palette().base.background,
border: Border {
color: self.palette().base.background,
width: 1.0,
radius: 5.0.into(),
},
text_color: Some(self.palette().bright.surface),
},
CheckBox::PackageDisabled => checkbox::Appearance {
@ -263,26 +300,33 @@ impl checkbox::StyleSheet for Theme {
a: 0.55,
..self.palette().base.background
}),
icon_color: self.palette().bright.primary,
border_radius: 5.0.into(),
border_width: 1.0,
border_color: self.palette().normal.primary,
border: Border {
color: self.palette().normal.primary,
width: 1.0,
radius: 5.0.into(),
},
text_color: Some(self.palette().normal.primary),
},
CheckBox::SettingsEnabled => checkbox::Appearance {
background: Background::Color(self.palette().base.background),
icon_color: self.palette().bright.primary,
border_radius: 5.0.into(),
border_width: 1.0,
border_color: self.palette().bright.primary,
border: Border {
color: self.palette().bright.primary,
width: 1.0,
radius: 5.0.into(),
},
text_color: Some(self.palette().bright.surface),
},
CheckBox::SettingsDisabled => checkbox::Appearance {
background: Background::Color(self.palette().base.foreground),
icon_color: self.palette().bright.primary,
border_radius: 5.0.into(),
border_width: 1.0,
border_color: self.palette().normal.primary,
border: Border {
color: self.palette().normal.primary,
width: 1.0,
radius: 5.0.into(),
},
text_color: Some(self.palette().bright.surface),
},
}
@ -292,9 +336,11 @@ impl checkbox::StyleSheet for Theme {
let from_appearance = || checkbox::Appearance {
background: Background::Color(self.palette().base.foreground),
icon_color: self.palette().bright.primary,
border_radius: 5.0.into(),
border_width: 2.0,
border_color: self.palette().bright.primary,
border: Border {
color: self.palette().bright.primary,
width: 2.0,
radius: 5.0.into(),
},
text_color: Some(self.palette().bright.surface),
};
@ -319,9 +365,11 @@ impl text_input::StyleSheet for Theme {
fn active(&self, _style: &Self::Style) -> text_input::Appearance {
text_input::Appearance {
background: Background::Color(self.palette().base.foreground),
border_radius: 5.0.into(),
border_width: 0.0,
border_color: self.palette().base.foreground,
border: Border {
color: self.palette().base.foreground,
width: 0.0,
radius: 5.0.into(),
},
icon_color: Color {
a: 0.5,
..self.palette().normal.primary
@ -332,11 +380,13 @@ impl text_input::StyleSheet for Theme {
fn focused(&self, _style: &Self::Style) -> text_input::Appearance {
text_input::Appearance {
background: Background::Color(self.palette().base.foreground),
border_radius: 2.0.into(),
border_width: 1.0,
border_color: Color {
a: 0.5,
..self.palette().normal.primary
border: Border {
color: Color {
a: 0.5,
..self.palette().normal.primary
},
width: 1.0,
radius: 2.0.into(),
},
icon_color: Color {
a: 0.5,
@ -355,11 +405,13 @@ impl text_input::StyleSheet for Theme {
fn disabled(&self, _style: &Self::Style) -> text_input::Appearance {
text_input::Appearance {
background: Background::Color(self.palette().base.background),
border_radius: 2.0.into(),
border_width: 1.0,
border_color: Color {
a: 0.5,
..self.palette().base.foreground
border: Border {
color: Color {
a: 0.5,
..self.palette().base.foreground
},
width: 1.0,
radius: 2.0.into(),
},
icon_color: Color {
a: 0.5,
@ -401,9 +453,11 @@ impl menu::StyleSheet for Theme {
menu::Appearance {
text_color: p.bright.surface,
background: p.base.background.into(),
border_width: 1.0,
border_radius: 2.0.into(),
border_color: p.base.background,
border: Border {
color: p.base.background,
width: 1.0,
radius: 2.0.into(),
},
selected_text_color: p.bright.surface,
selected_background: p.normal.primary.into(),
}
@ -417,12 +471,14 @@ impl pick_list::StyleSheet for Theme {
pick_list::Appearance {
text_color: self.palette().bright.surface,
background: self.palette().base.background.into(),
border_width: 1.0,
border_color: Color {
a: 0.5,
..self.palette().normal.primary
border: Border {
color: Color {
a: 0.5,
..self.palette().normal.primary
},
width: 1.0,
radius: 2.0.into(),
},
border_radius: 2.0.into(),
handle_color: self.palette().bright.surface,
placeholder_color: self.palette().bright.surface,
}
@ -431,7 +487,11 @@ impl pick_list::StyleSheet for Theme {
fn hovered(&self, style: &()) -> pick_list::Appearance {
let active = self.active(style);
pick_list::Appearance {
border_color: self.palette().normal.primary,
border: Border {
color: self.palette().normal.primary,
width: 1.0,
radius: 2.0.into(),
},
..active
}
}

View file

@ -26,7 +26,7 @@ impl About {
}
// other events are handled by UadGui update()
}
pub fn view(&self, update_state: &UpdateState) -> Element<Message, Renderer<Theme>> {
pub fn view(&self, update_state: &UpdateState) -> Element<Message, Theme, Renderer> {
let about_text = text(
"Universal Android Debloater Next Generation (UAD-ng) is a Free and Open-Source community project aiming at simplifying \
the removal of pre-installed apps on any Android device.",
@ -42,13 +42,13 @@ impl About {
let last_update_text = text(update_state.uad_list.to_string());
let uad_lists_btn = button("Update")
.on_press(Message::UpdateUadLists)
.padding(5)
.padding([5, 10])
.style(style::Button::Primary);
#[cfg(feature = "self-update")]
let self_update_btn = button("Update")
.on_press(Message::DoSelfUpdate)
.padding(5)
.padding([5, 10])
.style(style::Button::Primary);
#[cfg(feature = "self-update")]
@ -102,26 +102,26 @@ impl About {
.on_press(Message::UrlPressed(PathBuf::from(
"https://github.com/Universal-Debloater-Alliance/universal-android-debloater",
)))
.padding(5)
.padding([5, 10])
.style(style::Button::Primary);
let issue_btn = button("Have an issue?")
.on_press(Message::UrlPressed(PathBuf::from(
"https://github.com/Universal-Debloater-Alliance/universal-android-debloater/issues",
)))
.padding(5)
.padding([5, 10])
.style(style::Button::Primary);
let log_btn = button("Locate the logfiles")
.on_press(Message::UrlPressed(CACHE_DIR.to_path_buf()))
.padding(5)
.padding([5, 10])
.style(style::Button::Primary);
let wiki_btn = button("Wiki")
.on_press(Message::UrlPressed(PathBuf::from(
"https://github.com/Universal-Debloater-Alliance/universal-android-debloater/wiki",
)))
.padding(5)
.padding([5, 10])
.style(style::Button::Primary);
let row = row![website_btn, wiki_btn, issue_btn, log_btn,].spacing(20);

View file

@ -52,6 +52,7 @@ pub struct List {
description: String,
selection_modal: bool,
current_package_index: usize,
is_adb_satisfied: bool,
}
#[derive(Debug, Clone)]
@ -73,6 +74,8 @@ pub enum Message {
ModalHide,
ModalUserSelected(User),
ModalValidate,
ClearSelectedPackages,
ADBSatisfied(bool),
}
pub struct SummaryEntry {
@ -289,6 +292,14 @@ impl List {
Message::UserSelected(user),
)
}
Message::ClearSelectedPackages => {
self.selected_packages = Vec::new();
Command::none()
}
Message::ADBSatisfied(result) => {
self.is_adb_satisfied = result;
Command::none()
}
Message::Nothing => Command::none(),
}
}
@ -297,35 +308,52 @@ impl List {
&self,
settings: &Settings,
selected_device: &Phone,
) -> Element<Message, Renderer<Theme>> {
) -> Element<Message, Theme, Renderer> {
match &self.loading_state {
LoadingState::DownloadingList => {
let text = "Downloading latest UAD-ng lists from GitHub. Please wait...";
waiting_view(settings, text, true)
}
LoadingState::FindingPhones => {
waiting_view(settings, "Finding connected devices...", false)
waiting_view(settings, text, true, style::Text::Default)
}
LoadingState::FindingPhones => match self.is_adb_satisfied {
true => waiting_view(
settings,
"Finding connected devices...",
false,
style::Text::Default,
),
false => waiting_view(
settings,
"ADB is not installed on your system, install ADB and relaunch application.",
false,
style::Text::Danger,
),
},
LoadingState::LoadingPackages => {
let text = "Pulling packages from the device. Please wait...";
waiting_view(settings, text, false)
}
LoadingState::_UpdatingUad => {
waiting_view(settings, "Updating UAD-ng. Please wait...", false)
}
LoadingState::RestoringDevice(device) => {
waiting_view(settings, &format!("Restoring device: {device}"), false)
waiting_view(settings, text, false, style::Text::Default)
}
LoadingState::_UpdatingUad => waiting_view(
settings,
"Updating UAD-ng. Please wait...",
false,
style::Text::Default,
),
LoadingState::RestoringDevice(device) => waiting_view(
settings,
&format!("Restoring device: {device}"),
false,
style::Text::Default,
),
LoadingState::Ready => {
let search_packages = text_input("Search packages...", &self.input_value)
.width(Length::Fill)
.on_input(Message::SearchInputChanged)
.padding(5);
.padding([5, 10]);
let select_all_checkbox =
checkbox("", self.all_selected, Message::ToggleAllSelected)
.style(style::CheckBox::SettingsEnabled)
.spacing(0); // no label, so remove space entirely
let select_all_checkbox = checkbox("", self.all_selected)
.on_toggle(Message::ToggleAllSelected)
.style(style::CheckBox::SettingsEnabled)
.spacing(0); // no label, so remove space entirely
let col_sel_all = row![tooltip(
select_all_checkbox,
@ -404,14 +432,14 @@ impl List {
self.selected_packages.len()
)))
.on_press(Message::ApplyActionOnSelection)
.padding(5)
.padding([5, 10])
.style(style::Button::Primary)
} else {
button(text(format!(
"Review selection ({})",
self.selected_packages.len()
)))
.padding(5)
.padding([5, 10])
};
let action_row = row![Space::new(Length::Fill, Length::Shrink), review_selection]
@ -478,7 +506,7 @@ impl List {
device: &Phone,
settings: &Settings,
packages: &[PackageRow],
) -> Element<Message, Renderer<Theme>> {
) -> Element<Message, Theme, Renderer> {
// 5 element slice is cheap
let mut summaries = Removal::CATEGORIES.map(SummaryEntry::from);
for p in packages.iter().filter(|p| p.selected) {
@ -544,7 +572,7 @@ impl List {
let modal_btn_row = row![
button(text("Cancel")).on_press(Message::ModalHide),
horizontal_space(Length::Fill),
horizontal_space(),
button(text("Apply")).on_press(Message::ModalValidate),
]
.padding([0, 15, 10, 10]);
@ -591,7 +619,7 @@ impl List {
.name
.clone()
),],
horizontal_space(Length::Fill),
horizontal_space(),
row![match self.phone_packages[selection.0]
[selection.1]
.state
@ -728,23 +756,24 @@ fn waiting_view<'a>(
_settings: &Settings,
displayed_text: &str,
btn: bool,
) -> Element<'a, Message, Renderer<Theme>> {
text_style: style::Text,
) -> Element<'a, Message, Theme, Renderer> {
let col = if btn {
let no_internet_btn = button("No internet?")
.padding(5)
.padding([5, 10])
.on_press(Message::LoadUadList(false))
.style(style::Button::Primary);
column![]
.spacing(10)
.align_items(Alignment::Center)
.push(text(displayed_text).size(20))
.push(text(displayed_text).style(text_style).size(20))
.push(no_internet_btn)
} else {
column![]
.spacing(10)
.align_items(Alignment::Center)
.push(text(displayed_text).size(20))
.push(text(displayed_text).style(text_style).size(20))
};
container(col)
@ -797,10 +826,10 @@ fn build_action_pkg_commands(
commands
}
fn recap<'a>(settings: &Settings, recap: &SummaryEntry) -> Element<'a, Message, Renderer<Theme>> {
fn recap<'a>(settings: &Settings, recap: &SummaryEntry) -> Element<'a, Message, Theme, Renderer> {
container(
row![
text(recap.category).size(24).width(Length::FillPortion(1)),
text(recap.category).size(19).width(Length::FillPortion(1)),
vertical_rule(5),
row![
if settings.device.disable_mode {
@ -808,7 +837,7 @@ fn recap<'a>(settings: &Settings, recap: &SummaryEntry) -> Element<'a, Message,
} else {
text("Uninstall").style(style::Text::Danger)
},
horizontal_space(Length::Fill),
horizontal_space(),
text(recap.discard).style(style::Text::Danger)
]
.width(Length::FillPortion(1)),
@ -819,7 +848,7 @@ fn recap<'a>(settings: &Settings, recap: &SummaryEntry) -> Element<'a, Message,
} else {
text("Restore").style(style::Text::Ok)
},
horizontal_space(Length::Fill),
horizontal_space(),
text(recap.restore).style(style::Text::Ok)
]
.width(Length::FillPortion(1))

View file

@ -179,7 +179,7 @@ impl Settings {
}
}
pub fn view(&self, phone: &Phone) -> Element<Message, Renderer<Theme>> {
pub fn view(&self, phone: &Phone) -> Element<Message, Theme, Renderer> {
let radio_btn_theme = Theme::ALL
.iter()
.fold(row![].spacing(10), |column, option| {
@ -202,8 +202,8 @@ impl Settings {
let expert_mode_checkbox = checkbox(
"Allow to uninstall packages marked as \"unsafe\" (I KNOW WHAT I AM DOING)",
self.general.expert_mode,
Message::ExpertMode,
)
.on_toggle(Message::ExpertMode)
.style(style::CheckBox::SettingsEnabled);
let expert_mode_descr =
@ -248,8 +248,8 @@ impl Settings {
let multi_user_mode_checkbox = checkbox(
"Affect all the users of the device (not only the selected user)",
self.device.multi_user_mode,
Message::MultiUserMode,
)
.on_toggle(Message::MultiUserMode)
.style(style::CheckBox::SettingsEnabled);
let disable_checkbox_style = if phone.android_sdk >= 23 {
@ -275,8 +275,8 @@ impl Settings {
let disable_mode_checkbox = checkbox(
"Clear and disable packages instead of uninstalling them",
self.device.disable_mode,
Message::DisableMode,
)
.on_toggle(Message::DisableMode)
.style(disable_checkbox_style);
let disable_setting_row = if phone.android_sdk >= 23 {
@ -316,7 +316,7 @@ impl Settings {
.padding(6);
let backup_btn = button(text("Backup").horizontal_alignment(alignment::Horizontal::Center))
.padding(5)
.padding([5, 10])
.on_press(Message::BackupDevice)
.style(style::Button::Primary)
.width(77);
@ -324,24 +324,28 @@ impl Settings {
let restore_btn = |enabled| {
if enabled {
button(text("Restore").horizontal_alignment(alignment::Horizontal::Center))
.padding(5)
.padding([5, 10])
.on_press(Message::RestoreDevice)
.width(77)
} else {
button(text("No backup").horizontal_alignment(alignment::Horizontal::Center))
.padding(5)
.width(77)
button(
text("No backup")
.horizontal_alignment(alignment::Horizontal::Center)
.vertical_alignment(alignment::Vertical::Center),
)
.padding([5, 10])
.width(77)
}
};
let locate_backup_btn = if self.device.backup.backups.is_empty() {
button("Open backup directory")
.padding(5)
.padding([5, 10])
.style(style::Button::Primary)
} else {
button("Open backup directory")
.on_press(Message::UrlPressed(BACKUP_DIR.join(phone.adb_id.clone())))
.padding(5)
.padding([5, 10])
.style(style::Button::Primary)
};
@ -354,11 +358,7 @@ impl Settings {
.spacing(10)
.align_items(Alignment::Center);
let restore_row = if self.device.backup.backups.is_empty() {
row![restore_btn(false), "Restore the state of the device",]
.spacing(10)
.align_items(Alignment::Center)
} else {
let restore_row = if !self.device.backup.backups.is_empty() {
row![
restore_btn(true),
"Restore the state of the device",
@ -368,6 +368,8 @@ impl Settings {
]
.spacing(10)
.align_items(Alignment::Center)
} else {
row![]
};
let backup_restore_ctn = container(column![backup_row, restore_row].spacing(10))

View file

@ -4,17 +4,17 @@ use iced::mouse::{self, Cursor};
use iced::{advanced, event, Alignment, Color, Element, Event, Length, Point, Rectangle, Size};
/// A widget that centers a modal element over some base element
pub struct Modal<'a, Message, Renderer> {
base: Element<'a, Message, Renderer>,
modal: Element<'a, Message, Renderer>,
pub struct Modal<'a, Message, Theme, Renderer> {
base: Element<'a, Message, Theme, Renderer>,
modal: Element<'a, Message, Theme, Renderer>,
on_blur: Option<Message>,
}
impl<'a, Message, Renderer> Modal<'a, Message, Renderer> {
impl<'a, Message, Theme, Renderer> Modal<'a, Message, Theme, Renderer> {
/// Returns a new [`Modal`]
pub fn new(
base: impl Into<Element<'a, Message, Renderer>>,
modal: impl Into<Element<'a, Message, Renderer>>,
base: impl Into<Element<'a, Message, Theme, Renderer>>,
modal: impl Into<Element<'a, Message, Theme, Renderer>>,
) -> Self {
Self {
base: base.into(),
@ -34,7 +34,8 @@ impl<'a, Message, Renderer> Modal<'a, Message, Renderer> {
}
}
impl<'a, Message, Renderer> Widget<Message, Renderer> for Modal<'a, Message, Renderer>
impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
for Modal<'a, Message, Theme, Renderer>
where
Renderer: advanced::Renderer,
Message: Clone,
@ -43,20 +44,23 @@ where
vec![Tree::new(&self.base), Tree::new(&self.modal)]
}
fn size(&self) -> Size<Length> {
self.base.as_widget().size()
}
fn diff(&self, tree: &mut Tree) {
tree.diff_children(&[&self.base, &self.modal]);
}
fn width(&self) -> Length {
self.base.as_widget().width()
}
fn height(&self) -> Length {
self.base.as_widget().height()
}
fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> layout::Node {
self.base.as_widget().layout(renderer, limits)
fn layout(
&self,
tree: &mut Tree,
renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
self.base
.as_widget()
.layout(&mut tree.children[0], renderer, limits)
}
fn on_event(
@ -86,7 +90,7 @@ where
&self,
state: &Tree,
renderer: &mut Renderer,
theme: &Renderer::Theme,
theme: &Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor: Cursor,
@ -108,16 +112,15 @@ where
state: &'b mut Tree,
layout: Layout<'_>,
_renderer: &Renderer,
) -> Option<overlay::Element<'b, Message, Renderer>> {
Some(overlay::Element::new(
layout.position(),
Box::new(Overlay {
content: &mut self.modal,
tree: &mut state.children[1],
size: layout.bounds().size(),
on_blur: self.on_blur.clone(),
}),
))
_translation: iced::Vector,
) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
Some(overlay::Element::new(Box::new(Overlay {
position: layout.position(),
content: &mut self.modal,
tree: &mut state.children[1],
size: layout.bounds().size(),
on_blur: self.on_blur.clone(),
})))
}
fn mouse_interaction(
@ -150,31 +153,32 @@ where
}
}
struct Overlay<'a, 'b, Message, Renderer> {
content: &'b mut Element<'a, Message, Renderer>,
struct Overlay<'a, 'b, Message, Theme, Renderer> {
position: Point,
content: &'b mut Element<'a, Message, Theme, Renderer>,
tree: &'b mut Tree,
size: Size,
on_blur: Option<Message>,
}
impl<'a, 'b, Message, Renderer> overlay::Overlay<Message, Renderer>
for Overlay<'a, 'b, Message, Renderer>
impl<'a, 'b, Message, Theme, Renderer> overlay::Overlay<Message, Theme, Renderer>
for Overlay<'a, 'b, Message, Theme, Renderer>
where
Renderer: advanced::Renderer,
Message: Clone,
{
fn layout(&self, renderer: &Renderer, _bounds: Size, position: Point) -> layout::Node {
fn layout(&mut self, renderer: &Renderer, _bounds: Size) -> layout::Node {
let limits = layout::Limits::new(Size::ZERO, self.size)
.width(Length::Fill)
.height(Length::Fill);
let mut child = self.content.as_widget().layout(renderer, &limits);
child.align(Alignment::Center, Alignment::Center, limits.max());
let child = self
.content
.as_widget()
.layout(self.tree, renderer, &limits)
.align(Alignment::Center, Alignment::Center, limits.max());
let mut node = layout::Node::with_children(self.size, vec![child]);
node.move_to(position);
node
layout::Node::with_children(self.size, vec![child]).move_to(self.position)
}
fn on_event(
@ -215,7 +219,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
theme: &Renderer::Theme,
theme: &Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor: Cursor,
@ -223,9 +227,7 @@ where
renderer.fill_quad(
renderer::Quad {
bounds: layout.bounds(),
border_radius: iced::BorderRadius::from(0.0),
border_width: 0.0,
border_color: Color::TRANSPARENT,
..renderer::Quad::default()
},
Color {
a: 0.80,
@ -275,12 +277,14 @@ where
}
}
impl<'a, Message, Renderer> From<Modal<'a, Message, Renderer>> for Element<'a, Message, Renderer>
impl<'a, Message, Theme, Renderer> From<Modal<'a, Message, Theme, Renderer>>
for Element<'a, Message, Theme, Renderer>
where
Theme: 'a,
Renderer: 'a + advanced::Renderer,
Message: 'a + Clone,
{
fn from(modal: Modal<'a, Message, Renderer>) -> Self {
fn from(modal: Modal<'a, Message, Theme, Renderer>) -> Self {
Element::new(modal)
}
}

View file

@ -14,11 +14,11 @@ pub const ICONS: Font = Font {
};
pub fn nav_menu<'a>(
device_list: &'a Vec<Phone>,
device_list: &'a [Phone],
selected_device: Option<Phone>,
apps_view: &AppsView,
self_update_state: &SelfUpdateState,
) -> Element<'a, Message, Renderer<Theme>> {
) -> Element<'a, Message, Theme, Renderer> {
let apps_refresh_btn = button(
Text::new("\u{E900}")
.font(ICONS)
@ -26,7 +26,7 @@ pub fn nav_menu<'a>(
.horizontal_alignment(alignment::Horizontal::Center),
)
.on_press(Message::RefreshButtonPressed)
.padding(5)
.padding([5, 10])
.style(style::Button::Refresh);
let apps_refresh_tooltip = tooltip(apps_refresh_btn, "Refresh apps", tooltip::Position::Bottom)
@ -35,7 +35,7 @@ pub fn nav_menu<'a>(
let reboot_btn = button("Reboot")
.on_press(Message::RebootButtonPressed)
.padding(5)
.padding([5, 10])
.style(style::Button::Refresh);
#[allow(clippy::option_if_let_else)]
@ -56,7 +56,7 @@ pub fn nav_menu<'a>(
let update_btn = if self_update_state.latest_release.is_some() {
button("Update")
.on_press(Message::AboutAction(AboutMessage::DoSelfUpdate))
.padding(5)
.padding([5, 10])
.style(style::Button::SelfUpdate)
} else {
button("").height(0).width(0).style(style::Button::Hidden)
@ -64,17 +64,17 @@ pub fn nav_menu<'a>(
let apps_btn = button("Apps")
.on_press(Message::AppsPress)
.padding(5)
.padding([5, 10])
.style(style::Button::Primary);
let about_btn = button("About")
.on_press(Message::AboutPressed)
.padding(5)
.padding([5, 10])
.style(style::Button::Primary);
let settings_btn = button("Settings")
.on_press(Message::SettingsPressed)
.padding(5)
.padding([5, 10])
.style(style::Button::Primary);
let device_list_text = match apps_view.loading_state {

View file

@ -50,7 +50,7 @@ impl PackageRow {
Command::none()
}
pub fn view(&self, settings: &Settings, _phone: &Phone) -> Element<Message, Renderer<Theme>> {
pub fn view(&self, settings: &Settings, _phone: &Phone) -> Element<Message, Theme, Renderer> {
//let trash_svg = format!("{}/resources/assets/trash.svg", env!("CARGO_MANIFEST_DIR"));
//let restore_svg = format!("{}/resources/assets/rotate.svg", env!("CARGO_MANIFEST_DIR"));
let button_style;
@ -86,7 +86,8 @@ impl PackageRow {
|| self.state != PackageState::Enabled
|| settings.general.expert_mode
{
selection_checkbox = checkbox("", self.selected, Message::ToggleSelection)
selection_checkbox = checkbox("", self.selected)
.on_toggle(Message::ToggleSelection)
.style(style::CheckBox::PackageEnabled);
action_btn = button(
@ -96,7 +97,8 @@ impl PackageRow {
)
.on_press(Message::ActionPressed);
} else {
selection_checkbox = checkbox("", self.selected, Message::ToggleSelection)
selection_checkbox = checkbox("", self.selected)
.on_toggle(Message::ToggleSelection)
.style(style::CheckBox::PackageDisabled);
action_btn = button(