diff --git a/Cargo.toml b/Cargo.toml index b94ffd8..c6335a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,16 +12,19 @@ i18n-embed-fl = "0.8" once_cell = "1.19.0" rust-embed = "8.3.0" log = "0.4" +env_logger = "0.11" open = "5.0.2" serde = { version = "1.0.202", features = ["serde_derive"] } +tracing = "0.1.40" paste = "1.0" rustic_core = "0.2.0" rustic_backend = "0.1.1" +tracing-subscriber = { version = "0.3.18", features = ["json"] } [dependencies.libcosmic] git = "https://github.com/pop-os/libcosmic.git" default-features = false -features = ["dbus-config", "tokio", "winit", "wgpu"] +features = ["multi-window", "tokio", "winit", "wgpu"] [dependencies.i18n-embed] version = "0.14" diff --git a/README.md b/README.md index 49b6e26..b1153b9 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,19 @@ ![COSMIC Backups Dark](https://raw.githubusercontent.com/ahoneybun/cosmic-backups/main/res/screenshots/COSMIC-Backups-Dark.png#gh-dark-mode-only) -The current plan is to use Restic as the backend but for now the UI/UX is still being worked on. I have no idea if this will move forward past the init stage. - ![main branch parameter](https://github.com/ahoneybun/cosmic-backups/actions/workflows/build.yml/badge.svg?branch=main) +# UNDER ACTIVE DEVELOPMENT + +DO NOT TRUST this will important data at this time until it's first release. Always have multiple backups and follow the [3-2-1 rule](https://www.seagate.com/blog/what-is-a-3-2-1-backup-strategy/). + +## This is not an official COSMIC application from System76 + +## Current features + +- [x] Creating a repository with a hardcoded password +- [x] Creating a new snapshot (blank for now) into a selected repository + ## Install To install your COSMIC application, you will need [just](https://github.com/casey/just), if you're on Pop!\_OS, you can install it with the following command: diff --git a/res/com.example.CosmicAppTemplate.desktop b/res/com.github.ahoneybun.CosmicBackups.desktop similarity index 77% rename from res/com.example.CosmicAppTemplate.desktop rename to res/com.github.ahoneybun.CosmicBackups.desktop index 8967fd2..ba049cb 100644 --- a/res/com.example.CosmicAppTemplate.desktop +++ b/res/com.github.ahoneybun.CosmicBackups.desktop @@ -1,6 +1,6 @@ [Desktop Entry] -Name=COSMIC App Template -Exec=cosmic-app-template %F +Name=COSMIC Backups +Exec=cosmic-backups %F Terminal=false Type=Application StartupNotify=true diff --git a/res/com.example.CosmicAppTemplate.metainfo.xml b/res/com.github.ahoneybun.CosmicBackups.metainfo.xml similarity index 66% rename from res/com.example.CosmicAppTemplate.metainfo.xml rename to res/com.github.ahoneybun.CosmicBackups.metainfo.xml index 960ddde..f794be4 100644 --- a/res/com.example.CosmicAppTemplate.metainfo.xml +++ b/res/com.github.ahoneybun.CosmicBackups.metainfo.xml @@ -1,17 +1,17 @@ - com.example.CosmicAppTemplate + com.github.ahoneybun.CosmicBackups CC0-1.0 GPL-3.0-only COSMIC - YourName - your@email.com + Aaron Honeycutt + aaronhoneycutt@proton.me - COSMIC App Template - A template for COSMIC applications + COSMIC Backups + A simple backup application for the COSMIC desktop. -

A template for COSMIC applications

+

A simple backup application using Rustic for the COSMIC desktop.

com.example.CosmicAppTemplate.desktop https://raw.githubusercontent.com/edfloreshz/cosmic-app-template/master/res/icons/hicolor/256x256/apps/com.example.CosmicAppTemplate.svg @@ -22,7 +22,7 @@ text/plain - cosmic-app-template + cosmic-backups
diff --git a/src/app.rs b/src/app.rs index 436ff74..bd08a1f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,11 +1,14 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::app::config::{AppTheme, Repository}; -use crate::fl; +use std::any::TypeId; +use std::collections::{HashMap, VecDeque}; +use std::path::PathBuf; +use std::{env, process}; + use cosmic::app::{Command, Core}; use cosmic::iced::alignment::{Horizontal, Vertical}; -use cosmic::iced::window; -use cosmic::iced_core::keyboard::Key; +use cosmic::iced::{event, keyboard::Event as KeyEvent, window, Event, Subscription}; +use cosmic::iced_core::keyboard::{Key, Modifiers}; use cosmic::widget::menu::{ action::MenuAction, key_bind::{KeyBind, Modifier}, @@ -17,12 +20,13 @@ use cosmic::{ ApplicationExt, }; use cosmic::{widget, Application, Apply, Element}; -use std::collections::{HashMap, VecDeque}; -use std::path::PathBuf; -use std::{env, process}; + +use crate::app::config::{AppTheme, Repository, CONFIG_VERSION}; +use crate::fl; pub mod config; pub mod menu; +pub mod settings; /// This is the struct that represents your application. /// It is used to define the data that will be used by your application. @@ -39,6 +43,7 @@ pub struct App { dialog_pages: VecDeque, dialog_text_input: widget::Id, key_binds: HashMap, + modifiers: Modifiers, } /// This is the enum that contains all the possible variants that your application will need to transmit messages. @@ -53,6 +58,8 @@ pub enum Message { LaunchUrl(String), AppTheme(usize), SystemThemeModeChange(cosmic_theme::ThemeMode), + Key(Modifiers, Key), + Modifiers(Modifiers), WindowClose, WindowNew, CreateRepository(String), @@ -191,7 +198,7 @@ impl Application for App { type Message = Message; - const APP_ID: &'static str = "com.system76.CosmicBackups"; + const APP_ID: &'static str = "com.github.ahoneybun.CosmicBackups"; fn core(&self) -> &Core { &self.core @@ -223,6 +230,7 @@ impl Application for App { dialog_pages: VecDeque::new(), dialog_text_input: widget::Id::unique(), key_binds: key_binds(), + modifiers: Modifiers::empty(), }; let repositories = app.config.repositories.clone(); @@ -294,7 +302,7 @@ impl Application for App { if let Some(repository) = self.nav_model.data::(entity) { self.selected_repository = Some(repository.clone()); let window_title = format!("{} - {}", repository.name, fl!("cosmic-backups")); - commands.push(self.set_window_title(window_title)); + commands.push(self.set_window_title(window_title, self.main_window_id())); } Command::batch(commands) @@ -317,6 +325,58 @@ impl Application for App { .into() } + fn subscription(&self) -> Subscription { + struct ConfigSubscription; + struct ThemeSubscription; + + let subscriptions = vec![ + event::listen_with(|event, status| match event { + Event::Keyboard(KeyEvent::KeyPressed { key, modifiers, .. }) => match status { + event::Status::Ignored => Some(Message::Key(modifiers, key)), + event::Status::Captured => None, + }, + Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => { + Some(Message::Modifiers(modifiers)) + } + _ => None, + }), + cosmic_config::config_subscription( + TypeId::of::(), + Self::APP_ID.into(), + CONFIG_VERSION, + ) + .map(|update| { + if !update.errors.is_empty() { + log::info!( + "errors loading config {:?}: {:?}", + update.keys, + update.errors + ); + } + Message::SystemThemeModeChange(update.config) + }), + cosmic_config::config_subscription::<_, cosmic_theme::ThemeMode>( + TypeId::of::(), + cosmic_theme::THEME_MODE_ID.into(), + cosmic_theme::ThemeMode::version(), + ) + .map(|update| { + if !update.errors.is_empty() { + log::info!( + "errors loading theme mode {:?}: {:?}", + update.keys, + update.errors + ); + } + Message::SystemThemeModeChange(update.config) + }), + ]; + + // subscriptions.push(self.content.subscription().map(Message::Content)); + + Subscription::batch(subscriptions) + } + /// Handle application events here. fn update(&mut self, message: Self::Message) -> Command { // Helper for updating config values efficiently @@ -373,10 +433,11 @@ impl Application for App { .unwrap_or_default() .to_string_lossy() .to_string(); + let mut repositories = self.config.repositories.clone(); let repository = Repository { name, path }; - self.config.repositories.push(repository.clone()); + repositories.push(repository.clone()); self.create_nav_item(repository); - config_set!(repositories, self.config.repositories.clone()); + config_set!(repositories, repositories); } Err(e) => { // TODO: Show error to user. @@ -442,6 +503,16 @@ impl Application for App { log::warn!("failed to open {:?}: {}", url, err); } }, + Message::Key(modifiers, key) => { + for (key_bind, action) in self.key_binds.iter() { + if key_bind.matches(modifiers, &key) { + return self.update(action.message()); + } + } + } + Message::Modifiers(modifiers) => { + self.modifiers = modifiers; + } Message::AppTheme(index) => { let app_theme = match index { 1 => AppTheme::Dark, diff --git a/src/app/settings.rs b/src/app/settings.rs new file mode 100644 index 0000000..be31310 --- /dev/null +++ b/src/app/settings.rs @@ -0,0 +1,39 @@ +use super::config::CosmicBackupsConfig; +use crate::app::Flags; +use cosmic::app::Settings; +use cosmic::iced::{Limits, Size}; + +pub fn init() -> (Settings, Flags) { + set_logger(); + let settings = get_app_settings(); + let flags = get_flags(); + (settings, flags) +} + +pub fn get_app_settings() -> Settings { + let config = CosmicBackupsConfig::config(); + + let mut settings = Settings::default(); + settings = settings.theme(config.app_theme.theme()); + settings = settings.size_limits(Limits::NONE.min_width(400.0).min_height(180.0)); + settings = settings.size(Size::new(800.0, 800.0)); + settings = settings.debug(false); + settings +} + +pub fn set_logger() { + tracing_subscriber::fmt().json().init(); +} + +pub fn get_flags() -> Flags { + let (config_handler, config) = ( + CosmicBackupsConfig::config_handler(), + CosmicBackupsConfig::config(), + ); + + let flags = Flags { + config_handler, + config, + }; + flags +} diff --git a/src/main.rs b/src/main.rs index 4fab239..387358f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::app::App; -use app::{config::CosmicBackupsConfig, Flags}; -use cosmic::app::Settings; +use app::settings; /// The `app` module is used by convention to indicate the main component of our application. mod app; @@ -15,15 +14,6 @@ mod core; /// - `()` is the flags that your app needs to use before it starts. /// If your app does not need any flags, you can pass in `()`. fn main() -> cosmic::iced::Result { - let (settings, flags) = settings(); + let (settings, flags) = settings::init(); cosmic::app::run::(settings, flags) } - -fn settings() -> (Settings, Flags) { - let settings = Settings::default(); - let flags = Flags { - config_handler: CosmicBackupsConfig::config_handler(), - config: CosmicBackupsConfig::config(), - }; - (settings, flags) -}