Skip to content

Commit

Permalink
feat: add ability to customize backup folder
Browse files Browse the repository at this point in the history
 - added setting for back up folder

 - added pre-selected icons when importing icons.json to icommon

 - added Backup / Restore category when device is connected
  • Loading branch information
edgy-b committed Apr 28, 2024
1 parent b5cd560 commit 6931fb4
Show file tree
Hide file tree
Showing 8 changed files with 356 additions and 40 deletions.
263 changes: 241 additions & 22 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dirs = "^5.0.0"
ureq = { version = "*", features = ["json"] }
retry = "^2.0.0"
iced = { version = "^0.12.0", features = ["advanced", "image"] }
rfd = "^0.14"

[target.'cfg(not(target_os = "windows"))'.dependencies]
flate2 = { version = "^1", optional = true }
Expand Down
14 changes: 10 additions & 4 deletions resources/assets/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,11 @@
{
"ligatures": "folder-open, directory2",
"name": "folder-open",
"order": 0,
"id": 49
"order": 4,
"id": 49,
"prevSize": 28,
"code": 59696,
"tempChar": ""
},
{
"ligatures": "folder-plus, directory3",
Expand Down Expand Up @@ -1016,8 +1019,11 @@
{
"ligatures": "cog, gear",
"name": "cog",
"order": 0,
"id": 149
"order": 3,
"id": 149,
"prevSize": 28,
"code": 59796,
"tempChar": ""
},
{
"ligatures": "cogs, gears",
Expand Down
Binary file modified resources/assets/icons.ttf
Binary file not shown.
14 changes: 13 additions & 1 deletion src/core/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::core::sync::{get_android_sdk, User};
use crate::core::utils::DisplayablePath;
use crate::gui::views::settings::Settings;
use crate::CACHE_DIR;
use crate::CONFIG_DIR;
use serde::{Deserialize, Serialize};
use static_init::dynamic;
Expand All @@ -14,10 +15,11 @@ pub struct Config {
pub devices: Vec<DeviceSettings>,
}

#[derive(Default, Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct GeneralSettings {
pub theme: String,
pub expert_mode: bool,
pub backup_folder: PathBuf,
}

#[derive(Default, Debug, Clone)]
Expand All @@ -38,6 +40,16 @@ pub struct DeviceSettings {
pub backup: BackupSettings,
}

impl Default for GeneralSettings {
fn default() -> Self {
Self {
theme: String::from("Dark"),
expert_mode: false,
backup_folder: CACHE_DIR.join("backups"),
}
}
}

impl Default for DeviceSettings {
fn default() -> Self {
Self {
Expand Down
5 changes: 3 additions & 2 deletions src/core/save.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::core::config::DeviceSettings;
use crate::core::config::{Config, DeviceSettings};
use crate::core::sync::{apply_pkg_state_commands, CorePackage, Phone, User};
use crate::core::utils::DisplayablePath;
use crate::gui::widgets::package_row::PackageRow;
Expand Down Expand Up @@ -51,7 +51,8 @@ pub async fn backup_phone(

match serde_json::to_string_pretty(&backup) {
Ok(json) => {
let backup_path = &*BACKUP_DIR.join(device_id);
let backup_dir: PathBuf = Config::load_configuration_file().general.backup_folder;
let backup_path = &*backup_dir.join(device_id);

if let Err(e) = fs::create_dir_all(backup_path) {
error!("BACKUP: could not create backup dir: {}", e);
Expand Down
14 changes: 14 additions & 0 deletions src/core/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ use std::path::PathBuf;
use std::process::Command;
use std::{fmt, fs};

#[derive(Debug, Clone)]
pub enum Error {
DialogClosed(String),
}

pub fn fetch_packages(uad_lists: &PackageHashMap, user_id: Option<&User>) -> Vec<PackageRow> {
let all_system_packages = list_all_system_packages(user_id); // installed and uninstalled packages
let enabled_system_packages = hashset_system_packages(PackageState::Enabled, user_id);
Expand Down Expand Up @@ -129,3 +134,12 @@ impl fmt::Display for DisplayablePath {
write!(f, "{stem}")
}
}

pub async fn open_folder() -> Result<PathBuf, Error> {
let picked_folder = rfd::AsyncFileDialog::new()
.pick_folder()
.await
.ok_or(Error::DialogClosed(err))?;

Ok(picked_folder.path().to_owned())
}
85 changes: 74 additions & 11 deletions src/gui/views/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,37 @@ use crate::core::sync::AdbError;

use crate::core::config::{BackupSettings, Config, DeviceSettings, GeneralSettings};
use crate::core::save::{
backup_phone, list_available_backup_user, list_available_backups, restore_backup, BACKUP_DIR,
backup_phone, list_available_backup_user, list_available_backups, restore_backup,
};
use crate::core::sync::{get_android_sdk, perform_adb_commands, CommandType, Phone};
use crate::core::theme::Theme;
use crate::core::utils::{open_url, string_to_theme, DisplayablePath};
use crate::core::utils::{open_folder, open_url, string_to_theme, DisplayablePath};
use crate::gui::style;
use crate::gui::views::list::PackageInfo;
use crate::gui::widgets::navigation_menu::ICONS;
use crate::gui::widgets::package_row::PackageRow;

use iced::widget::{
button, checkbox, column, container, pick_list, radio, row, scrollable, text, Space,
button, checkbox, column, container, pick_list, radio, row, scrollable, text, Space, Text,
};
use iced::{alignment, Alignment, Command, Element, Length, Renderer};
use std::path::PathBuf;

use crate::core::utils::Error;

#[derive(Debug, Clone)]
pub struct Settings {
pub general: GeneralSettings,
pub device: DeviceSettings,
is_loading: bool,
}

impl Default for Settings {
fn default() -> Self {
Self {
general: Config::load_configuration_file().general,
device: DeviceSettings::default(),
is_loading: false,
}
}
}
Expand All @@ -45,6 +50,8 @@ pub enum Message {
RestoreDevice,
RestoringDevice(Result<CommandType, AdbError>),
DeviceBackedUp(Result<(), String>),
ChooseBackUpFolder,
FolderChosen(Result<PathBuf, Error>),
}

impl Settings {
Expand Down Expand Up @@ -87,7 +94,8 @@ impl Settings {
Command::none()
}
Message::LoadDeviceSettings => {
let backups = list_available_backups(&BACKUP_DIR.join(&phone.adb_id));
let backups =
list_available_backups(&self.general.backup_folder.join(&phone.adb_id));
let backup = BackupSettings {
backups: backups.clone(),
selected: backups.first().cloned(),
Expand Down Expand Up @@ -131,7 +139,7 @@ impl Settings {
Message::DeviceBackedUp(_) => {
info!("[BACKUP] Backup successfully created");
self.device.backup.backups =
list_available_backups(&BACKUP_DIR.join(phone.adb_id.clone()));
list_available_backups(&self.general.backup_folder.join(phone.adb_id.clone()));
self.device.backup.selected = self.device.backup.backups.first().cloned();
Command::none()
}
Expand Down Expand Up @@ -178,6 +186,32 @@ impl Settings {
},
// Trigger an action in mod.rs (Message::SettingsAction(msg))
Message::RestoringDevice(_) => Command::none(),
Message::FolderChosen(result) => {
self.is_loading = false;

if let Ok(path) = result {
self.general.backup_folder = path;
Config::save_changes(self, &phone.adb_id);
#[allow(unused_must_use)]
{
self.update(
phone,
packages,
nb_running_async_adb_commands,
Message::LoadDeviceSettings,
);
}
}
Command::none()
}
Message::ChooseBackUpFolder => {
if self.is_loading {
Command::none()
} else {
self.is_loading = true;
Command::perform(open_folder(), Message::FolderChosen)
}
}
}
}

Expand Down Expand Up @@ -212,11 +246,37 @@ impl Settings {
text("Most unsafe packages are known to bootloop the device if removed.")
.style(style::Text::Commentary);

let general_ctn = container(column![expert_mode_checkbox, expert_mode_descr].spacing(10))
.padding(10)
.width(Length::Fill)
.height(Length::Shrink)
.style(style::Container::Frame);
let choose_backup_descr = text("Note: If you have previous backups, you will need to transfer them manually to newly changed backup folder to be able to use Restore functionality")
.style(style::Text::Commentary);

let choose_backup_btn = button(Text::new("\u{E930}").font(ICONS))
.padding([5, 10])
.on_press(Message::ChooseBackUpFolder)
.style(style::Button::Primary);

let choose_backup_row = row![
choose_backup_btn,
"Choose backup folder",
Space::new(Length::Fill, Length::Shrink),
"Current folder: ",
Text::new(self.general.backup_folder.to_string_lossy())
]
.spacing(10)
.align_items(Alignment::Center);

let general_ctn = container(
column![
expert_mode_checkbox,
expert_mode_descr,
choose_backup_row,
choose_backup_descr,
]
.spacing(10),
)
.padding(10)
.width(Length::Fill)
.height(Length::Shrink)
.style(style::Container::Frame);

let warning_ctn = container(
row![
Expand Down Expand Up @@ -346,7 +406,9 @@ impl Settings {
.style(style::Button::Primary)
} else {
button("Open backup directory")
.on_press(Message::UrlPressed(BACKUP_DIR.join(phone.adb_id.clone())))
.on_press(Message::UrlPressed(
self.general.backup_folder.join(phone.adb_id.clone()),
))
.padding([5, 10])
.style(style::Button::Primary)
};
Expand Down Expand Up @@ -409,6 +471,7 @@ impl Settings {
text("Current device").size(26),
warning_ctn,
device_specific_ctn,
text("Backup / Restore").size(26),
backup_restore_ctn,
]
.width(Length::Fill)
Expand Down

0 comments on commit 6931fb4

Please sign in to comment.