From 66fa7cee718f4478aba87edfe5b82a1107451791 Mon Sep 17 00:00:00 2001 From: saying Date: Sat, 22 Feb 2025 16:54:08 +0800 Subject: [PATCH 1/3] feat(config): add `show_avatar` field --- crates/lcode-config/src/config/mod.rs | 10 +- .../src/config/user_serializes.rs | 6 +- crates/lcode/src/app/impl_app/get_info.rs | 102 +++++++++++------- crates/lcode/src/mytui/mod.rs | 2 +- crates/lcode/src/mytui/ui/info.rs | 14 +-- 5 files changed, 79 insertions(+), 55 deletions(-) diff --git a/crates/lcode-config/src/config/mod.rs b/crates/lcode-config/src/config/mod.rs index e24ddf1..aecff31 100644 --- a/crates/lcode-config/src/config/mod.rs +++ b/crates/lcode-config/src/config/mod.rs @@ -53,10 +53,13 @@ pub struct Config { pub code_dir: PathBuf, #[serde(default)] pub browser: String, - #[serde(default = "cargo_default")] + #[serde(default = "default_true")] pub cargo_integr: bool, - #[serde(default = "default_ser_bool")] - pub dir_with_frontend_id: bool, // create qs dir use frontend id + #[serde(default)] + /// create qs dir use frontend id + pub dir_with_frontend_id: bool, + #[serde(default)] + pub show_avatar: bool, } impl Config { @@ -86,6 +89,7 @@ impl Default for Config { browser: String::new(), cargo_integr: true, dir_with_frontend_id: false, + show_avatar: false, } } } diff --git a/crates/lcode-config/src/config/user_serializes.rs b/crates/lcode-config/src/config/user_serializes.rs index 3c6de1d..9cfdb24 100644 --- a/crates/lcode-config/src/config/user_serializes.rs +++ b/crates/lcode-config/src/config/user_serializes.rs @@ -27,13 +27,9 @@ where serializer.serialize_str(res) } -pub(super) const fn cargo_default() -> bool { +pub(super) const fn default_true() -> bool { true } -/// return false -pub(super) const fn default_ser_bool() -> bool { - false -} pub(super) fn lang_default() -> String { "rust".to_owned() } diff --git a/crates/lcode/src/app/impl_app/get_info.rs b/crates/lcode/src/app/impl_app/get_info.rs index 5035244..59b3579 100644 --- a/crates/lcode/src/app/impl_app/get_info.rs +++ b/crates/lcode/src/app/impl_app/get_info.rs @@ -6,7 +6,6 @@ use leetcode_api::{ glob_leetcode, leetcode::resps::{checkin::TotalPoints, pass_qs::PassData, user_data::UserStatus}, }; -use miette::IntoDiagnostic; use notify_rust::Notification; use ratatui::prelude::*; use ratatui_image::{Resize, picker::Picker, protocol::StatefulProtocol, thread::ThreadProtocol}; @@ -104,10 +103,8 @@ impl App<'_> { }); } - pub fn get_status_done( - &mut self, - info: (UserStatus, TotalPoints, PassData, Option), - ) -> miette::Result<()> { + #[expect(clippy::cognitive_complexity, reason = "todo refactor")] + pub fn get_status_done(&mut self, info: (UserStatus, TotalPoints, PassData, Option)) { ( self.info.user_status, self.info.points, @@ -115,46 +112,71 @@ impl App<'_> { self.info.avatar_path, ) = info; - if self.img_state.is_none() && self.info.avatar_path.is_some() { - let mut picker = - Picker::from_query_stdio().or(Err(miette::miette!("Image Picker error")))?; - - picker.set_background_color([255, 0, 255, 0]); - let dyn_img = image::ImageReader::open( - self.info - .avatar_path - .as_ref() - .expect("No avatar file"), - ) - .into_diagnostic()? - .with_guessed_format() - .into_diagnostic()? - .decode() - .into_diagnostic()? - .resize_to_fill(150, 150, ratatui_image::FilterType::Triangle); - - // Send a [ResizeProtocol] to resize and encode it in a separate thread. - let (tx_worker, rec_worker) = mpsc::channel::<(StatefulProtocol, Resize, Rect)>(); - - // Resize and encode in background thread. - let tx_main_render = self.events.tx.clone(); - thread::spawn(move || { - loop { - if let Ok((mut protocol, resize, area)) = rec_worker.recv() { - protocol.resize_encode(&resize, Rgba([0; 4]), area); - if let Err(e) = tx_main_render.send(UserEvent::RedrawImg(protocol)) { - tracing::error!("{e}"); + 'o: { + if self.img_state.is_none() + && self.info.avatar_path.is_some() + && G_USER_CONFIG.config.show_avatar + { + let mut picker = match Picker::from_query_stdio() { + Ok(p) => p, + Err(e) => { + tracing::error!("Image error: {}", e); + break 'o; + }, + }; + + picker.set_background_color([255, 0, 255, 0]); + + let dyn_img = match image::ImageReader::open(unsafe { + self.info + .avatar_path + .as_ref() + .unwrap_unchecked() + }) { + Ok(img) => img, + Err(e) => { + tracing::error!("Image error: {}", e); + break 'o; + }, + }; + let dyn_img = match dyn_img.with_guessed_format() { + Ok(i) => i, + Err(e) => { + tracing::error!("Image error: {}", e); + break 'o; + }, + }; + let dyn_img = match dyn_img.decode() { + Ok(i) => i, + Err(e) => { + tracing::error!("Image error: {}", e); + break 'o; + }, + }; + let dyn_img = dyn_img.resize_to_fill(150, 150, ratatui_image::FilterType::Triangle); + + // Send a [ResizeProtocol] to resize and encode it in a separate thread. + let (tx_worker, rec_worker) = mpsc::channel::<(StatefulProtocol, Resize, Rect)>(); + + // Resize and encode in background thread. + let tx_main_render = self.events.tx.clone(); + thread::spawn(move || { + loop { + if let Ok((mut protocol, resize, area)) = rec_worker.recv() { + protocol.resize_encode(&resize, Rgba([0; 4]), area); + if let Err(e) = tx_main_render.send(UserEvent::RedrawImg(protocol)) { + tracing::error!("{e}"); + } } } - } - }); + }); - let async_state = ThreadProtocol::new(tx_worker, picker.new_resize_protocol(dyn_img)); - self.img_state = Some(async_state); + let async_state = + ThreadProtocol::new(tx_worker, picker.new_resize_protocol(dyn_img)); + self.img_state = Some(async_state); + } } self.render(); - - Ok(()) } } diff --git a/crates/lcode/src/mytui/mod.rs b/crates/lcode/src/mytui/mod.rs index 4b96248..04d329c 100644 --- a/crates/lcode/src/mytui/mod.rs +++ b/crates/lcode/src/mytui/mod.rs @@ -29,7 +29,7 @@ pub async fn run() -> Result<()> { Term::stop()?; break; }, - UserEvent::UserInfo(info) => app.get_status_done(*info)?, + UserEvent::UserInfo(info) => app.get_status_done(*info), UserEvent::SubmitDone(s_res) => { // update info if s_res.total_correct == s_res.total_testcases { diff --git a/crates/lcode/src/mytui/ui/info.rs b/crates/lcode/src/mytui/ui/info.rs index e493d0d..cc4c6e8 100644 --- a/crates/lcode/src/mytui/ui/info.rs +++ b/crates/lcode/src/mytui/ui/info.rs @@ -1,4 +1,4 @@ -use lcode_config::global::G_THEME; +use lcode_config::global::{G_THEME, G_USER_CONFIG}; use ratatui::{prelude::*, widgets::*}; use ratatui_image::{Resize, thread::ThreadImage}; @@ -77,11 +77,13 @@ pub fn draw_info(f: &mut Frame, app: &mut App, area: Rect) { .split(chunks[0]); assert!(chunks1.len() >= 2); f.render_widget(user_info_list, chunks1[0]); - draw_avatar( - f, - app, - helper::top_right_rect(14, 9, chunks1[0].inner(Margin::new(1, 1))), - ); + if G_USER_CONFIG.config.show_avatar { + draw_avatar( + f, + app, + helper::top_right_rect(14, 9, chunks1[0].inner(Margin::new(1, 1))), + ); + } f.render_widget(pass_info_list, chunks1[1]); f.render_stateful_widget(keymap_list, chunks[1], &mut app.info.keymap.list_state); } From 3af3060f0d94ab7479e7bae18a312558fd5c3a7e Mon Sep 17 00:00:00 2001 From: saying Date: Sat, 22 Feb 2025 16:57:32 +0800 Subject: [PATCH 2/3] docs(README): udpate --- README-CN.md | 3 +++ README.md | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/README-CN.md b/README-CN.md index c76cc1b..700035a 100644 --- a/README-CN.md +++ b/README-CN.md @@ -255,6 +255,9 @@ cargo_integr = true # 是否用 fronted id 创建代码目录 dir_with_frontend_id = true + +# 是否展示头像,在kitty上工作的很好,在其他终端有可能出现问题 +show_avatar = false ``` ## 用户信息 diff --git a/README.md b/README.md index ded8400..ba3b197 100644 --- a/README.md +++ b/README.md @@ -254,7 +254,7 @@ page_size = 25 # - helix # # You can add additional parameters at the end. -# like `editor = ["vim", "--noplugin"]` +# Like `editor = ["vim", "--noplugin"]` editor = ["vim"] # Set your selected programming language. @@ -262,17 +262,21 @@ lang = "rust" # Set the location for storing code and test cases. # You can also starting with `~` -# like `code_dir = "~/.local/share/lcode"` +# Like `code_dir = "~/.local/share/lcode"`. code_dir = "/home/user/.local/share/lcode" # Checkout the [Cookies (Important)](#cookies-important) section above. browser = "" -# For better rust coding. It will add a `Cargo.toml` file +# For better rust coding. It will add a `Cargo.toml` file. cargo_integr = true -# use frontend id create code dir or not +# Use frontend id create code dir or not. dir_with_frontend_id = true + +# Show you lc avatar or not. +# Works fine in kitty, may have problems in other terminals. +show_avatar = false ``` You can checkout the info/tab3 in tui for ensure cookies is valid. From fd3aae48307f6a44af348f29e8b01ecb0e6c89d6 Mon Sep 17 00:00:00 2001 From: saying Date: Sat, 22 Feb 2025 17:01:21 +0800 Subject: [PATCH 3/3] docs(CHANGELOG): update --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ad6cb8..2c97b97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- Add `show_avatar` config field. + ## [0.9.8] ### Fixed