mirror of
https://github.com/0x192/universal-android-debloater.git
synced 2026-04-26 10:50:49 +00:00
refactor: apply extra clippy lints suggestions (#673)
Cherry picking of lints from clippy::pedantic / clippy::nursery / clippy::unwrap_used / clippy::expect_used Notable changes : - consideration of all clippy::use-self lints - replaced sort() by unstable_sort() - use of map_or_else() when appropriate - replaced "".to_string() by String::new() - replaced collect() + len() by count() The code base now passes all the clippy::nursery lints --------- Co-authored-by: w1nst0n <w1nst0n@keemail.me>
This commit is contained in:
parent
69235a9aa5
commit
68092ff987
27 changed files with 429 additions and 403 deletions
22
.github/ISSUE_TEMPLATE/add-new-package-s-.md
vendored
22
.github/ISSUE_TEMPLATE/add-new-package-s-.md
vendored
|
|
@ -1,28 +1,34 @@
|
|||
---
|
||||
name: Add new package(s)
|
||||
about: You want to add new apps in the debloat list
|
||||
title: ''
|
||||
title: ""
|
||||
labels: package::addition
|
||||
assignees: ''
|
||||
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Your phone:** <phone model>
|
||||
**Your phone model:**
|
||||
|
||||
**Packages:**
|
||||
|
||||
```
|
||||
com.this.is.a.bad.application
|
||||
com.this.is.another.bad.application
|
||||
...
|
||||
```
|
||||
|
||||
- [ ] **I removed all those packages on my phone**
|
||||
If not why. Leave the brackets blank and explain why.
|
||||
If not why. Leave the brackets blank and explain why.
|
||||
|
||||
## Document each package the best you can
|
||||
**List**: `Google`|`Misc`|`Oem` (manufacturer)|`Aosp`|`Pending`|`Carrier` (isp).
|
||||
**Removal**: `Recommended`, `Advanced`, `Expert` (this can break important features), `Unsafe` (this can bootloop the phone or break extremely important features).
|
||||
|
||||
**List**: `Google`|`Misc`|`OEM` (manufacturer)|`AOSP`|`Pending`|`Carrier` (isp).
|
||||
|
||||
**Removal**: `Recommended`, `Advanced`, `Expert` (this can break important features),
|
||||
or `Unsafe` (this can bootloop the phone or break extremely important features).
|
||||
|
||||
### \<package name\>
|
||||
**List**: \<list\>
|
||||
|
||||
**List**: \<list\>
|
||||
**Removal**: \<recommendation list\>
|
||||
|
||||
> Description. Link to its Playstore page if it exists.
|
||||
|
|
|
|||
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -1,10 +1,9 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: You have an issue with the UAD software itself
|
||||
title: ''
|
||||
title: ""
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
---
|
||||
name: Debloat issue report
|
||||
about: Your phone has unexpected issues after debloating
|
||||
title: ''
|
||||
title: ""
|
||||
labels: package::breakage
|
||||
assignees: ''
|
||||
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Your phone**: \<phone model\>
|
||||
**Your phone model**:
|
||||
|
||||
**Describe the issue**
|
||||
A clear and concise description of what the problem is.
|
||||
|
|
@ -16,4 +15,4 @@ A clear and concise description of what the problem is.
|
|||
What to do to fix the issue.
|
||||
|
||||
**UAD log**
|
||||
Upload the logfile generated by UAD. You can hardly be helped without.
|
||||
Upload the logfile generated by UAD. It would be difficult to help you without it.
|
||||
|
|
|
|||
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
|
@ -1,10 +1,9 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: You want a new feature
|
||||
title: ''
|
||||
title: ""
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Describe the feature you want**
|
||||
|
|
|
|||
|
|
@ -1,30 +1,37 @@
|
|||
---
|
||||
name: Update apps description or recommendation
|
||||
about: You want to improve/update a description/recommendation
|
||||
title: ''
|
||||
title: ""
|
||||
labels: package::documentation
|
||||
assignees: ''
|
||||
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Your phone**: \<phone model\>
|
||||
**Your phone model**:
|
||||
|
||||
**Packages documentation to update:**
|
||||
|
||||
```
|
||||
com.this.is.a.application
|
||||
com.this.is.another.application
|
||||
...
|
||||
```
|
||||
## Documentation chage
|
||||
**List**: `Google`|`Misc`|`Oem` (manufacturer)|`Aosp`|`Pending`|`Carrier` (isp).
|
||||
**Removal**: `Recommended`, `Advanced`, `Expert` (this can break important features), `Unsafe` (this can bootloop the phone or break extremely important features).
|
||||
|
||||
## Documentation Change
|
||||
|
||||
**List**: `Google`|`Misc`|`OEM` (manufacturer)|`AOSP`|`Pending`|`Carrier` (isp).
|
||||
**Removal**: `Recommended`, `Advanced`, `Expert` (this can break important features),
|
||||
or `Unsafe` (this can bootloop the phone or break extremely important features).
|
||||
|
||||
### \<package name\>
|
||||
**List**: \<current list\> :arrow_right: \<proposed list\>
|
||||
**Removal**: \<current recommendation list\> :arrow_right: \<proposed recommendation list\>
|
||||
|
||||
**Current description**
|
||||
**List**: \<current list\> :arrow_right: \<proposed list\>
|
||||
**Removal**: \<current recommendation list\>
|
||||
:arrow_right: \<proposed recommendation list\>
|
||||
|
||||
### Current description
|
||||
|
||||
> Current description
|
||||
|
||||
**Proposed description**
|
||||
### Proposed description
|
||||
|
||||
> Proposed description
|
||||
|
|
|
|||
6
.github/workflows/build_artifacts.yml
vendored
6
.github/workflows/build_artifacts.yml
vendored
|
|
@ -25,9 +25,9 @@ jobs:
|
|||
- graphics: glow
|
||||
renderer: "-opengl"
|
||||
- graphics: wgpu
|
||||
renderer: '' # Vulkan but we don't want this in the binary filename
|
||||
renderer: "" # Vulkan but we don't want this in the binary filename
|
||||
- update_feature: self-update
|
||||
update_name: '' # we don't want this in the binary filename
|
||||
update_name: "" # we don't want this in the binary filename
|
||||
- update_feature: no-self-update
|
||||
update_name: "-noseflupdate"
|
||||
steps:
|
||||
|
|
@ -62,4 +62,4 @@ jobs:
|
|||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: uad_gui${{ matrix.update_name }}-${{ matrix.build_target }}${{ matrix.renderer }}
|
||||
path: bin/uad_gui-*
|
||||
path: bin/uad_gui-*
|
||||
|
|
|
|||
18
.github/workflows/ci.yml
vendored
18
.github/workflows/ci.yml
vendored
|
|
@ -2,16 +2,16 @@ name: Continuous Integration
|
|||
on:
|
||||
push:
|
||||
paths:
|
||||
- '**.rs'
|
||||
- 'Cargo.lock'
|
||||
- 'Cargo.toml'
|
||||
- '**.json'
|
||||
- "**.rs"
|
||||
- "Cargo.lock"
|
||||
- "Cargo.toml"
|
||||
- "**.json"
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.rs'
|
||||
- 'Cargo.lock'
|
||||
- 'Cargo.toml'
|
||||
- '**.json'
|
||||
- "**.rs"
|
||||
- "Cargo.lock"
|
||||
- "Cargo.toml"
|
||||
- "**.json"
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
- lint: check
|
||||
args: " --all-features"
|
||||
- lint: test
|
||||
args: ''
|
||||
args: ""
|
||||
- lint: clippy
|
||||
args: " --all --all-features -- -D warnings"
|
||||
- lint: fmt
|
||||
|
|
|
|||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
|
|
@ -5,9 +5,9 @@ on:
|
|||
branches:
|
||||
- main
|
||||
paths:
|
||||
- '**.rs'
|
||||
- 'Cargo.lock'
|
||||
- 'Cargo.toml'
|
||||
- "**.rs"
|
||||
- "Cargo.lock"
|
||||
- "Cargo.toml"
|
||||
tags-ignore:
|
||||
- dev-build
|
||||
|
||||
|
|
|
|||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,3 +1,3 @@
|
|||
debug/
|
||||
target/
|
||||
*.log
|
||||
*.log
|
||||
|
|
|
|||
4
LICENSE
4
LICENSE
|
|
@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
|
|||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
Universal Android Debloater GUI
|
||||
Copyright (C) 2021 W1nst0n
|
||||
Copyright (C) 2021 W1nst0n
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
|
|||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) 2021 W1nst0n
|
||||
Universal Android Debloater GUI Copyright (C) 2021 W1nst0n
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
|
|
|||
176
README.md
176
README.md
|
|
@ -1,97 +1,122 @@
|
|||
# Universal Android Debloater GUI
|
||||
**DISCLAIMER**: Use at your own risk. I am not responsible for anything that could happen to your phone.
|
||||
|
||||
**DISCLAIMER**: Use at your own risk. I am not responsible for anything that
|
||||
could happen to your phone.
|
||||
|
||||
<img src="/resources/screenshots/v0.5.0.png" width="850" alt="uad_screenshot">
|
||||
|
||||
**This software is still in an early stage of development. Check out the issues, and feel free to contribute!**
|
||||
|
||||
## Summary
|
||||
This is a complete rewrite in Rust of the [UAD project](https://gitlab.com/W1nst0n/universal-android-debloater), which aims to improve privacy and battery performance by removing unnecessary and obscure system apps. This can also contribute to improve security by reducing [the attack surface](https://en.wikipedia.org/wiki/Attack_surface).
|
||||
|
||||
Packages are as well documented as possible in order to provide a better understanding of what you can delete or not. The worst thing which could happen is removing an essential system package needed during boot causing then an unfortunate bootloop. After about 5 failed system boots, the phone will automatically reboot in recovery mode and you'll have to perform a FACTORY RESET. So make a backup first!
|
||||
This is a complete rewrite in Rust of the [UAD project](https://gitlab.com/W1nst0n/universal-android-debloater),
|
||||
which aims to improve privacy and battery performance by removing unnecessary
|
||||
and obscure system apps.
|
||||
This can also contribute to improve security by reducing [the attack surface](https://en.wikipedia.org/wiki/Attack_surface).
|
||||
|
||||
In any case, you can NOT brick your device with this software! That's the main thing, right?
|
||||
Packages are as well documented as possible in order to provide a better
|
||||
understanding of what you can delete or not. The worst issue that could happen
|
||||
is removing an essential system package needed during boot causing then an unfortunate
|
||||
bootloop. After about 5 failed system boots, the phone will automatically reboot
|
||||
in recovery mode, and you'll have to perform a FACTORY RESET. Make a backup first!
|
||||
|
||||
In any case, you **CANNOT** brick your device with this software!
|
||||
That's the main point, right?
|
||||
|
||||
## Features
|
||||
* [X] Uninstall/Disable and Restore/Enable system packages
|
||||
* [X] Multi-user support (e.g apps in work profiles)
|
||||
* [X] Export/Import your selection in `uad_exported_selection.txt`
|
||||
* [X] Multi-device support: you can connect multiple phones at the same time
|
||||
* [X] All your actions are logged so you never forget what you've done
|
||||
|
||||
NB : System apps cannot really be uninstalled without root (see the [FAQ](https://github.com/0x192/universal-android-debloater/wiki/FAQ))
|
||||
- [x] Uninstall/Disable and Restore/Enable system packages
|
||||
- [x] Multi-user support (e.g. apps in work profiles)
|
||||
- [x] Export/Import your selection in `uad_exported_selection.txt`
|
||||
- [x] Multi-device support: you can connect multiple phones at the same time
|
||||
- [x] All your actions are logged, so you never forget what you've done
|
||||
|
||||
## Universal debloat lists
|
||||
* [X] GFAM (Google/Facebook/Amazon/Microsoft)
|
||||
* [X] AOSP
|
||||
* [X] Manufacturers (OEM)
|
||||
* [X] Mobile carriers
|
||||
* [X] Qualcomm / Mediatek / Miscellaneous
|
||||
NB : System apps cannot truly be uninstalled without root (see the [FAQ](https://github.com/0x192/universal-android-debloater/wiki/FAQ))
|
||||
|
||||
## Universal Debloat Lists
|
||||
|
||||
- [x] GFAM (Google/Facebook/Amazon/Microsoft)
|
||||
- [x] AOSP
|
||||
- [x] Manufacturers (OEM)
|
||||
- [x] Mobile carriers
|
||||
- [x] Qualcomm / Mediatek / Miscellaneous
|
||||
|
||||
## Manufacturers debloat lists
|
||||
* [ ] Archos
|
||||
* [X] Asus
|
||||
* [ ] Blackberry
|
||||
* [ ] Gionee
|
||||
* [X] LG
|
||||
* [X] Google
|
||||
* [ ] iQOO
|
||||
* [X] Fairphone
|
||||
* [ ] HTC
|
||||
* [X] Huawei
|
||||
* [X] Motorola
|
||||
* [X] Nokia
|
||||
* [X] OnePlus
|
||||
* [X] Oppo
|
||||
* [X] Realme
|
||||
* [X] Samsung
|
||||
* [X] Sony
|
||||
* [X] Tecno
|
||||
* [ ] TCL
|
||||
* [X] Unihertz
|
||||
* [X] Vivo/iQOO
|
||||
* [ ] Wiko
|
||||
* [X] Xiaomi
|
||||
* [X] ZTE
|
||||
|
||||
- [ ] Archos
|
||||
- [x] Asus
|
||||
- [ ] Blackberry
|
||||
- [ ] Gionee
|
||||
- [x] LG
|
||||
- [x] Google
|
||||
- [ ] iQOO
|
||||
- [x] Fairphone
|
||||
- [ ] HTC
|
||||
- [x] Huawei
|
||||
- [x] Motorola
|
||||
- [x] Nokia
|
||||
- [x] OnePlus
|
||||
- [x] Oppo
|
||||
- [x] Realme
|
||||
- [x] Samsung
|
||||
- [x] Sony
|
||||
- [x] Tecno
|
||||
- [ ] TCL
|
||||
- [x] Unihertz
|
||||
- [x] Vivo/iQOO
|
||||
- [ ] Wiko
|
||||
- [x] Xiaomi
|
||||
- [x] ZTE
|
||||
|
||||
## Mobile carriers debloat lists
|
||||
| Country | Carriers |
|
||||
|-----------------|-----------------------------------|
|
||||
| France | Orange, SFR, Free, Bouygues |
|
||||
| USA | T-Mobile, Verizon, Sprint, AT&T |
|
||||
| Germany | Telekom |
|
||||
| UK | EE |
|
||||
|
||||
| Country | Carriers |
|
||||
| ------- | ------------------------------- |
|
||||
| France | Orange, SFR, Free, Bouygues |
|
||||
| USA | T-Mobile, Verizon, Sprint, AT&T |
|
||||
| Germany | Telekom |
|
||||
| UK | EE |
|
||||
|
||||
## How to use it
|
||||
|
||||
- **Read the [FAQ](https://github.com/0x192/universal-android-debloater/wiki/FAQ)!**
|
||||
- **Do a proper backup of your data! You can never be too careful!**
|
||||
- Enable *Developer Options* on your smartphone.
|
||||
- Turn on *USB Debugging* from the developer panel.
|
||||
- From the settings, disconnect from any OEM accounts (when you delete an OEM account package it could lock you on the lockscreen because the phone can't associate your identity anymore)
|
||||
- Enable _Developer Options_ on your smartphone.
|
||||
- Turn on _USB Debugging_ from the developer panel.
|
||||
- From the settings, disconnect from any OEM accounts (when you delete an OEM
|
||||
account package it could lock you on the lockscreen because the phone can't
|
||||
associate your identity anymore)
|
||||
- Install ADB (see the intructions by clicking on your OS below):
|
||||
<p>
|
||||
<details>
|
||||
<summary>LINUX</summary>
|
||||
|
||||
- Install *Android platform tools* on your PC :
|
||||
- Install _Android platform tools_ on your PC :
|
||||
|
||||
Debian Base:
|
||||
|
||||
```bash
|
||||
$ sudo apt install android-sdk-platform-tools
|
||||
sudo apt install android-sdk-platform-tools
|
||||
```
|
||||
|
||||
Arch-Linux Base:
|
||||
|
||||
```bash
|
||||
$ sudo pacman -S android-tools
|
||||
sudo pacman -S android-tools
|
||||
```
|
||||
|
||||
Red Hat Base:
|
||||
|
||||
```bash
|
||||
$ sudo yum install android-tools
|
||||
sudo yum install android-tools
|
||||
```
|
||||
|
||||
OpenSUSE Base:
|
||||
|
||||
```bash
|
||||
$ sudo zypper install android-tools
|
||||
sudo zypper install android-tools
|
||||
```
|
||||
|
||||
</details>
|
||||
</p>
|
||||
|
||||
|
|
@ -100,42 +125,55 @@ NB : System apps cannot really be uninstalled without root (see the [FAQ](https:
|
|||
<summary>MAC OS</summary>
|
||||
|
||||
- Install [Homebrew](https://brew.sh/)
|
||||
- Install *Android platform tools*
|
||||
- Install _Android platform tools_
|
||||
|
||||
```bash
|
||||
$ brew install android-platform-tools
|
||||
brew install android-platform-tools
|
||||
```
|
||||
</details>
|
||||
</p>
|
||||
|
||||
</details>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<details>
|
||||
<summary>WINDOWS</summary>
|
||||
|
||||
- Download [android platform tools](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) and unzip it somewhere.
|
||||
- [Add the android platform tools to your PATH](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) **OR** make sure to launch UAD from the same directory.
|
||||
- Download [android platform tools](https://dl.google.com/android/repository/platform-tools-latest-windows.zip)
|
||||
and unzip it somewhere.
|
||||
- [Add the android platform tools to your PATH](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/)
|
||||
**OR** make sure to launch UAD from the same directory.
|
||||
|
||||
- [Install USB drivers for your device](https://developer.android.com/studio/run/oem-usb#Drivers)
|
||||
- Check your device is detected:
|
||||
```batch
|
||||
> adb devices
|
||||
|
||||
```bash
|
||||
adb devices
|
||||
```
|
||||
</details>
|
||||
</p>
|
||||
|
||||
</details>
|
||||
</p>
|
||||
|
||||
- Download the latest release of UAD GUI for your Operating System [here](https://github.com/0x192/universal-android-debloater/releases). Take the `opengl` version only if the default version (with a Vulkan backend) doesn't launch.
|
||||
- Download the latest release of UAD GUI for your Operating System [here](https://github.com/0x192/universal-android-debloater/releases).
|
||||
Take the `opengl` version only if the default version (with a Vulkan backend)
|
||||
doesn't launch.
|
||||
|
||||
**NOTE:** Chinese phones users may need to use the AOSP list for removing some stock apps because those Chinese manufacturers (especially Xiaomi and Huawei) have been using the name of AOSP packages for their own (modified & closed-source) apps.
|
||||
**NOTE:** Chinese phones users may need to use the AOSP list for removing some stock
|
||||
apps because those Chinese manufacturers (especially Xiaomi and Huawei) have been
|
||||
using the name of AOSP packages for their own (modified & closed-source) apps.
|
||||
|
||||
**IMPORTANT NOTE:** You will have to run this software whenever your OEM pushes an update to your phone as some *uninstalled* system apps could be reinstalled.
|
||||
**IMPORTANT NOTE:** You will have to run this software whenever your OEM pushes
|
||||
an update to your phone as some _uninstalled_ system apps could be reinstalled.
|
||||
|
||||
## How to contribute
|
||||
|
||||
Hey-hey-hey! Don't go away so fast! This is a community project. That means I need you! I'm sure you want to make this project better anyway.
|
||||
Hey-hey-hey! Don't go away so fast! This is a community project.
|
||||
That means I need you! I'm sure you want to make this project better anyway.
|
||||
|
||||
==> [How to contribute](https://github.com/0x192/universal-android-debloater/wiki)
|
||||
|
||||
## Special thanks
|
||||
|
||||
- [@mawilms](https://github.com/mawilms) for his LotRO plugin manager ([Lembas](https://github.com/mawilms/lembas)) which helped me a lot to understand how to use the [Iced](https://github.com/hecrj/iced) GUI library.
|
||||
- [@mawilms](https://github.com/mawilms) for his LotRO plugin manager ([Lembas](https://github.com/mawilms/lembas))
|
||||
which helped me a lot to understand how to use the [Iced](https://github.com/hecrj/iced)
|
||||
GUI library.
|
||||
- [@casperstorm](https://github.com/casperstorm) for the UI/UX inspiration.
|
||||
|
|
|
|||
|
|
@ -55,43 +55,38 @@ static CONFIG_FILE: PathBuf = CONFIG_DIR.join("config.toml");
|
|||
impl Config {
|
||||
pub fn save_changes(settings: &Settings, device_id: &String) {
|
||||
let mut config = Self::load_configuration_file();
|
||||
match config
|
||||
if let Some(device) = config
|
||||
.devices
|
||||
.iter_mut()
|
||||
.find(|x| x.device_id == *device_id)
|
||||
{
|
||||
Some(device) => {
|
||||
*device = settings.device.clone();
|
||||
config.general = settings.general.clone();
|
||||
}
|
||||
None => {
|
||||
debug!("config: New device settings saved");
|
||||
config.devices.push(settings.device.clone());
|
||||
config.general = settings.general.clone();
|
||||
}
|
||||
*device = settings.device.clone();
|
||||
} else {
|
||||
debug!("config: New device settings saved");
|
||||
config.devices.push(settings.device.clone());
|
||||
}
|
||||
config.general = settings.general.clone();
|
||||
let toml = toml::to_string(&config).unwrap();
|
||||
fs::write(&*CONFIG_FILE, toml).expect("Could not write config file to disk!");
|
||||
}
|
||||
|
||||
#[allow(clippy::option_if_let_else)]
|
||||
pub fn load_configuration_file() -> Self {
|
||||
match fs::read_to_string(&*CONFIG_FILE) {
|
||||
Ok(s) => match toml::from_str(&s) {
|
||||
if let Ok(s) = fs::read_to_string(&*CONFIG_FILE) {
|
||||
match toml::from_str(&s) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
error!("Invalid config file: `{}`", e);
|
||||
error!("Restoring default config file");
|
||||
let toml = toml::to_string(&Config::default()).unwrap();
|
||||
let toml = toml::to_string(&Self::default()).unwrap();
|
||||
fs::write(&*CONFIG_FILE, toml).expect("Could not write config file to disk!");
|
||||
Config::default()
|
||||
Self::default()
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
let default_conf = toml::to_string(&Config::default()).unwrap();
|
||||
fs::write(&*CONFIG_FILE, default_conf)
|
||||
.expect("Could not write config file to disk!");
|
||||
Config::default()
|
||||
}
|
||||
} else {
|
||||
let default_conf = toml::to_string(&Self::default()).unwrap();
|
||||
fs::write(&*CONFIG_FILE, default_conf).expect("Could not write config file to disk!");
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ pub async fn backup_phone(
|
|||
user_backup.packages.push(CorePackage {
|
||||
name: p.name.clone(),
|
||||
state: p.state,
|
||||
})
|
||||
});
|
||||
}
|
||||
backup.users.push(user_backup);
|
||||
}
|
||||
|
|
@ -71,6 +71,7 @@ pub async fn backup_phone(
|
|||
}
|
||||
|
||||
pub fn list_available_backups(dir: &Path) -> Vec<DisplayablePath> {
|
||||
#[allow(clippy::option_if_let_else)]
|
||||
match fs::read_dir(dir) {
|
||||
Ok(files) => files
|
||||
.filter_map(|e| e.ok())
|
||||
|
|
@ -129,15 +130,14 @@ pub fn restore_backup(
|
|||
|
||||
let mut commands = vec![];
|
||||
for u in phone_backup.users {
|
||||
let mut _index = 0;
|
||||
match selected_device.user_list.iter().find(|x| x.id == u.id) {
|
||||
Some(i) => _index = i.index,
|
||||
let index = match selected_device.user_list.iter().find(|x| x.id == u.id) {
|
||||
Some(i) => i.index,
|
||||
None => return Err(format!("user {} doesn't exist", u.id)),
|
||||
};
|
||||
|
||||
for (i, backup_package) in u.packages.iter().enumerate() {
|
||||
let package: CorePackage;
|
||||
match packages[_index]
|
||||
match packages[index]
|
||||
.iter()
|
||||
.find(|x| x.name == backup_package.name)
|
||||
{
|
||||
|
|
@ -150,8 +150,8 @@ pub fn restore_backup(
|
|||
}
|
||||
}
|
||||
let p_commands = apply_pkg_state_commands(
|
||||
package,
|
||||
&backup_package.state,
|
||||
&package,
|
||||
backup_package.state,
|
||||
&settings
|
||||
.backup
|
||||
.selected_user
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ impl Default for Phone {
|
|||
model: "fetching devices...".to_string(),
|
||||
android_sdk: 0,
|
||||
user_list: vec![],
|
||||
adb_id: "".to_string(),
|
||||
adb_id: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -54,9 +54,10 @@ impl std::fmt::Display for User {
|
|||
}
|
||||
|
||||
pub fn adb_shell_command(shell: bool, args: &str) -> Result<String, String> {
|
||||
let adb_command = match shell {
|
||||
true => vec!["shell", args],
|
||||
false => vec![args],
|
||||
let adb_command = if shell {
|
||||
vec!["shell", args]
|
||||
} else {
|
||||
vec![args]
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
|
|
@ -77,7 +78,12 @@ pub fn adb_shell_command(shell: bool, args: &str) -> Result<String, String> {
|
|||
Err("ADB was not found".to_string())
|
||||
}
|
||||
Ok(o) => {
|
||||
if !o.status.success() {
|
||||
if o.status.success() {
|
||||
Ok(String::from_utf8(o.stdout)
|
||||
.map_err(|e| e.to_string())?
|
||||
.trim_end()
|
||||
.to_string())
|
||||
} else {
|
||||
let stdout = String::from_utf8(o.stdout)
|
||||
.map_err(|e| e.to_string())?
|
||||
.trim_end()
|
||||
|
|
@ -90,11 +96,6 @@ pub fn adb_shell_command(shell: bool, args: &str) -> Result<String, String> {
|
|||
// ADB does really weird things. Some errors are not redirected to stderr
|
||||
let err = if stdout.is_empty() { stderr } else { stdout };
|
||||
Err(err)
|
||||
} else {
|
||||
Ok(String::from_utf8(o.stdout)
|
||||
.map_err(|e| e.to_string())?
|
||||
.trim_end()
|
||||
.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -139,26 +140,28 @@ pub async fn perform_adb_commands(
|
|||
}
|
||||
|
||||
pub fn list_all_system_packages(user_id: Option<&User>) -> String {
|
||||
#[allow(clippy::option_if_let_else)]
|
||||
let action = match user_id {
|
||||
Some(user_id) => format!("pm list packages -s -u --user {}", user_id.id),
|
||||
None => "pm list packages -s -u".to_string(),
|
||||
};
|
||||
|
||||
adb_shell_command(true, &action)
|
||||
.unwrap_or_else(|_| "".to_string())
|
||||
.unwrap_or_else(|_| String::new())
|
||||
.replace("package:", "")
|
||||
}
|
||||
|
||||
pub fn hashset_system_packages(state: PackageState, user_id: Option<&User>) -> HashSet<String> {
|
||||
#[allow(clippy::option_if_let_else)]
|
||||
let user = match user_id {
|
||||
Some(user_id) => format!(" --user {}", user_id.id),
|
||||
None => "".to_string(),
|
||||
None => String::new(),
|
||||
};
|
||||
|
||||
let action = match state {
|
||||
PackageState::Enabled => format!("pm list packages -s -e{user}"),
|
||||
PackageState::Disabled => format!("pm list package -s -d{user}"),
|
||||
_ => "".to_string(), // You probably don't need to use this function for anything else
|
||||
_ => String::new(), // You probably don't need to use this function for anything else
|
||||
};
|
||||
|
||||
adb_shell_command(true, &action)
|
||||
|
|
@ -178,7 +181,7 @@ pub struct CorePackage {
|
|||
|
||||
impl From<&mut PackageRow> for CorePackage {
|
||||
fn from(pr: &mut PackageRow) -> Self {
|
||||
CorePackage {
|
||||
Self {
|
||||
name: pr.name.clone(),
|
||||
state: pr.state,
|
||||
}
|
||||
|
|
@ -186,7 +189,7 @@ impl From<&mut PackageRow> for CorePackage {
|
|||
}
|
||||
impl From<PackageRow> for CorePackage {
|
||||
fn from(pr: PackageRow) -> Self {
|
||||
CorePackage {
|
||||
Self {
|
||||
name: pr.name.clone(),
|
||||
state: pr.state,
|
||||
}
|
||||
|
|
@ -195,7 +198,7 @@ impl From<PackageRow> for CorePackage {
|
|||
|
||||
impl From<&PackageRow> for CorePackage {
|
||||
fn from(pr: &PackageRow) -> Self {
|
||||
CorePackage {
|
||||
Self {
|
||||
name: pr.name.clone(),
|
||||
state: pr.state,
|
||||
}
|
||||
|
|
@ -203,8 +206,8 @@ impl From<&PackageRow> for CorePackage {
|
|||
}
|
||||
|
||||
pub fn apply_pkg_state_commands(
|
||||
package: CorePackage,
|
||||
wanted_state: &PackageState,
|
||||
package: &CorePackage,
|
||||
wanted_state: PackageState,
|
||||
selected_user: &User,
|
||||
phone: &Phone,
|
||||
) -> Vec<String> {
|
||||
|
|
@ -242,24 +245,25 @@ pub fn apply_pkg_state_commands(
|
|||
},
|
||||
_ => vec![],
|
||||
},
|
||||
_ => vec![],
|
||||
PackageState::All => vec![],
|
||||
};
|
||||
if phone.android_sdk < 21 {
|
||||
request_builder(commands, &package.name, None)
|
||||
request_builder(&commands, &package.name, None)
|
||||
} else {
|
||||
request_builder(commands, &package.name, Some(selected_user))
|
||||
request_builder(&commands, &package.name, Some(selected_user))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn request_builder(commands: Vec<&str>, package: &str, user: Option<&User>) -> Vec<String> {
|
||||
if let Some(u) = user {
|
||||
commands
|
||||
.iter()
|
||||
.map(|c| format!("{} --user {} {}", c, u.id, package))
|
||||
.collect()
|
||||
} else {
|
||||
commands.iter().map(|c| format!("{c} {package}")).collect()
|
||||
}
|
||||
pub fn request_builder(commands: &[&str], package: &str, user: Option<&User>) -> Vec<String> {
|
||||
user.map_or_else(
|
||||
|| commands.iter().map(|c| format!("{c} {package}")).collect(),
|
||||
|u| {
|
||||
commands
|
||||
.iter()
|
||||
.map(|c| format!("{} --user {} {}", c, u.id, package))
|
||||
.collect()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_phone_model() -> String {
|
||||
|
|
@ -277,17 +281,14 @@ pub fn get_phone_model() -> String {
|
|||
}
|
||||
|
||||
pub fn get_android_sdk() -> u8 {
|
||||
match adb_shell_command(true, "getprop ro.build.version.sdk") {
|
||||
Ok(sdk) => sdk.parse().unwrap(),
|
||||
Err(_) => 0,
|
||||
}
|
||||
adb_shell_command(true, "getprop ro.build.version.sdk").map_or(0, |sdk| sdk.parse().unwrap())
|
||||
}
|
||||
|
||||
pub fn get_phone_brand() -> String {
|
||||
format!(
|
||||
"{} {}",
|
||||
adb_shell_command(true, "getprop ro.product.brand")
|
||||
.unwrap_or_else(|_| "".to_string())
|
||||
.unwrap_or_else(|_| String::new())
|
||||
.trim(),
|
||||
get_phone_model()
|
||||
)
|
||||
|
|
@ -300,6 +301,8 @@ pub fn is_protected_user(user_id: &str) -> bool {
|
|||
pub fn get_user_list() -> Vec<User> {
|
||||
#[dynamic]
|
||||
static RE: Regex = Regex::new(r"\{([0-9]+)").unwrap();
|
||||
|
||||
#[allow(clippy::option_if_let_else)]
|
||||
match adb_shell_command(true, "pm list users") {
|
||||
Ok(users) => RE
|
||||
.find_iter(&users)
|
||||
|
|
@ -316,7 +319,7 @@ pub fn get_user_list() -> Vec<User> {
|
|||
|
||||
// getprop ro.serialno
|
||||
pub async fn get_devices_list() -> Vec<Phone> {
|
||||
match retry(
|
||||
retry(
|
||||
Fixed::from_millis(500).take(120),
|
||||
|| match adb_shell_command(false, "devices") {
|
||||
Ok(devices) => {
|
||||
|
|
@ -341,8 +344,6 @@ pub async fn get_devices_list() -> Vec<Phone> {
|
|||
OperationResult::Retry(test)
|
||||
}
|
||||
},
|
||||
) {
|
||||
Ok(devices) => devices,
|
||||
Err(_) => vec![],
|
||||
}
|
||||
)
|
||||
.map_or_else(|_| vec![], |devices| devices)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub struct ColorPalette {
|
|||
|
||||
impl Theme {
|
||||
pub const ALL: [Self; 3] = [Self::Lupin, Self::Dark, Self::Light];
|
||||
pub fn palette(&self) -> ColorPalette {
|
||||
pub fn palette(self) -> ColorPalette {
|
||||
match self {
|
||||
Self::Dark => ColorPalette {
|
||||
base: BaseColors {
|
||||
|
|
@ -105,9 +105,9 @@ impl std::fmt::Display for Theme {
|
|||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Theme::Dark => "Dark",
|
||||
Theme::Light => "Light",
|
||||
Theme::Lupin => "Lupin",
|
||||
Self::Dark => "Dark",
|
||||
Self::Light => "Light",
|
||||
Self::Lupin => "Lupin",
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,24 +44,24 @@ impl std::fmt::Display for UadListState {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let date = last_modified_date(CACHE_DIR.join("uad_lists.json"));
|
||||
let s = match self {
|
||||
UadListState::Downloading => "Checking updates...".to_string(),
|
||||
UadListState::Done => format!("Done (last was {})", format_diff_time_from_now(date)),
|
||||
UadListState::Failed => "Failed to check update!".to_string(),
|
||||
Self::Downloading => "Checking updates...".to_string(),
|
||||
Self::Done => format!("Done (last was {})", format_diff_time_from_now(date)),
|
||||
Self::Failed => "Failed to check update!".to_string(),
|
||||
};
|
||||
write!(f, "{s}")
|
||||
}
|
||||
}
|
||||
|
||||
impl UadList {
|
||||
pub const ALL: [UadList; 8] = [
|
||||
UadList::All,
|
||||
UadList::Aosp,
|
||||
UadList::Carrier,
|
||||
UadList::Google,
|
||||
UadList::Misc,
|
||||
UadList::Oem,
|
||||
UadList::Pending,
|
||||
UadList::Unlisted,
|
||||
pub const ALL: [Self; 8] = [
|
||||
Self::All,
|
||||
Self::Aosp,
|
||||
Self::Carrier,
|
||||
Self::Google,
|
||||
Self::Misc,
|
||||
Self::Oem,
|
||||
Self::Pending,
|
||||
Self::Unlisted,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -71,14 +71,14 @@ impl std::fmt::Display for UadList {
|
|||
f,
|
||||
"{}",
|
||||
match self {
|
||||
UadList::All => "All lists",
|
||||
UadList::Aosp => "aosp",
|
||||
UadList::Carrier => "carrier",
|
||||
UadList::Google => "google",
|
||||
UadList::Misc => "misc",
|
||||
UadList::Oem => "oem",
|
||||
UadList::Pending => "pending",
|
||||
UadList::Unlisted => "unlisted",
|
||||
Self::All => "All lists",
|
||||
Self::Aosp => "aosp",
|
||||
Self::Carrier => "carrier",
|
||||
Self::Google => "google",
|
||||
Self::Misc => "misc",
|
||||
Self::Oem => "oem",
|
||||
Self::Pending => "pending",
|
||||
Self::Unlisted => "unlisted",
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -94,12 +94,7 @@ pub enum PackageState {
|
|||
}
|
||||
|
||||
impl PackageState {
|
||||
pub const ALL: [PackageState; 4] = [
|
||||
PackageState::All,
|
||||
PackageState::Enabled,
|
||||
PackageState::Uninstalled,
|
||||
PackageState::Disabled,
|
||||
];
|
||||
pub const ALL: [Self; 4] = [Self::All, Self::Enabled, Self::Uninstalled, Self::Disabled];
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PackageState {
|
||||
|
|
@ -108,10 +103,10 @@ impl std::fmt::Display for PackageState {
|
|||
f,
|
||||
"{}",
|
||||
match self {
|
||||
PackageState::All => "All packages",
|
||||
PackageState::Enabled => "Enabled",
|
||||
PackageState::Uninstalled => "Uninstalled",
|
||||
PackageState::Disabled => "Disabled",
|
||||
Self::All => "All packages",
|
||||
Self::Enabled => "Enabled",
|
||||
Self::Uninstalled => "Uninstalled",
|
||||
Self::Disabled => "Disabled",
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -122,17 +117,17 @@ pub trait Opposite {
|
|||
}
|
||||
|
||||
impl Opposite for PackageState {
|
||||
fn opposite(&self, disable: bool) -> PackageState {
|
||||
fn opposite(&self, disable: bool) -> Self {
|
||||
match self {
|
||||
PackageState::Enabled => {
|
||||
Self::Enabled => {
|
||||
if disable {
|
||||
PackageState::Disabled
|
||||
Self::Disabled
|
||||
} else {
|
||||
PackageState::Uninstalled
|
||||
Self::Uninstalled
|
||||
}
|
||||
}
|
||||
PackageState::Uninstalled | PackageState::Disabled => PackageState::Enabled,
|
||||
PackageState::All => PackageState::All,
|
||||
Self::Uninstalled | Self::Disabled => Self::Enabled,
|
||||
Self::All => Self::All,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -150,13 +145,13 @@ pub enum Removal {
|
|||
}
|
||||
|
||||
impl Removal {
|
||||
pub const ALL: [Removal; 6] = [
|
||||
Removal::All,
|
||||
Removal::Recommended,
|
||||
Removal::Advanced,
|
||||
Removal::Expert,
|
||||
Removal::Unsafe,
|
||||
Removal::Unlisted,
|
||||
pub const ALL: [Self; 6] = [
|
||||
Self::All,
|
||||
Self::Recommended,
|
||||
Self::Advanced,
|
||||
Self::Expert,
|
||||
Self::Unsafe,
|
||||
Self::Unlisted,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -166,12 +161,12 @@ impl std::fmt::Display for Removal {
|
|||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Removal::All => "All",
|
||||
Removal::Recommended => "Recommended",
|
||||
Removal::Advanced => "Advanced",
|
||||
Removal::Expert => "Expert",
|
||||
Removal::Unsafe => "Unsafe",
|
||||
Removal::Unlisted => "Unlisted",
|
||||
Self::All => "All",
|
||||
Self::Recommended => "Recommended",
|
||||
Self::Advanced => "Advanced",
|
||||
Self::Expert => "Expert",
|
||||
Self::Unsafe => "Unsafe",
|
||||
Self::Unlisted => "Unlisted",
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -182,10 +177,10 @@ pub fn load_debloat_lists(remote: bool) -> (Result<PackageHashMap, PackageHashMa
|
|||
let cached_uad_lists: PathBuf = CACHE_DIR.join("uad_lists.json");
|
||||
let mut error = false;
|
||||
let list: Vec<Package> = if remote {
|
||||
match retry(Fixed::from_millis(1000).take(60), || {
|
||||
retry(Fixed::from_millis(1000).take(60), || {
|
||||
match ureq::get(
|
||||
"https://raw.githubusercontent.com/0x192/universal-android-debloater/\
|
||||
main/resources/assets/uad_lists.json",
|
||||
main/resources/assets/uad_lists.json",
|
||||
)
|
||||
.call()
|
||||
{
|
||||
|
|
@ -201,10 +196,8 @@ pub fn load_debloat_lists(remote: bool) -> (Result<PackageHashMap, PackageHashMa
|
|||
OperationResult::Retry(Vec::<Package>::new())
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Ok(list) => list,
|
||||
Err(_) => get_local_lists(),
|
||||
}
|
||||
})
|
||||
.map_or_else(|_| get_local_lists(), |list| list)
|
||||
} else {
|
||||
warn!("Could not load remote debloat list");
|
||||
get_local_lists()
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ pub enum SelfUpdateStatus {
|
|||
impl std::fmt::Display for SelfUpdateStatus {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let s = match self {
|
||||
SelfUpdateStatus::Checking => "Checking updates...",
|
||||
SelfUpdateStatus::Updating => "Updating...",
|
||||
SelfUpdateStatus::Failed => "Failed to check update!",
|
||||
SelfUpdateStatus::Done => "Done",
|
||||
Self::Checking => "Checking updates...",
|
||||
Self::Updating => "Updating...",
|
||||
Self::Failed => "Failed to check update!",
|
||||
Self::Done => "Done",
|
||||
};
|
||||
write!(f, "{s}")
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ impl std::fmt::Display for SelfUpdateStatus {
|
|||
|
||||
/// Download a file from the internet
|
||||
#[cfg(feature = "self-update")]
|
||||
pub async fn download_file<T: ToString>(url: T, dest_file: PathBuf) -> Result<(), String> {
|
||||
pub async fn download_file<T: ToString + Send>(url: T, dest_file: PathBuf) -> Result<(), String> {
|
||||
let url = url.to_string();
|
||||
debug!("downloading file from {}", &url);
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ pub fn get_latest_release() -> Result<Option<Release>, ()> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Extracts the binary from a `tar.gz` archive to temp_file path
|
||||
/// Extracts the binary from a `tar.gz` archive to `temp_file` path
|
||||
#[cfg(feature = "self-update")]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn extract_binary_from_tar(archive_path: &Path, temp_file: &Path) -> io::Result<()> {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ pub fn fetch_packages(
|
|||
if uad_lists.contains_key(p_name) {
|
||||
description = &uad_lists.get(p_name).unwrap().description;
|
||||
if description.is_empty() {
|
||||
description = "[No description] : CONTRIBUTION WELCOMED"
|
||||
description = "[No description] : CONTRIBUTION WELCOMED";
|
||||
};
|
||||
uad_list = uad_lists.get(p_name).unwrap().list;
|
||||
removal = uad_lists.get(p_name).unwrap().removal;
|
||||
|
|
@ -51,8 +51,8 @@ pub fn fetch_packages(
|
|||
user_package
|
||||
}
|
||||
|
||||
pub fn string_to_theme(theme: String) -> Theme {
|
||||
match theme.as_str() {
|
||||
pub fn string_to_theme(theme: &str) -> Theme {
|
||||
match theme {
|
||||
"Dark" => Theme::Dark,
|
||||
"Light" => Theme::Light,
|
||||
"Lupin" => Theme::Lupin,
|
||||
|
|
@ -80,21 +80,20 @@ pub fn open_url(dir: PathBuf) {
|
|||
Ok(o) => {
|
||||
if !o.status.success() {
|
||||
let stderr = String::from_utf8(o.stderr).unwrap().trim_end().to_string();
|
||||
error!("Can't open the following URL: {}", stderr)
|
||||
error!("Can't open the following URL: {}", stderr);
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Failed to run command to open the file explorer: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(clippy::option_if_let_else)]
|
||||
pub fn last_modified_date(file: PathBuf) -> DateTime<Utc> {
|
||||
match fs::metadata(file) {
|
||||
Ok(metadata) => match metadata.modified() {
|
||||
Ok(time) => time.into(),
|
||||
Err(_) => Utc::now(),
|
||||
},
|
||||
fs::metadata(file).map_or_else(|_| Utc::now(), |metadata| match metadata.modified() {
|
||||
Ok(time) => time.into(),
|
||||
Err(_) => Utc::now(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn format_diff_time_from_now(date: DateTime<Utc>) -> String {
|
||||
|
|
@ -118,19 +117,20 @@ pub struct DisplayablePath {
|
|||
|
||||
impl fmt::Display for DisplayablePath {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let stem = match self.path.file_stem() {
|
||||
Some(p) => match p.to_os_string().into_string() {
|
||||
let stem = self.path.file_stem().map_or_else(
|
||||
|| {
|
||||
error!("[PATH STEM]: No file stem found");
|
||||
"[File steam not found]".to_string()
|
||||
},
|
||||
|p| match p.to_os_string().into_string() {
|
||||
Ok(stem) => stem,
|
||||
Err(e) => {
|
||||
error!("[PATH ENCODING]: {:?}", e);
|
||||
"[PATH ENCODING ERROR]".to_string()
|
||||
}
|
||||
},
|
||||
None => {
|
||||
error!("[PATH STEM]: No file stem found");
|
||||
"[File steam not found]".to_string()
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
write!(f, "{stem}")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ impl Application for UadGui {
|
|||
}
|
||||
|
||||
fn theme(&self) -> Theme {
|
||||
string_to_theme(self.settings_view.general.theme.clone())
|
||||
string_to_theme(&self.settings_view.general.theme)
|
||||
}
|
||||
|
||||
fn title(&self) -> String {
|
||||
|
|
@ -95,6 +95,7 @@ impl Application for UadGui {
|
|||
}
|
||||
fn update(&mut self, msg: Message) -> Command<Message> {
|
||||
match msg {
|
||||
#[allow(clippy::option_if_let_else)]
|
||||
Message::LoadDevices(devices_list) => {
|
||||
self.selected_device = match &self.selected_device {
|
||||
Some(s_device) => {
|
||||
|
|
@ -102,9 +103,9 @@ impl Application for UadGui {
|
|||
devices_list
|
||||
.iter()
|
||||
.find(|phone| phone.adb_id == s_device.adb_id)
|
||||
.map(|x| x.to_owned())
|
||||
.cloned()
|
||||
}
|
||||
None => devices_list.first().map(|x| x.to_owned()),
|
||||
None => devices_list.first().cloned(),
|
||||
};
|
||||
self.devices_list = devices_list;
|
||||
|
||||
|
|
@ -210,7 +211,7 @@ impl Application for UadGui {
|
|||
AboutMessage::UpdateUadLists => {
|
||||
self.update_state.uad_list = UadListState::Downloading;
|
||||
self.apps_view.loading_state =
|
||||
ListLoadingState::DownloadingList("".to_string());
|
||||
ListLoadingState::DownloadingList(String::new());
|
||||
self.update(Message::AppsAction(AppsMessage::LoadUadList(true)))
|
||||
}
|
||||
AboutMessage::DoSelfUpdate => {
|
||||
|
|
@ -218,7 +219,7 @@ impl Application for UadGui {
|
|||
if self.update_state.self_update.latest_release.is_some() {
|
||||
self.update_state.self_update.status = SelfUpdateStatus::Updating;
|
||||
self.apps_view.loading_state =
|
||||
ListLoadingState::_UpdatingUad("".to_string());
|
||||
ListLoadingState::_UpdatingUad(String::new());
|
||||
let bin_name = bin_name().to_owned();
|
||||
let release = self
|
||||
.update_state
|
||||
|
|
@ -237,7 +238,7 @@ impl Application for UadGui {
|
|||
#[cfg(not(feature = "self-update"))]
|
||||
Command::none()
|
||||
}
|
||||
_ => Command::none(),
|
||||
AboutMessage::UrlPressed(_) => Command::none(),
|
||||
}
|
||||
}
|
||||
Message::DeviceSelected(s_device) => {
|
||||
|
|
@ -250,7 +251,7 @@ impl Application for UadGui {
|
|||
s_device.android_sdk, s_device.model
|
||||
);
|
||||
info!("{:-^65}", "-");
|
||||
self.apps_view.loading_state = ListLoadingState::FindingPhones("".to_string());
|
||||
self.apps_view.loading_state = ListLoadingState::FindingPhones(String::new());
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
{
|
||||
|
|
@ -261,48 +262,46 @@ impl Application for UadGui {
|
|||
UadListState::Done,
|
||||
))))
|
||||
}
|
||||
Message::_NewReleaseDownloaded(_res) => {
|
||||
Message::_NewReleaseDownloaded(res) => {
|
||||
debug!("UAD update has been download!");
|
||||
|
||||
#[cfg(feature = "self-update")]
|
||||
match _res {
|
||||
Ok((relaunch_path, cleanup_path)) => {
|
||||
// Remove first arg, which is path to binary. We don't use this first
|
||||
// arg as binary path because it's not reliable, per the docs.
|
||||
let mut args = std::env::args();
|
||||
args.next();
|
||||
let mut args: Vec<_> = args.collect();
|
||||
if let Ok((relaunch_path, cleanup_path)) = res {
|
||||
// Remove first arg, which is path to binary. We don't use this first
|
||||
// arg as binary path because it's not reliable, per the docs.
|
||||
let mut args = std::env::args();
|
||||
args.next();
|
||||
let mut args: Vec<_> = args.collect();
|
||||
|
||||
// Remove the `--self-update-temp` arg from args if it exists,
|
||||
// since we need to pass it cleanly. Otherwise new process will
|
||||
// fail during arg parsing.
|
||||
if let Some(idx) = args.iter().position(|a| a == "--self-update-temp") {
|
||||
args.remove(idx);
|
||||
// Remove path passed after this arg
|
||||
args.remove(idx);
|
||||
// Remove the `--self-update-temp` arg from args if it exists,
|
||||
// since we need to pass it cleanly. Otherwise new process will
|
||||
// fail during arg parsing.
|
||||
if let Some(idx) = args.iter().position(|a| a == "--self-update-temp") {
|
||||
args.remove(idx);
|
||||
// Remove path passed after this arg
|
||||
args.remove(idx);
|
||||
}
|
||||
|
||||
match std::process::Command::new(relaunch_path)
|
||||
.args(args)
|
||||
.arg("--self-update-temp")
|
||||
.arg(&cleanup_path)
|
||||
.spawn()
|
||||
{
|
||||
Ok(_) => {
|
||||
if let Err(e) = remove_file(cleanup_path) {
|
||||
error!("Could not remove temp update file: {}", e);
|
||||
}
|
||||
std::process::exit(0)
|
||||
}
|
||||
|
||||
match std::process::Command::new(relaunch_path)
|
||||
.args(args)
|
||||
.arg("--self-update-temp")
|
||||
.arg(&cleanup_path)
|
||||
.spawn()
|
||||
{
|
||||
Ok(_) => {
|
||||
if let Err(e) = remove_file(cleanup_path) {
|
||||
error!("Could not remove temp update file: {}", e);
|
||||
}
|
||||
std::process::exit(0)
|
||||
}
|
||||
Err(error) => {
|
||||
if let Err(e) = remove_file(cleanup_path) {
|
||||
error!("Could not remove temp update file: {}", e);
|
||||
}
|
||||
error!("Failed to update UAD: {}", error)
|
||||
Err(error) => {
|
||||
if let Err(e) = remove_file(cleanup_path) {
|
||||
error!("Could not remove temp update file: {}", e);
|
||||
}
|
||||
error!("Failed to update UAD: {}", error);
|
||||
}
|
||||
}
|
||||
Err(()) => error!("Failed to update UAD!"),
|
||||
} else {
|
||||
error!("Failed to update UAD!");
|
||||
}
|
||||
Command::none()
|
||||
}
|
||||
|
|
@ -310,13 +309,13 @@ impl Application for UadGui {
|
|||
match release {
|
||||
Ok(r) => {
|
||||
self.update_state.self_update.status = SelfUpdateStatus::Done;
|
||||
self.update_state.self_update.latest_release = r
|
||||
self.update_state.self_update.latest_release = r;
|
||||
}
|
||||
Err(_) => self.update_state.self_update.status = SelfUpdateStatus::Failed,
|
||||
};
|
||||
Command::none()
|
||||
}
|
||||
_ => Command::none(),
|
||||
Message::Nothing => Command::none(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,11 +102,9 @@ impl button::StyleSheet for Theme {
|
|||
};
|
||||
|
||||
match style {
|
||||
Button::Primary => active_appearance(None, p.bright.primary),
|
||||
Button::Unavailable => active_appearance(None, p.bright.error),
|
||||
Button::Refresh => active_appearance(None, p.bright.primary),
|
||||
Button::SelfUpdate => active_appearance(None, p.bright.primary),
|
||||
Button::UninstallPackage => active_appearance(None, p.bright.error),
|
||||
Button::Primary | Button::SelfUpdate | Button::Refresh => {
|
||||
active_appearance(None, p.bright.primary)
|
||||
}
|
||||
Button::RestorePackage => active_appearance(None, p.bright.secondary),
|
||||
Button::NormalPackage => button::Appearance {
|
||||
background: Some(Background::Color(p.base.foreground)),
|
||||
|
|
@ -127,6 +125,9 @@ impl button::StyleSheet for Theme {
|
|||
border_color: p.normal.primary,
|
||||
..appearance
|
||||
},
|
||||
Button::Unavailable | Button::UninstallPackage => {
|
||||
active_appearance(None, p.bright.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,17 +142,22 @@ impl button::StyleSheet for Theme {
|
|||
};
|
||||
|
||||
match style {
|
||||
Button::Primary => hover_appearance(p.bright.primary, None),
|
||||
Button::Unavailable => hover_appearance(p.bright.error, None),
|
||||
Button::Refresh => hover_appearance(p.bright.primary, None),
|
||||
Button::SelfUpdate => hover_appearance(p.bright.primary, None),
|
||||
Button::UninstallPackage => hover_appearance(p.bright.error, None),
|
||||
Button::RestorePackage => hover_appearance(p.bright.secondary, None),
|
||||
Button::Primary | Button::SelfUpdate | Button::Refresh => {
|
||||
hover_appearance(p.bright.primary, None)
|
||||
}
|
||||
Button::NormalPackage => hover_appearance(p.normal.primary, Some(p.bright.surface)),
|
||||
Button::SelectedPackage => hover_appearance(p.normal.primary, None),
|
||||
Button::RestorePackage => hover_appearance(p.bright.secondary, None),
|
||||
Button::Unavailable | Button::UninstallPackage => {
|
||||
hover_appearance(p.bright.error, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pressed(&self, style: &Self::Style) -> button::Appearance {
|
||||
self.active(style)
|
||||
}
|
||||
|
||||
fn disabled(&self, style: &Self::Style) -> button::Appearance {
|
||||
let active = self.active(style);
|
||||
let p = self.palette();
|
||||
|
|
@ -169,13 +175,7 @@ impl button::StyleSheet for Theme {
|
|||
Button::RestorePackage => disabled_appearance(p.normal.primary, Some(p.bright.primary)),
|
||||
Button::UninstallPackage => disabled_appearance(p.bright.error, None),
|
||||
Button::Primary => disabled_appearance(p.bright.primary, Some(p.bright.primary)),
|
||||
_ => button::Appearance { ..active },
|
||||
}
|
||||
}
|
||||
|
||||
fn pressed(&self, style: &Self::Style) -> button::Appearance {
|
||||
button::Appearance {
|
||||
..self.active(style)
|
||||
_ => active,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -212,9 +212,7 @@ impl scrollable::StyleSheet for Theme {
|
|||
|
||||
fn hovered(&self, style: &Self::Style, _mouse_over_scrollbar: bool) -> scrollable::Scrollbar {
|
||||
scrollable::Scrollbar {
|
||||
scroller: scrollable::Scroller {
|
||||
..self.active(style).scroller
|
||||
},
|
||||
scroller: self.active(style).scroller,
|
||||
..self.active(style)
|
||||
}
|
||||
}
|
||||
|
|
@ -222,7 +220,7 @@ impl scrollable::StyleSheet for Theme {
|
|||
fn dragging(&self, style: &Self::Style) -> scrollable::Scrollbar {
|
||||
let hovered = self.hovered(style, true);
|
||||
scrollable::Scrollbar {
|
||||
scroller: scrollable::Scroller { ..hovered.scroller },
|
||||
scroller: hovered.scroller,
|
||||
..hovered
|
||||
}
|
||||
}
|
||||
|
|
@ -291,10 +289,10 @@ impl checkbox::StyleSheet for Theme {
|
|||
};
|
||||
|
||||
match style {
|
||||
CheckBox::PackageEnabled => from_appearance(),
|
||||
CheckBox::SettingsEnabled => from_appearance(),
|
||||
CheckBox::PackageDisabled => self.active(style, is_checked),
|
||||
CheckBox::SettingsDisabled => self.active(style, is_checked),
|
||||
CheckBox::PackageEnabled | CheckBox::SettingsEnabled => from_appearance(),
|
||||
CheckBox::PackageDisabled | CheckBox::SettingsDisabled => {
|
||||
self.active(style, is_checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -410,7 +408,7 @@ pub enum Text {
|
|||
|
||||
impl From<Color> for Text {
|
||||
fn from(color: Color) -> Self {
|
||||
Text::Color(color)
|
||||
Self::Color(color)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -419,7 +417,7 @@ impl text::StyleSheet for Theme {
|
|||
|
||||
fn appearance(&self, style: Self::Style) -> text::Appearance {
|
||||
match style {
|
||||
Text::Default => Default::default(),
|
||||
Text::Default => text::Appearance::default(),
|
||||
Text::Ok => text::Appearance {
|
||||
color: Some(self.palette().bright.secondary),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -56,22 +56,17 @@ impl About {
|
|||
text(format!("UAD version: v{}", env!("CARGO_PKG_VERSION"))).width(250);
|
||||
|
||||
#[cfg(feature = "self-update")]
|
||||
let self_update_text = match &update_state.self_update.latest_release {
|
||||
Some(r) => {
|
||||
if update_state.self_update.status == SelfUpdateStatus::Updating {
|
||||
update_state.self_update.status.to_string()
|
||||
} else {
|
||||
format!("(v{} available)", r.tag_name)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if update_state.self_update.status == SelfUpdateStatus::Done {
|
||||
"(No update available)".to_string()
|
||||
} else {
|
||||
update_state.self_update.status.to_string()
|
||||
}
|
||||
}
|
||||
};
|
||||
#[rustfmt::skip]
|
||||
let self_update_text = update_state.self_update.latest_release.as_ref().map_or_else(||
|
||||
if update_state.self_update.status == SelfUpdateStatus::Done {
|
||||
"(No update available)".to_string()
|
||||
} else {
|
||||
update_state.self_update.status.to_string()
|
||||
}, |r| if update_state.self_update.status == SelfUpdateStatus::Updating {
|
||||
update_state.self_update.status.to_string()
|
||||
} else {
|
||||
format!("(v{} available)", r.tag_name)
|
||||
});
|
||||
|
||||
#[cfg(feature = "self-update")]
|
||||
let last_self_update_text = text(self_update_text).style(style::Text::Default);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ pub enum LoadingState {
|
|||
|
||||
impl Default for LoadingState {
|
||||
fn default() -> Self {
|
||||
Self::FindingPhones("".to_string())
|
||||
Self::FindingPhones(String::new())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ impl List {
|
|||
}
|
||||
Message::ModalValidate => {
|
||||
let mut commands = vec![];
|
||||
self.selected_packages.sort();
|
||||
self.selected_packages.sort_unstable();
|
||||
self.selected_packages.dedup();
|
||||
for selection in &self.selected_packages {
|
||||
commands.append(&mut build_action_pkg_commands(
|
||||
|
|
@ -114,7 +114,7 @@ impl List {
|
|||
if let CommandType::PackageManager(p) = res {
|
||||
self.loading_state = LoadingState::RestoringDevice(
|
||||
self.phone_packages[i_user][p.index].name.clone(),
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
self.loading_state = LoadingState::RestoringDevice("Error [TODO]".to_string());
|
||||
|
|
@ -128,7 +128,7 @@ impl List {
|
|||
selected_device.android_sdk, selected_device.model
|
||||
);
|
||||
info!("{:-^65}", "-");
|
||||
self.loading_state = LoadingState::DownloadingList("".to_string());
|
||||
self.loading_state = LoadingState::DownloadingList(String::new());
|
||||
Command::perform(
|
||||
Self::init_apps_view(remote, selected_device.clone()),
|
||||
Message::LoadPhonePackages,
|
||||
|
|
@ -136,7 +136,7 @@ impl List {
|
|||
}
|
||||
Message::LoadPhonePackages(list_box) => {
|
||||
let (uad_list, list_state) = list_box;
|
||||
self.loading_state = LoadingState::LoadingPackages("".to_string());
|
||||
self.loading_state = LoadingState::LoadingPackages(String::new());
|
||||
self.uad_lists = uad_list.clone();
|
||||
*list_update_state = list_state;
|
||||
Command::perform(
|
||||
|
|
@ -152,7 +152,7 @@ impl List {
|
|||
self.selected_list = Some(UadList::All);
|
||||
self.selected_user = Some(User::default());
|
||||
Self::filter_package_lists(self);
|
||||
self.loading_state = LoadingState::Ready("".to_string());
|
||||
self.loading_state = LoadingState::Ready(String::new());
|
||||
Command::none()
|
||||
}
|
||||
Message::ToggleAllSelected(selected) => {
|
||||
|
|
@ -193,7 +193,7 @@ impl List {
|
|||
#[allow(unused_must_use)]
|
||||
{
|
||||
self.phone_packages[i_user][i_package]
|
||||
.update(row_message.clone())
|
||||
.update(&row_message)
|
||||
.map(move |row_message| Message::List(i_package, row_message));
|
||||
}
|
||||
|
||||
|
|
@ -600,7 +600,7 @@ impl List {
|
|||
text("Enable").style(style::Text::Ok),
|
||||
PackageState::Uninstalled =>
|
||||
text("Restore").style(style::Text::Ok),
|
||||
_ => text("Impossible")
|
||||
PackageState::All => text("Impossible")
|
||||
.style(style::Text::Danger),
|
||||
},]
|
||||
.width(60),
|
||||
|
|
@ -625,13 +625,7 @@ impl List {
|
|||
.padding([0, 10, 0, 10]);
|
||||
|
||||
container(
|
||||
if device
|
||||
.user_list
|
||||
.iter()
|
||||
.filter(|&u| !u.protected)
|
||||
.collect::<Vec<&User>>()
|
||||
.len()
|
||||
> 1
|
||||
if device.user_list.iter().filter(|&u| !u.protected).count() > 1
|
||||
&& settings.device.multi_user_mode
|
||||
{
|
||||
column![
|
||||
|
|
@ -696,13 +690,13 @@ impl List {
|
|||
let mut phone_packages = vec![];
|
||||
|
||||
if user_list.len() <= 1 {
|
||||
phone_packages.push(fetch_packages(&uad_list, None))
|
||||
phone_packages.push(fetch_packages(&uad_list, None));
|
||||
} else {
|
||||
phone_packages.extend(
|
||||
user_list
|
||||
.iter()
|
||||
.map(|user| fetch_packages(&uad_list, Some(user))),
|
||||
)
|
||||
);
|
||||
};
|
||||
phone_packages
|
||||
}
|
||||
|
|
@ -775,10 +769,10 @@ fn build_action_pkg_commands(
|
|||
}) {
|
||||
let u_pkg = packages[u.index][selection.1].clone();
|
||||
let actions = if settings.multi_user_mode {
|
||||
apply_pkg_state_commands(u_pkg.into(), &wanted_state, u, device)
|
||||
apply_pkg_state_commands(&u_pkg.into(), wanted_state, u, device)
|
||||
} else {
|
||||
let wanted_state = &u_pkg.state.opposite(settings.disable_mode);
|
||||
apply_pkg_state_commands(u_pkg.into(), wanted_state, u, device)
|
||||
let wanted_state = u_pkg.state.opposite(settings.disable_mode);
|
||||
apply_pkg_state_commands(&u_pkg.into(), wanted_state, u, device)
|
||||
};
|
||||
for (j, action) in actions.into_iter().enumerate() {
|
||||
let p_info = PackageInfo {
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ impl Settings {
|
|||
selected: backups.first().cloned(),
|
||||
users: phone.user_list.clone(),
|
||||
selected_user: phone.user_list.first().copied(),
|
||||
backup_state: "".to_string(),
|
||||
backup_state: String::new(),
|
||||
};
|
||||
}
|
||||
None => {
|
||||
|
|
@ -109,7 +109,7 @@ impl Settings {
|
|||
selected: backups.first().cloned(),
|
||||
users: phone.user_list.clone(),
|
||||
selected_user: phone.user_list.first().copied(),
|
||||
backup_state: "".to_string(),
|
||||
backup_state: String::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -190,7 +190,7 @@ impl Settings {
|
|||
radio(
|
||||
format!("{}", option.clone()),
|
||||
*option,
|
||||
Some(string_to_theme(self.general.theme.clone())),
|
||||
Some(string_to_theme(&self.general.theme)),
|
||||
Message::ApplyTheme,
|
||||
)
|
||||
.size(23),
|
||||
|
|
@ -224,7 +224,7 @@ impl Settings {
|
|||
row![
|
||||
text("The following settings only affect the currently selected device :")
|
||||
.style(style::Text::Danger),
|
||||
text(phone.model.to_owned()),
|
||||
text(phone.model.clone()),
|
||||
Space::new(Length::Fill, Length::Shrink),
|
||||
text(phone.adb_id.clone()).style(style::Text::Commentary)
|
||||
]
|
||||
|
|
@ -390,20 +390,7 @@ impl Settings {
|
|||
.style(style::Container::BorderedFrame)
|
||||
};
|
||||
|
||||
let content = if !phone.adb_id.clone().is_empty() {
|
||||
column![
|
||||
text("Theme").size(25),
|
||||
theme_ctn,
|
||||
text("General").size(25),
|
||||
general_ctn,
|
||||
text("Current device").size(25),
|
||||
warning_ctn,
|
||||
device_specific_ctn,
|
||||
backup_restore_ctn,
|
||||
]
|
||||
.width(Length::Fill)
|
||||
.spacing(20)
|
||||
} else {
|
||||
let content = if phone.adb_id.clone().is_empty() {
|
||||
column![
|
||||
text("Theme").size(25),
|
||||
theme_ctn,
|
||||
|
|
@ -416,6 +403,19 @@ impl Settings {
|
|||
]
|
||||
.width(Length::Fill)
|
||||
.spacing(20)
|
||||
} else {
|
||||
column![
|
||||
text("Theme").size(25),
|
||||
theme_ctn,
|
||||
text("General").size(25),
|
||||
general_ctn,
|
||||
text("Current device").size(25),
|
||||
warning_ctn,
|
||||
device_specific_ctn,
|
||||
backup_restore_ctn,
|
||||
]
|
||||
.width(Length::Fill)
|
||||
.spacing(20)
|
||||
};
|
||||
|
||||
container(content)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ impl<'a, Message, Renderer> Modal<'a, Message, Renderer> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_const_for_fn)]
|
||||
/// Sets the message that will be produces when the background
|
||||
/// of the [`Modal`] is pressed
|
||||
pub fn on_blur(self, on_blur: Message) -> Self {
|
||||
|
|
@ -187,6 +188,7 @@ where
|
|||
) -> event::Status {
|
||||
let content_bounds = layout.children().next().unwrap().bounds();
|
||||
|
||||
#[allow(clippy::equatable_if_let)]
|
||||
if let Some(message) = self.on_blur.as_ref() {
|
||||
if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) = &event {
|
||||
if !content_bounds.contains(cursor_position) {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ pub fn nav_menu<'a>(
|
|||
.padding(5)
|
||||
.style(style::Button::Refresh);
|
||||
|
||||
#[allow(clippy::option_if_let_else)]
|
||||
let uad_version_text = if let Some(r) = &self_update_state.latest_release {
|
||||
if self_update_state.status == SelfUpdateStatus::Updating {
|
||||
Text::new("Updating please wait...")
|
||||
|
|
@ -48,17 +49,17 @@ pub fn nav_menu<'a>(
|
|||
Text::new(env!("CARGO_PKG_VERSION"))
|
||||
};
|
||||
|
||||
let mut apps_btn = button("Apps")
|
||||
.on_press(Message::AppsPress)
|
||||
.padding(5)
|
||||
.style(style::Button::Primary);
|
||||
|
||||
if self_update_state.latest_release.is_some() {
|
||||
apps_btn = button("Update")
|
||||
let apps_btn = if self_update_state.latest_release.is_some() {
|
||||
button("Update")
|
||||
.on_press(Message::AboutAction(AboutMessage::DoSelfUpdate))
|
||||
.padding(5)
|
||||
.style(style::Button::SelfUpdate);
|
||||
}
|
||||
.style(style::Button::SelfUpdate)
|
||||
} else {
|
||||
button("Apps")
|
||||
.on_press(Message::AppsPress)
|
||||
.padding(5)
|
||||
.style(style::Button::Primary)
|
||||
};
|
||||
|
||||
let about_btn = button("About")
|
||||
.on_press(Message::AboutPressed)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl PackageRow {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, _message: Message) -> Command<Message> {
|
||||
pub fn update(&mut self, _message: &Message) -> Command<Message> {
|
||||
Command::none()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ pub fn setup_logger() -> Result<(), fern::InitError> {
|
|||
record.file().unwrap_or("?"),
|
||||
record.line().map(|l| l.to_string()).unwrap_or_default(),
|
||||
message
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue