diff --git a/Cargo.lock b/Cargo.lock index 1b81827..9515119 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -257,6 +257,12 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70033777eb8b5124a81a1889416543dddef2de240019b674c81285a2635a7e1e" +[[package]] +name = "anyhow" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" + [[package]] name = "apply" version = "0.3.0" @@ -1162,6 +1168,7 @@ dependencies = [ "mime_guess", "notify", "once_cell", + "open", "paste", "rust-embed", "serde", @@ -1171,6 +1178,7 @@ dependencies = [ "test-log", "tokio", "trash", + "vergen", ] [[package]] @@ -1446,6 +1454,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivative" version = "2.2.0" @@ -2903,6 +2920,31 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + [[package]] name = "jni" version = "0.21.1" @@ -3625,6 +3667,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.46" @@ -3730,6 +3778,15 @@ dependencies = [ "syn 2.0.51", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "objc" version = "0.2.7" @@ -3822,6 +3879,17 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "open" +version = "5.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eedff767bc49d336bff300224f73307ae36963c843e38dc9312a22171b012cbc" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -3995,6 +4063,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -4133,6 +4207,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -4587,6 +4667,12 @@ dependencies = [ "owned_ttf_parser 0.15.2", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "rustybuzz" version = "0.12.1" @@ -5127,6 +5213,39 @@ dependencies = [ "weezl", ] +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -5548,6 +5667,18 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "vergen" +version = "8.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" +dependencies = [ + "anyhow", + "cfg-if 1.0.0", + "rustversion", + "time", +] + [[package]] name = "version-compare" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index aced9f1..17c5a21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,21 @@ [package] name = "cosmic-files" version = "0.1.0" +authors = ["Jeremy Soller "] edition = "2021" +license = "GPL-3.0-only" rust-version = "1.71" +[build-dependencies] +vergen = { version = "8", features = ["git", "gitcl"] } + [dependencies] chrono = { version = "0.4", features = ["unstable-locales"] } dirs = "5.0.1" env_logger = "0.11" image = "0.24" once_cell = "1.19" +open = "5.0.2" lexical-sort = "0.3.1" log = "0.4" mime_guess = "2" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..3628d6a --- /dev/null +++ b/build.rs @@ -0,0 +1,11 @@ +fn main() -> Result<(), Box> { + // Rebuild if i18n files change + println!("cargo:rerun-if-changed=i18n"); + + vergen::EmitBuilder::builder() + .fail_on_error() + .git_commit_date() + .git_sha(true) + .emit()?; + Ok(()) +} diff --git a/debian/control b/debian/control index 7212a02..e2328d9 100644 --- a/debian/control +++ b/debian/control @@ -4,6 +4,7 @@ Priority: optional Maintainer: Jeremy Soller Build-Depends: debhelper-compat (=13), + git, just (>= 1.13.0), pkg-config, rust-all, diff --git a/i18n/en/cosmic_files.ftl b/i18n/en/cosmic_files.ftl index a20a3df..4af4109 100644 --- a/i18n/en/cosmic_files.ftl +++ b/i18n/en/cosmic_files.ftl @@ -1,3 +1,4 @@ +cosmic-files = COSMIC Files empty-folder = Empty folder empty-folder-hidden = Empty folder (has hidden items) filesystem = Filesystem @@ -37,6 +38,10 @@ size = Size # Context Pages +## About +about = About +git-description = Git commit {$hash} on {$date} + ## Operations operations = Operations pending = Pending @@ -89,3 +94,4 @@ view = View grid-view = Grid view list-view = List view menu-settings = Settings... +menu-about = About COSMIC Files... diff --git a/justfile b/justfile index 99cdc63..d802b6c 100644 --- a/justfile +++ b/justfile @@ -15,6 +15,9 @@ desktop := APPID + '.desktop' desktop-src := 'res' / desktop desktop-dst := clean(rootdir / prefix) / 'share' / 'applications' / desktop +icons-src := 'res' / 'icons' / 'hicolor' +icons-dst := clean(rootdir / prefix) / 'share' / 'icons' / 'hicolor' + # Default recipe which runs `just build-release` default: build-release @@ -60,7 +63,10 @@ run *args: # Installs files install: install -Dm0755 {{bin-src}} {{bin-dst}} - install -Dm0755 {{desktop-src}} {{desktop-dst}} + install -Dm0644 {{desktop-src}} {{desktop-dst}} + for size in `ls {{icons-src}}`; do \ + install -Dm0644 "{{icons-src}}/$size/apps/{{APPID}}.svg" "{{icons-dst}}/$size/apps/{{APPID}}.svg"; \ + done # Uninstalls installed files uninstall: diff --git a/res/com.system76.CosmicFiles.desktop b/res/com.system76.CosmicFiles.desktop index 27288b7..6e8d578 100644 --- a/res/com.system76.CosmicFiles.desktop +++ b/res/com.system76.CosmicFiles.desktop @@ -1,11 +1,11 @@ #TODO: more build-out, desktop actions, translations? [Desktop Entry] -Name=COSMIC File Manager +Name=COSMIC Files Exec=cosmic-files %F Terminal=false Type=Application StartupNotify=true -Icon=system-file-manager +Icon=com.system76.CosmicFiles Categories=COSMIC;Utility;FileManager; Keywords=Folder;Manager; MimeType=inode/directory; diff --git a/res/icons/hicolor/128x128/apps/com.system76.CosmicFiles.svg b/res/icons/hicolor/128x128/apps/com.system76.CosmicFiles.svg new file mode 100644 index 0000000..3acc2f1 --- /dev/null +++ b/res/icons/hicolor/128x128/apps/com.system76.CosmicFiles.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/res/icons/hicolor/16x16/apps/com.system76.CosmicFiles.svg b/res/icons/hicolor/16x16/apps/com.system76.CosmicFiles.svg new file mode 100644 index 0000000..0ae0da9 --- /dev/null +++ b/res/icons/hicolor/16x16/apps/com.system76.CosmicFiles.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/res/icons/hicolor/24x24/apps/com.system76.CosmicFiles.svg b/res/icons/hicolor/24x24/apps/com.system76.CosmicFiles.svg new file mode 100644 index 0000000..0ceb87d --- /dev/null +++ b/res/icons/hicolor/24x24/apps/com.system76.CosmicFiles.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/res/icons/hicolor/256x256/apps/com.system76.CosmicFiles.svg b/res/icons/hicolor/256x256/apps/com.system76.CosmicFiles.svg new file mode 100644 index 0000000..3c40602 --- /dev/null +++ b/res/icons/hicolor/256x256/apps/com.system76.CosmicFiles.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/res/icons/hicolor/32x32/apps/com.system76.CosmicFiles.svg b/res/icons/hicolor/32x32/apps/com.system76.CosmicFiles.svg new file mode 100644 index 0000000..92a83ca --- /dev/null +++ b/res/icons/hicolor/32x32/apps/com.system76.CosmicFiles.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/res/icons/hicolor/48x48/apps/com.system76.CosmicFiles.svg b/res/icons/hicolor/48x48/apps/com.system76.CosmicFiles.svg new file mode 100644 index 0000000..b49771a --- /dev/null +++ b/res/icons/hicolor/48x48/apps/com.system76.CosmicFiles.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/res/icons/hicolor/64x64/apps/com.system76.CosmicFiles.svg b/res/icons/hicolor/64x64/apps/com.system76.CosmicFiles.svg new file mode 100644 index 0000000..6510078 --- /dev/null +++ b/res/icons/hicolor/64x64/apps/com.system76.CosmicFiles.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/app.rs b/src/app.rs index 5a68d88..41a9146 100644 --- a/src/app.rs +++ b/src/app.rs @@ -9,7 +9,7 @@ use cosmic::{ futures::{self, SinkExt}, keyboard::{Event as KeyEvent, Key, Modifiers}, subscription::{self, Subscription}, - window, Event, Length, + window, Alignment, Event, Length, }, style, widget::{self, segmented_button}, @@ -31,7 +31,6 @@ use crate::{ menu, operation::Operation, tab::{self, ItemMetadata, Location, Tab}, - util, }; #[derive(Clone, Debug)] @@ -42,6 +41,7 @@ pub struct Flags { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Action { + About, Copy, Cut, HistoryNext, @@ -70,6 +70,7 @@ pub enum Action { impl Action { pub fn message(self, entity_opt: Option) -> Message { match self { + Action::About => Message::ToggleContextPage(ContextPage::About), Action::Copy => Message::Copy(entity_opt), Action::Cut => Message::Cut(entity_opt), Action::HistoryNext => Message::TabMessage(None, tab::Message::GoNext), @@ -112,6 +113,7 @@ pub enum Message { DialogComplete, DialogUpdate(DialogPage), Key(Modifiers, Key), + LaunchUrl(String), Modifiers(Modifiers), MoveToTrash(Option), NewItem(Option, bool), @@ -139,6 +141,7 @@ pub enum Message { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ContextPage { + About, Operations, Properties, Settings, @@ -147,6 +150,7 @@ pub enum ContextPage { impl ContextPage { fn title(&self) -> String { match self { + Self::About => fl!("about"), Self::Operations => fl!("operations"), Self::Properties => fl!("properties"), Self::Settings => fl!("settings"), @@ -308,6 +312,37 @@ impl App { Command::none() } + fn about(&self) -> Element { + let cosmic_theme::Spacing { space_xxs, .. } = self.core().system_theme().cosmic().spacing; + let repository = "https://github.com/pop-os/cosmic-files"; + let hash = env!("VERGEN_GIT_SHA"); + let date = env!("VERGEN_GIT_COMMIT_DATE"); + widget::column::with_children(vec![ + widget::svg(widget::svg::Handle::from_memory( + &include_bytes!( + "../res/icons/hicolor/128x128/apps/com.system76.CosmicFiles.svg" + )[..], + )) + .into(), + widget::text::title3(fl!("cosmic-files")).into(), + widget::button::link(repository) + .on_press(Message::LaunchUrl(repository.to_string())) + .padding(0) + .into(), + widget::button::link(fl!( + "git-description", + hash = hash, + date = date + )) + .on_press(Message::LaunchUrl(format!("{}/commits/{}", repository, hash))) + .padding(0) + .into(), + ]) + .align_items(Alignment::Center) + .spacing(space_xxs) + .into() + } + fn operations(&self) -> Element { let mut children = Vec::new(); @@ -679,6 +714,12 @@ impl Application for App { } } } + Message::LaunchUrl(url) => match open::that_detached(&url) { + Ok(()) => {} + Err(err) => { + log::warn!("failed to open {:?}: {}", url, err); + } + }, Message::Modifiers(modifiers) => { self.modifiers = modifiers; } @@ -915,9 +956,8 @@ impl Application for App { ])); } tab::Command::OpenFile(item_path) => { - let mut command = util::open_command(&item_path); - match command.spawn() { - Ok(_) => (), + match open::that_detached(&item_path) { + Ok(()) => (), Err(err) => { log::warn!("failed to open {:?}: {}", item_path, err); } @@ -977,6 +1017,7 @@ impl Application for App { } Some(match self.context_page { + ContextPage::About => self.about(), ContextPage::Operations => self.operations(), ContextPage::Properties => self.properties(), ContextPage::Settings => self.settings(), diff --git a/src/lib.rs b/src/lib.rs index dc9d666..555e6ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,6 @@ mod mime_icon; mod mouse_area; mod operation; mod tab; -mod util; pub fn home_dir() -> PathBuf { match dirs::home_dir() { diff --git a/src/menu.rs b/src/menu.rs index e041028..91c6210 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -158,6 +158,8 @@ pub fn menu_bar<'a>(key_binds: &HashMap) -> Element<'a, Message menu_item(fl!("list-view"), Action::TabViewList), MenuTree::new(horizontal_rule(1)), menu_item(fl!("menu-settings"), Action::Settings), + MenuTree::new(horizontal_rule(1)), + menu_item(fl!("menu-about"), Action::About), ], ), ]) diff --git a/src/util.rs b/src/util.rs deleted file mode 100644 index 37877c6..0000000 --- a/src/util.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::{path::PathBuf, process}; - -#[cfg(target_os = "linux")] -pub fn open_command(path: &PathBuf) -> process::Command { - let mut command = process::Command::new("xdg-open"); - command.arg(path); - command -} - -#[cfg(target_os = "macos")] -pub fn open_command(path: &PathBuf) -> process::Command { - let mut command = process::Command::new("open"); - command.arg(path); - command -} - -#[cfg(target_os = "redox")] -pub fn open_command(path: &PathBuf) -> process::Command { - let mut command = process::Command::new("launcher"); - command.arg(path); - command -} - -#[cfg(target_os = "windows")] -pub fn open_command(path: &PathBuf) -> process::Command { - use std::os::windows::process::CommandExt; - - let mut command = process::Command::new("cmd"); - - command - .arg("/c") - .arg("start") - .raw_arg("\"\"") - .arg(path) - .creation_flags(0x08000000); - command -}