From 37abb5c1913558fab259b9e389c253d84078ec81 Mon Sep 17 00:00:00 2001 From: unsecretised Date: Fri, 23 Jan 2026 08:53:16 +0800 Subject: [PATCH] improve styling --- src/app.rs | 2 +- src/app/pages/clipboard.rs | 10 ++-- src/app/tile/elm.rs | 116 ++++++++++++++++++++++++++++++------- src/app/tile/update.rs | 6 +- src/styles.rs | 27 ++++----- 5 files changed, 115 insertions(+), 46 deletions(-) diff --git a/src/app.rs b/src/app.rs index 613b0f2..803342b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -73,7 +73,7 @@ pub fn default_settings() -> Settings { minimizable: false, level: window::Level::AlwaysOnTop, transparent: true, - blur: true, + blur: false, size: iced::Size { width: WINDOW_WIDTH, height: DEFAULT_WINDOW_HEIGHT, diff --git a/src/app/pages/clipboard.rs b/src/app/pages/clipboard.rs index 2206161..6bf5473 100644 --- a/src/app/pages/clipboard.rs +++ b/src/app/pages/clipboard.rs @@ -13,7 +13,7 @@ pub fn clipboard_view( ) -> Element<'static, Message> { let theme_clone = theme.clone(); let theme_clone_2 = theme.clone(); - Row::from_vec(vec![ + container(Row::from_vec(vec![ container( scrollable( Column::from_iter(clipboard_content.iter().enumerate().map(|(i, content)| { @@ -23,7 +23,7 @@ pub fn clipboard_view( ) .id("results"), ) - .height(7 * 55) + .height(385) .style(move |_| result_row_container_style(&theme_clone_2, false)) .into(), container(Scrollable::with_direction( @@ -33,7 +33,7 @@ pub fn clipboard_view( .map(|x| x.to_app().name_lc) .unwrap_or("".to_string()), ) - .height(Length::Fill) + .height(385) .width(Length::Fill) .align_x(Alignment::Start) .font(theme.font()) @@ -46,8 +46,8 @@ pub fn clipboard_view( .padding(10) .style(move |_| result_row_container_style(&theme_clone, false)) .width((WINDOW_WIDTH / 3.) * 2.) - .height(7 * 55) .into(), - ]) + ])) + .height(280) .into() } diff --git a/src/app/tile/elm.rs b/src/app/tile/elm.rs index df952f4..70d5998 100644 --- a/src/app/tile/elm.rs +++ b/src/app/tile/elm.rs @@ -5,8 +5,8 @@ use global_hotkey::hotkey::HotKey; use iced::border::Radius; use iced::widget::scrollable::{Anchor, Direction, Scrollbar}; use iced::widget::text::LineHeight; -use iced::widget::{Column, Scrollable, container, space}; -use iced::{Color, window}; +use iced::widget::{Column, Row, Scrollable, Text, container, space}; +use iced::{Alignment, Color, Length, Vector, window}; use iced::{Element, Task}; use iced::{Length::Fill, widget::text_input}; @@ -15,10 +15,12 @@ use rayon::{ slice::ParallelSliceMut, }; +use crate::app::WINDOW_WIDTH; use crate::app::pages::clipboard::clipboard_view; use crate::app::pages::emoji::emoji_page; use crate::app::tile::AppIndex; -use crate::styles::{contents_style, rustcast_text_input_style}; +use crate::config::Theme; +use crate::styles::{contents_style, rustcast_text_input_style, tint, with_alpha}; use crate::{ app::{Message, Page, apps::App, default_settings, tile::Tile}, config::Config, @@ -88,6 +90,10 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task) { pub fn view(tile: &Tile, wid: window::Id) -> Element<'_, Message> { if tile.visible { + let round_bottom_edges = match &tile.page { + Page::Main | Page::EmojiSearch => tile.results.is_empty(), + Page::ClipboardHistory => tile.clipboard_content.is_empty(), + }; let title_input = text_input(tile.config.placeholder.as_str(), &tile.query) .on_input(move |a| Message::SearchQueryChanged(a, wid)) .on_paste(move |a| Message::SearchQueryChanged(a, wid)) @@ -96,7 +102,7 @@ pub fn view(tile: &Tile, wid: window::Id) -> Element<'_, Message> { .id("query") .width(Fill) .line_height(LineHeight::Relative(1.75)) - .style(|_, status| rustcast_text_input_style(&tile.config.theme, status)) + .style(move |_, _| rustcast_text_input_style(&tile.config.theme, round_bottom_edges)) .padding(20); let scrollbar_direction = if tile.config.theme.show_scroll_bar { @@ -129,25 +135,48 @@ pub fn view(tile: &Tile, wid: window::Id) -> Element<'_, Message> { tile.focus_id, ) } else { - Column::from_iter(tile.results.iter().enumerate().map(|(i, app)| { - app.clone() - .render(tile.config.theme.clone(), i as u32, tile.focus_id) - })) + container(Column::from_iter(tile.results.iter().enumerate().map( + |(i, app)| { + app.clone() + .render(tile.config.theme.clone(), i as u32, tile.focus_id) + }, + ))) .into() }; - let scrollable = Scrollable::with_direction(results, scrollbar_direction).id("results"); - let contents = container(Column::new().push(title_input).push(scrollable).spacing(0)) - .style(|_| container::Style { - text_color: None, - background: None, - border: iced::Border { - color: Color::WHITE, - width: 1., - radius: Radius::new(5), - }, - ..Default::default() - }); + let results_count = match &tile.page { + Page::Main => tile.results.len(), + Page::ClipboardHistory => tile.clipboard_content.len(), + Page::EmojiSearch => tile.results.len(), + }; + + let height = if tile.page == Page::ClipboardHistory { + 385 + } else { + std::cmp::min(tile.results.len() * 60, 290) + }; + + let scrollable = Scrollable::with_direction(results, scrollbar_direction) + .id("results") + .height(height as u32); + + let contents = container( + Column::new() + .push(title_input) + .push(scrollable) + .push(footer(tile.config.theme.clone(), results_count)) + .spacing(0), + ) + .style(|_| container::Style { + text_color: None, + background: None, + border: iced::Border { + color: Color::TRANSPARENT, + width: 0., + radius: Radius::new(15), + }, + ..Default::default() + }); container(contents.clip(false)) .style(|_| contents_style(&tile.config.theme)) @@ -156,3 +185,50 @@ pub fn view(tile: &Tile, wid: window::Id) -> Element<'_, Message> { space().into() } } + +fn footer(theme: Theme, results_count: usize) -> Element<'static, Message> { + let text = if results_count == 0 { + return space().into(); + } else if results_count == 1 { + "1 result found" + } else { + &format!("{} results found", results_count) + }; + + container( + Row::new() + .push( + Text::new(text.to_string()) + .size(12) + .height(30) + .color(theme.text_color(0.7)) + .font(theme.font()) + .align_x(Alignment::Center), + ) + .padding(4) + .width(Fill) + .height(30), + ) + .center(Length::Fill) + .width(WINDOW_WIDTH) + .padding(5) + .style(move |_| container::Style { + text_color: None, + background: Some(iced::Background::Color(with_alpha( + tint(theme.bg_color(), 0.04), + 1.0, + ))), + border: iced::Border { + color: Color::WHITE, + width: 0., + radius: Radius::new(15).top(0), + }, + shadow: iced::Shadow { + color: Color::TRANSPARENT, + offset: Vector::ZERO, + blur_radius: 0., + }, + snap: false, + }) + .into() +} diff --git a/src/app/tile/update.rs b/src/app/tile/update.rs index e6095cb..17c609e 100644 --- a/src/app/tile/update.rs +++ b/src/app/tile/update.rs @@ -104,7 +104,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { _ => tile.results.len() as u32, }; - let old_focus_id = tile.focus_id.clone(); + let old_focus_id = tile.focus_id; if len == 0 { return Task::none(); @@ -456,7 +456,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { id, iced::Size { width: WINDOW_WIDTH, - height: ((max_elem * 55) + DEFAULT_WINDOW_HEIGHT as usize) as f32, + height: ((max_elem * 55) + 35 + DEFAULT_WINDOW_HEIGHT as usize) as f32, }, ), Task::done(Message::ChangeFocus(ArrowKey::Left)), @@ -467,7 +467,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { id, iced::Size { width: WINDOW_WIDTH, - height: ((7 * 55) + DEFAULT_WINDOW_HEIGHT as usize) as f32, + height: ((7 * 55) + 35 + DEFAULT_WINDOW_HEIGHT as usize) as f32, }, ), Task::done(Message::ChangeFocus(ArrowKey::Left)), diff --git a/src/styles.rs b/src/styles.rs index af7a2f4..2d447fb 100644 --- a/src/styles.rs +++ b/src/styles.rs @@ -1,5 +1,4 @@ use iced::border::Radius; -use iced::widget::text_input::Status; use iced::widget::{button, container}; use iced::{Background, Border, Color, widget::text_input}; @@ -19,23 +18,21 @@ pub fn with_alpha(mut c: Color, a: f32) -> Color { c } -pub fn rustcast_text_input_style(theme: &ConfigTheme, status: Status) -> text_input::Style { +pub fn rustcast_text_input_style( + theme: &ConfigTheme, + round_bottom_edges: bool, +) -> text_input::Style { let base_bg = theme.bg_color(); let surface = with_alpha(tint(base_bg, 0.06), 1.0); - let (border_color, border_width) = match status { - text_input::Status::Focused { .. } => (theme.text_color(0.20), 1.), - text_input::Status::Hovered => (theme.text_color(0.20), 1.), - text_input::Status::Active => (theme.text_color(0.20), 1.), - text_input::Status::Disabled => (theme.text_color(0.20), 1.), - }; + let border_color = theme.text_color(1.); text_input::Style { background: Background::Color(surface), border: Border { color: border_color, - width: border_width, - radius: Radius::new(5.0).bottom(0.), + width: 1., + radius: Radius::new(15.).bottom(if round_bottom_edges { 15. } else { 0. }), }, icon: theme.text_color(0.7), placeholder: theme.text_color(0.45), @@ -50,7 +47,7 @@ pub fn contents_style(theme: &ConfigTheme) -> container::Style { text_color: None, border: iced::Border { color: theme.text_color(0.7), - width: 1.0, + width: 0., radius: Radius::new(14.0), }, ..Default::default() @@ -76,12 +73,8 @@ pub fn result_row_container_style(tile: &ConfigTheme, focused: bool) -> containe container::Style { background: Some(Background::Color(row_bg)), border: Border { - color: if focused { - tile.text_color(0.35) - } else { - tile.text_color(0.10) - }, - width: 0.2, + color: tile.text_color(1.), + width: 0., radius: Radius::new(0.), }, ..Default::default()