From 0d83b8f32f7b606be9a426edd6c04c8243174efa Mon Sep 17 00:00:00 2001 From: Casper Rogild Storm Date: Thu, 28 Mar 2024 19:41:35 +0100 Subject: [PATCH 1/2] feat: display version in command bar --- CHANGELOG.md | 18 +- Cargo.lock | 348 +++++++++++++++++++++++++++- data/Cargo.toml | 1 + data/src/environment.rs | 1 + data/src/lib.rs | 2 + data/src/version.rs | 46 ++++ src/main.rs | 41 ++-- src/screen/dashboard.rs | 38 ++- src/screen/dashboard/command_bar.rs | 45 +++- 9 files changed, 506 insertions(+), 34 deletions(-) create mode 100644 data/src/version.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f3d11db..bfe11fb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Added: - Configuration to adjust WHO polling for servers without away-notify (see [server configuration](https://halloy.squidowl.org/configuration/servers.html)) +- Display current version, and latest remote version in command bar Fixed: @@ -61,7 +62,7 @@ Fix: Changed: - Various UI changes - - Ensured consistent padding in channel buffer + - Ensured consistent padding in channel buffer - Unified styling for dividers Security: @@ -100,15 +101,14 @@ Changed: is set to `replacePane`, then selecting a channel in the sidebar will replace the focused pane instead of opening a new pane) - `hidden_server_messages` has been changed to `server_messages` and additional customization has been added: - Exclude messages [join, part, quit]. - - Adjust username format. + - Adjust username format. Fixed: -- Accept '*' as a legal special symbol for usernames +- Accept '\*' as a legal special symbol for usernames - Accept '/' in usernames, ensuring correct parsing for bouncers using the nick/server convention - Create the configuration directory correctly, if it does not exist yet. - # 2023.5 (2023-11-12) Added: @@ -128,11 +128,11 @@ Changed: Added: - Command bar (opened by pressing (Ctrl + k (macOS: + k))) -- Configurable keyboard shortcuts for common actions, such as changing buffer focus, maximize / restoring buffer size, - cycling channels in the buffer and more! A new `keys` section has been added to the config file, reference the +- Configurable keyboard shortcuts for common actions, such as changing buffer focus, maximize / restoring buffer size, + cycling channels in the buffer and more! A new `keys` section has been added to the config file, reference the [wiki](https://github.com/squidowl/halloy/wiki/Keyboard-shortcuts) for more details. - Single clicking on a user will insert nickname to input -- Configuration option `on_connect` to execute commands once connected to a server, reference the +- Configuration option `on_connect` to execute commands once connected to a server, reference the [wiki](https://github.com/squidowl/halloy/wiki/Configuration#on-connect-commands) for more details. Changed: @@ -146,7 +146,7 @@ Fixed: # 2023.3 (2023-07-27) -**Message history and dashboard state will be reset due to a breaking change. We've switched to a more flexible storage format +**Message history and dashboard state will be reset due to a breaking change. We've switched to a more flexible storage format to ensure future breakages won't occur.** Added: @@ -208,7 +208,7 @@ Fixed: - Correctly load image on welcome screen # 2023.1-alpha1 (2023-06-30) - + Added: - First release 🎉 diff --git a/Cargo.lock b/Cargo.lock index 55f2600e..4b6c8ab7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -843,6 +843,7 @@ dependencies = [ "palette", "rand", "rand_chacha", + "reqwest", "seahash", "serde", "serde_json", @@ -981,7 +982,16 @@ dependencies = [ "rustc_version", "toml", "vswhom", - "winreg", + "winreg 0.52.0", +] + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", ] [[package]] @@ -1179,6 +1189,12 @@ dependencies = [ "spin", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "font-types" version = "0.4.3" @@ -1250,6 +1266,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "futures" version = "0.3.30" @@ -1527,6 +1552,25 @@ dependencies = [ "svg_fmt", ] +[[package]] +name = "h2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "2.4.0" @@ -1607,6 +1651,102 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "hyper" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2 0.5.6", + "tokio", + "tower", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1792,6 +1932,16 @@ dependencies = [ "objc2", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "image" version = "0.24.9" @@ -1840,6 +1990,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "irc" version = "0.1.0" @@ -2178,6 +2334,12 @@ dependencies = [ "paste", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2681,6 +2843,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3004,6 +3186,48 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "reqwest" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.50.0", +] + [[package]] name = "roxmltree" version = "0.19.0" @@ -3058,6 +3282,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + [[package]] name = "rustybuzz" version = "0.11.0" @@ -3216,6 +3449,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha1" version = "0.10.6" @@ -3437,6 +3682,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sys-locale" version = "0.3.1" @@ -3446,6 +3697,27 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tauri-winrt-notification" version = "0.1.3" @@ -3711,12 +3983,41 @@ dependencies = [ "winnow 0.6.5", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3742,6 +4043,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "ttf-parser" version = "0.19.2" @@ -3801,6 +4108,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-properties" version = "0.1.1" @@ -3831,6 +4147,17 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "uuid" version = "1.7.0" @@ -3888,6 +4215,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4569,6 +4905,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "winreg" version = "0.52.0" diff --git a/data/Cargo.toml b/data/Cargo.toml index 8f76ebb6..f3c4db96 100644 --- a/data/Cargo.toml +++ b/data/Cargo.toml @@ -22,6 +22,7 @@ seahash = "4.1.0" serde_json = "1.0" toml = "0.8.11" thiserror = "1.0.30" +reqwest = { version = "0.12", features = ["json"] } tokio = { version = "1.0", features = ["io-util"] } tokio-stream = { version = "0.1", features = ["time"] } itertools = "0.12.1" diff --git a/data/src/environment.rs b/data/src/environment.rs index 7403adc4..7395f475 100644 --- a/data/src/environment.rs +++ b/data/src/environment.rs @@ -7,6 +7,7 @@ pub const CONFIG_FILE_NAME: &str = "config.toml"; pub const APPLICATION_ID: &str = "org.squidowl.halloy"; pub const WIKI_WEBSITE: &str = "https://halloy.squidowl.org"; pub const MIGRATION_WEBSITE: &str = "https://halloy.squidowl.org/guides/migrating-from-yaml.html"; +pub const RELEASE_WEBSITE: &str = "https://github.com/squidowl/halloy/releases/latest"; pub fn formatted_version() -> String { let hash = GIT_HASH diff --git a/data/src/lib.rs b/data/src/lib.rs index fb8e1acb..51beb59c 100644 --- a/data/src/lib.rs +++ b/data/src/lib.rs @@ -12,6 +12,7 @@ pub use self::server::Server; pub use self::shortcut::Shortcut; pub use self::theme::Theme; pub use self::user::User; +pub use self::version::Version; pub mod buffer; pub mod channel; @@ -33,3 +34,4 @@ pub mod stream; pub mod theme; pub mod time; pub mod user; +pub mod version; diff --git a/data/src/version.rs b/data/src/version.rs new file mode 100644 index 00000000..912e159c --- /dev/null +++ b/data/src/version.rs @@ -0,0 +1,46 @@ +use crate::environment::VERSION; + +const LATEST_REMOTE_RELEASE_URL: &str = + "https://api.github.com/repos/squidowl/halloy/releases/latest"; + +#[derive(Debug, Clone)] +pub struct Version { + pub current: String, + pub remote: Option, +} + +impl Version { + pub fn new() -> Version { + let current = VERSION.to_owned(); + + Version { + current, + remote: None, + } + } +} + +pub async fn latest_remote_version() -> Option { + #[derive(serde::Deserialize)] + struct Release { + tag_name: String, + } + + let client = reqwest::Client::builder() + .user_agent("halloy") + .build() + .ok()?; + + let response = client + .get(LATEST_REMOTE_RELEASE_URL) + .header(reqwest::header::ACCEPT, "application/vnd.github.v3+json") + .send() + .await + .ok()?; + + response + .json::() + .await + .ok() + .map(|release| release.tag_name) +} diff --git a/src/main.rs b/src/main.rs index df0fe8aa..56c0d953 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,8 @@ use std::env; use std::time::{Duration, Instant}; use data::config::{self, Config}; -use data::{environment, server, User}; +use data::version::Version; +use data::{environment, server, version, User}; use iced::widget::container; use iced::{executor, Application, Command, Length, Subscription}; use screen::{dashboard, help, migration, welcome}; @@ -96,6 +97,7 @@ fn settings( } struct Halloy { + version: Version, screen: Screen, theme: Theme, config: Config, @@ -157,6 +159,7 @@ impl Halloy { ( Halloy { + version: Version::new(), screen, theme: config.themes.default.clone().into(), clients: Default::default(), @@ -184,6 +187,7 @@ pub enum Message { Migration(migration::Message), Event(Event), Tick(Instant), + Version(Option), } impl Application for Halloy { @@ -194,6 +198,10 @@ impl Application for Halloy { fn new(config_load: Self::Flags) -> (Halloy, Command) { let (halloy, command) = Halloy::load_from_state(config_load); + let latest_remote_version = + Command::perform(version::latest_remote_version(), Message::Version); + + let command = Command::batch(vec![command, latest_remote_version]); (halloy, command) } @@ -214,6 +222,7 @@ impl Application for Halloy { &mut self.clients, &mut self.servers, &mut self.theme, + &self.version, &self.config, ); // Retrack after dashboard state changes @@ -224,6 +233,12 @@ impl Application for Halloy { track.map(Message::Dashboard), ]) } + Message::Version(remote) => { + // Set latest known remote version + self.version.remote = remote; + + Command::none() + } Message::Help(message) => { let Screen::Help(help) = &mut self.screen else { return Command::none(); @@ -301,12 +316,7 @@ impl Application for Halloy { notification::show("Disconnected", &server, notification.sound()); }; - dashboard.broadcast_disconnected( - &server, - error, - &self.config, - sent_time, - ); + dashboard.broadcast_disconnected(&server, error, &self.config, sent_time); } Command::none() @@ -352,12 +362,7 @@ impl Application for Halloy { return Command::none(); }; - dashboard.broadcast_connection_failed( - &server, - error, - &self.config, - sent_time, - ); + dashboard.broadcast_connection_failed(&server, error, &self.config, sent_time); Command::none() } @@ -495,7 +500,13 @@ impl Application for Halloy { Message::Event(event) => { if let Screen::Dashboard(dashboard) = &mut self.screen { dashboard - .handle_event(event, &self.clients, &self.config, &mut self.theme) + .handle_event( + event, + &self.clients, + &self.version, + &self.config, + &mut self.theme, + ) .map(Message::Dashboard) } else if let event::Event::CloseRequested = event { window::close(window::Id::MAIN) @@ -518,7 +529,7 @@ impl Application for Halloy { fn view(&self) -> Element { let content = match &self.screen { Screen::Dashboard(dashboard) => dashboard - .view(&self.clients, &self.config) + .view(&self.clients, &self.version, &self.config) .map(Message::Dashboard), Screen::Help(help) => help.view().map(Message::Help), Screen::Welcome(welcome) => welcome.view().map(Message::Welcome), diff --git a/src/screen/dashboard.rs b/src/screen/dashboard.rs index 327cd9f1..8434979a 100644 --- a/src/screen/dashboard.rs +++ b/src/screen/dashboard.rs @@ -3,11 +3,12 @@ pub mod pane; pub mod sidebar; use chrono::{DateTime, Utc}; +use data::environment::RELEASE_WEBSITE; use std::time::{Duration, Instant}; use data::history::manager::Broadcast; use data::user::Nick; -use data::{client, environment, history, server, Config, Server, User}; +use data::{client, environment, history, server, Config, Server, User, Version}; use iced::widget::pane_grid::{self, PaneGrid}; use iced::widget::{column, container, row, Space}; use iced::{clipboard, window, Command, Length}; @@ -80,6 +81,7 @@ impl Dashboard { clients: &mut client::Map, servers: &mut server::Map, theme: &mut Theme, + version: &Version, config: &Config, ) -> Command { match message { @@ -356,6 +358,12 @@ impl Dashboard { }, Some(command_bar::Event::Command(command)) => { let command = match command { + command_bar::Command::Version(command) => match command { + command_bar::Version::Application(_) => { + let _ = open::that(RELEASE_WEBSITE); + Command::none() + } + }, command_bar::Command::Buffer(command) => match command { command_bar::Buffer::Maximize(_) => { self.maximize_pane(); @@ -397,7 +405,7 @@ impl Dashboard { command_bar::Configuration::OpenWebsite => { let _ = open::that(environment::WIKI_WEBSITE); Command::none() - }, + } }, command_bar::Command::UI(command) => match command { command_bar::Ui::ToggleSidebarVisibility => { @@ -415,12 +423,18 @@ impl Dashboard { return Command::batch(vec![ command, - self.toggle_command_bar(&closed_buffers(self, clients), config, theme), + self.toggle_command_bar( + &closed_buffers(self, clients), + version, + config, + theme, + ), ]); } Some(command_bar::Event::Unfocused) => { return self.toggle_command_bar( &closed_buffers(self, clients), + version, config, theme, ); @@ -504,6 +518,7 @@ impl Dashboard { CommandBar => { return self.toggle_command_bar( &closed_buffers(self, clients), + version, config, theme, ); @@ -518,6 +533,7 @@ impl Dashboard { pub fn view<'a>( &'a self, clients: &'a client::Map, + version: &'a Version, config: &'a Config, ) -> Element<'a, Message> { let focus = self.focus; @@ -588,6 +604,7 @@ impl Dashboard { &all_buffers(clients, &self.history), self.focus.is_some(), self.buffer_resize_action(), + version, config, ) .map(Message::Command), @@ -608,6 +625,7 @@ impl Dashboard { &mut self, event: event::Event, clients: &data::client::Map, + version: &Version, config: &Config, theme: &mut Theme, ) -> Command { @@ -621,7 +639,12 @@ impl Dashboard { // - Restore maximized pane // - Unfocus if self.command_bar.is_some() { - return self.toggle_command_bar(&closed_buffers(self, clients), config, theme); + return self.toggle_command_bar( + &closed_buffers(self, clients), + version, + config, + theme, + ); } else if self.is_pane_maximized() { self.panes.restore(); } else { @@ -1008,6 +1031,7 @@ impl Dashboard { pub fn toggle_command_bar( &mut self, buffers: &[data::Buffer], + version: &Version, config: &Config, theme: &mut Theme, ) -> Command { @@ -1022,15 +1046,15 @@ impl Dashboard { .map(|pane| self.focus_pane(pane)) .unwrap_or(Command::none()) } else { - self.open_command_bar(buffers, config); - + self.open_command_bar(buffers, version, config); Command::none() } } - fn open_command_bar(&mut self, buffers: &[data::Buffer], config: &Config) { + fn open_command_bar(&mut self, buffers: &[data::Buffer], version: &Version, config: &Config) { self.command_bar = Some(CommandBar::new( buffers, + version, config, self.focus.is_some(), self.buffer_resize_action(), diff --git a/src/screen/dashboard/command_bar.rs b/src/screen/dashboard/command_bar.rs index 17413e74..f14b07fc 100644 --- a/src/screen/dashboard/command_bar.rs +++ b/src/screen/dashboard/command_bar.rs @@ -21,6 +21,7 @@ pub enum Message { impl CommandBar { pub fn new( buffers: &[data::Buffer], + version: &data::Version, config: &Config, is_focused_buffer: bool, resize_buffer: data::buffer::Resize, @@ -30,6 +31,7 @@ impl CommandBar { config, is_focused_buffer, resize_buffer, + version, )); state.focus(); @@ -53,6 +55,7 @@ impl CommandBar { buffers: &[data::Buffer], focused_buffer: bool, resize_buffer: data::buffer::Resize, + version: &data::Version, config: &'a Config, ) -> Element<'a, Message> { // 1px larger than default @@ -78,7 +81,7 @@ impl CommandBar { column( std::iter::once(text("Type a command...").size(font_size)) .chain( - Command::list(buffers, config, focused_buffer, resize_buffer) + Command::list(buffers, config, focused_buffer, resize_buffer, version) .iter() .map(|command| text(command).size(font_size)), ) @@ -102,12 +105,18 @@ pub enum Event { #[derive(Debug, Clone)] pub enum Command { + Version(Version), Buffer(Buffer), Configuration(Configuration), UI(Ui), Theme(Theme), } +#[derive(Debug, Clone)] +pub enum Version { + Application(data::Version), +} + #[derive(Debug, Clone)] pub enum Buffer { Maximize(bool), @@ -138,6 +147,7 @@ impl Command { config: &Config, is_focused_buffer: bool, resize_buffer: data::buffer::Resize, + version: &data::Version, ) -> Vec { let buffers = Buffer::list(buffers, is_focused_buffer, resize_buffer) .into_iter() @@ -151,7 +161,14 @@ impl Command { let themes = Theme::list(config).into_iter().map(Command::Theme); - buffers.chain(configs).chain(themes).chain(uis).collect() + let version = Version::list(version).into_iter().map(Command::Version); + + version + .chain(buffers) + .chain(configs) + .chain(themes) + .chain(uis) + .collect() } } @@ -162,6 +179,7 @@ impl std::fmt::Display for Command { Command::Configuration(config) => write!(f, "Configuration: {}", config), Command::UI(ui) => write!(f, "UI: {}", ui), Command::Theme(theme) => write!(f, "Theme: {}", theme), + Command::Version(application) => write!(f, "Version: {}", application), } } } @@ -190,6 +208,12 @@ impl Buffer { } } +impl Version { + fn list(version: &data::Version) -> Vec { + vec![Version::Application(version.clone())] + } +} + impl Configuration { fn list() -> Vec { vec![Configuration::OpenDirectory, Configuration::OpenWebsite] @@ -214,6 +238,23 @@ impl Theme { } } +impl std::fmt::Display for Version { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Version::Application(version) => { + let latest = version + .remote + .as_ref() + .filter(|remote| remote != &&version.current) + .map(|remote| format!("(Latest: {})", remote)) + .unwrap_or("(Latest release)".to_owned()); + + write!(f, "{} {}", version.current, latest) + } + } + } +} + impl std::fmt::Display for Buffer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { From 7957636d50c5af0b23506758c63ab0b8bd288c8c Mon Sep 17 00:00:00 2001 From: Casper Rogild Storm Date: Thu, 28 Mar 2024 19:47:23 +0100 Subject: [PATCH 2/2] clippy --- data/src/version.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data/src/version.rs b/data/src/version.rs index 912e159c..f2c14081 100644 --- a/data/src/version.rs +++ b/data/src/version.rs @@ -9,6 +9,12 @@ pub struct Version { pub remote: Option, } +impl Default for Version { + fn default() -> Self { + Self::new() + } +} + impl Version { pub fn new() -> Version { let current = VERSION.to_owned();