Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::HashMap;

use crate::app::apps::{App, AppCommand, ICNS_ICON};
use crate::commands::Function;
use crate::config::{Config, MainPage, Shelly, ThemeMode};
use crate::config::{Config, GlassMode, MainPage, Shelly, ThemeMode};
use crate::debounce::DebouncePolicy;
use crate::platform::launching::Shortcut;
use crate::utils::icns_data_to_handle;
Expand All @@ -24,6 +24,21 @@ pub const WINDOW_WIDTH: f32 = 500.;
/// The default window height
pub const DEFAULT_WINDOW_HEIGHT: f32 = 100.;

/// Height of one search result row, selection inset included.
pub const RESULT_ROW_HEIGHT: f32 = 52.;

/// Space above and below the results list.
pub const RESULTS_LIST_PADDING: f32 = 6.;

/// Launcher height showing `rows` result rows under the search field.
pub const fn results_window_height(rows: usize) -> f32 {
if rows == 0 {
DEFAULT_WINDOW_HEIGHT
} else {
DEFAULT_WINDOW_HEIGHT + rows as f32 * RESULT_ROW_HEIGHT + 2. * RESULTS_LIST_PADDING
}
}

/// The clipboard history page gets a big, purpose-built window.
pub const CLIPBOARD_WIDTH: f32 = 860.;
pub const CLIPBOARD_HEIGHT: f32 = 600.;
Expand Down Expand Up @@ -210,6 +225,7 @@ pub enum ResetField {
TextColor,
BackgroundColor,
ThemeMode,
Glass,
Aliases,
Modes,
SearchDirs,
Expand Down Expand Up @@ -369,6 +385,7 @@ pub enum SetConfigThemeFields {
ShowIcons(bool),
Font(String),
ThemeMode(ThemeMode),
Glass(GlassMode),
}

#[derive(Debug, Clone)]
Expand All @@ -385,7 +402,10 @@ pub fn default_settings() -> Settings {
minimizable: false,
level: window::Level::AlwaysOnTop,
transparent: true,
blur: true,
// winit's blur asks for the whole window rectangle, which shows
// blurred square corners. The rounded region is requested per resize
// instead, and only when the glass is translucent.
blur: false,
// Map centred on the active monitor so the window never flashes at the
// window manager's default spot; `position_launcher` then nudges it up
// to the Spotlight/Raycast upper-third anchor once it is mapped.
Expand Down
69 changes: 44 additions & 25 deletions src/app/apps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use std::io::Cursor;

use iced::{
Alignment,
Length::{self, Fill},
Alignment, Color,
Length::Fill,
widget::{
Button, Row, Text, container,
image::{Handle, Viewer},
Expand All @@ -18,7 +18,10 @@ use crate::{
app::{Message, Page, RUSTCAST_DESC_NAME},
clipboard::ClipBoardContentType,
commands::Function,
styles::{favourite_button_style, result_button_style, result_row_container_style},
styles::{
PRIMARY, SECONDARY, favourite_button_style, label, result_button_style,
result_row_container_style,
},
utils::icns_data_to_handle,
};

Expand Down Expand Up @@ -250,50 +253,59 @@ impl App {
on_press: Option<Message>,
) -> iced::Element<'static, Message> {
let focused = focussed_id == id_num;
// On the accent-filled selection, labels turn white like macOS lists.
let (title_color, subtitle_color) = if focused {
(Color::WHITE, Color::from_rgba(1.0, 1.0, 1.0, 0.78))
} else {
(label(&theme, PRIMARY), label(&theme, SECONDARY))
};

// Title + subtitle (Raycast style)
// Title + subtitle (Spotlight style: 14pt title, 11pt subtitle)
let text_block = iced::widget::Column::new()
.spacing(2)
.spacing(1)
.push(
Text::new(self.display_name)
.font(theme.font())
.size(16)
.size(14)
.wrapping(Wrapping::None)
.color(theme.text_color(1.0)),
.color(title_color),
)
.push(
Text::new(self.desc)
.font(theme.font())
.size(13)
.size(11)
.wrapping(Wrapping::None)
.color(theme.text_color(0.55)),
.color(subtitle_color),
);

let mut row = Row::new()
.align_y(Alignment::Center)
.width(Fill)
.spacing(10)
.height(50);
.padding([0, 10])
.height(Fill);

if theme.show_icons
&& let Some(icon) = &self.icons
{
row = row.push(
container(Viewer::new(icon).height(40).width(40))
.width(40)
.height(40),
container(Viewer::new(icon).height(30).width(30))
.width(30)
.height(30),
);
}
row = row.push(container(text_block).width(Fill));
row = row.push(container(text_block).width(Fill).clip(true));

let name = self.search_name.clone();
let theme_clone = theme.clone();
let is_favourite = self.ranking == -1;
row = row.push(
Button::new(Text::new("♥️").width(Length::Fill).align_x(Alignment::End))
Button::new(Text::new("♥").size(13))
.on_press_with(move || Message::ToggleFavouriteApp(name.clone()))
.width(Length::Fill)
.style(move |_, status| favourite_button_style(&theme_clone, status, is_favourite)),
.padding([4, 6])
.style(move |_, status| {
favourite_button_style(&theme_clone, status, is_favourite, focused)
}),
);

let msg = on_press.or(match self.open_command.clone() {
Expand All @@ -308,14 +320,21 @@ impl App {
.on_press_maybe(msg)
.style(move |_, _| result_button_style(&theme_clone))
.width(Fill)
.padding(0)
.height(50);
.height(Fill)
.padding(0);

container(content)
.id(format!("result-{}", id_num))
.style(move |_| result_row_container_style(&theme, focused))
.padding(8)
.width(Fill)
.into()
// The selection pill is inset from the window edge; the outer
// container gives the row its fixed height.
container(
container(content)
.style(move |_| result_row_container_style(&theme, focused))
.width(Fill)
.height(Fill),
)
.id(format!("result-{}", id_num))
.padding([2, 6])
.width(Fill)
.height(crate::app::RESULT_ROW_HEIGHT)
.into()
}
}
41 changes: 17 additions & 24 deletions src/app/pages/emoji.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
app::pages::prelude::*,
clipboard::ClipBoardContentType,
commands::Function,
styles::{glass_border, glass_surface, with_alpha},
styles::{PRIMARY, label, rim, window_fill, with_alpha},
};

/// The emoji pages element to render
Expand Down Expand Up @@ -55,7 +55,7 @@ pub fn emoji_page(
.on_press(Message::RunFunction(Function::CopyToClipboard(
ClipBoardContentType::Text(emoji.display_name),
)))
.style(move |_, _| emoji_button_style(&value)),
.style(move |_, status| emoji_button_style(&value, status)),
)
.width(70)
.height(70)
Expand All @@ -64,11 +64,23 @@ pub fn emoji_page(
container(
Text::new(emoji.desc)
.font(tile_theme.font())
.size(20)
.color(tile_theme.text_color(0.7)),
.size(12)
.color(label(&tile_theme, PRIMARY)),
)
.padding([4, 8])
.style(move |_| container::Style {
background: Some(Background::Color(value_two.bg_color())),
// Tooltips are solid so they read over the emoji grid.
background: Some(Background::Color(with_alpha(window_fill(&value_two), 1.0))),
border: Border {
color: rim(&value_two),
width: 1.0,
radius: Radius::new(7.0),
},
shadow: iced::Shadow {
color: iced::Color::from_rgba(0.0, 0.0, 0.0, 0.25),
offset: iced::Vector::new(0.0, 3.0),
blur_radius: 10.0,
},
..Default::default()
}),
tooltip::Position::Top,
Expand All @@ -80,27 +92,8 @@ pub fn emoji_page(
column.push(container(emoji_row_element).center_y(70).into());
}

let tile_theme_clone = tile_theme.clone();
container(Column::from_vec(column).spacing(10))
.padding(10)
.style(move |_| container::Style {
background: Some(Background::Color(glass_surface(
tile_theme_clone.bg_color(),
false,
))),
text_color: None,
border: Border {
color: glass_border(tile_theme_clone.text_color(1.0), false),
width: 0.5,
radius: Radius::new(14.0).top(0),
},
shadow: iced::Shadow {
color: with_alpha(iced::Color::TRANSPARENT, 0.),
offset: iced::Vector::new(0.0, 10.0),
blur_radius: 28.0,
},
snap: false,
})
.center_x(WINDOW_WIDTH)
.into()
}
Loading
Loading