Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06e97b9f50 | ||
|
|
601ec92181 | ||
|
|
713526b2a8 | ||
|
|
450121b591 | ||
|
|
eab9357f23 | ||
|
|
57f21a0edf |
+33
-1
@@ -2432,6 +2432,35 @@ fn view(state: &AppState) -> Element<'_, AppMessage> {
|
||||
.spacing(10)
|
||||
.width(iced::Length::Fill);
|
||||
|
||||
let remove_background: Element<'_, AppMessage> = if state.config.background.is_some() {
|
||||
button(text("Remove background").size(13))
|
||||
.on_press(AppMessage::RemoveBackground)
|
||||
.style(b_style(color_surface, color_blue, color_text, 6.0))
|
||||
.padding(8)
|
||||
.into()
|
||||
} else {
|
||||
iced::widget::Space::new().width(0.0).height(0.0).into()
|
||||
};
|
||||
let background_section = column![
|
||||
row![
|
||||
button(text("Choose image…").size(13))
|
||||
.on_press(AppMessage::PickBackgroundFile)
|
||||
.style(b_style(color_surface, color_blue, color_text, 6.0))
|
||||
.padding(8),
|
||||
remove_background,
|
||||
].spacing(8),
|
||||
text(format!("Background dimming: {:.0}%", state.config.background_dim * 100.0))
|
||||
.size(11)
|
||||
.color(color_subtext),
|
||||
slider(0.0..=1.0, state.config.background_dim, AppMessage::SetBackgroundDim)
|
||||
.step(0.05),
|
||||
text("Set a picture from your computer as the app background. Auto-resized; a dimming overlay keeps text readable. Applies live.")
|
||||
.size(11)
|
||||
.color(color_subtext),
|
||||
]
|
||||
.spacing(10)
|
||||
.width(iced::Length::Fill);
|
||||
|
||||
// Inline avatar chooser (W4): the monogram fallback plus the bundled
|
||||
// presets, each a clickable tile. Same SelectAvatar message, applied live
|
||||
// + persisted (and re-announced to the room).
|
||||
@@ -2780,6 +2809,9 @@ fn view(state: &AppState) -> Element<'_, AppMessage> {
|
||||
vertical_space(section_gap),
|
||||
section_header("Theme"),
|
||||
theme_section,
|
||||
vertical_space(section_gap),
|
||||
section_header("Background"),
|
||||
background_section,
|
||||
]
|
||||
.spacing(10)
|
||||
.width(iced::Length::Fill)
|
||||
@@ -3725,7 +3757,7 @@ fn view(state: &AppState) -> Element<'_, AppMessage> {
|
||||
.padding(15)
|
||||
.width(iced::Length::Fill)
|
||||
.height(iced::Length::Fill)
|
||||
.style(c_style(color_crust, Color::TRANSPARENT, 0.0));
|
||||
.style(c_style(root_bg, Color::TRANSPARENT, 0.0));
|
||||
|
||||
with_hotkey_info(
|
||||
with_pixelpass_help(with_layout_picker(room.into(), state), state),
|
||||
|
||||
+64
-4
@@ -60,6 +60,9 @@ pub enum AppTheme {
|
||||
GruvboxDark,
|
||||
SolarizedLight,
|
||||
GruvboxLight,
|
||||
AyuDark,
|
||||
AyuMirage,
|
||||
AyuLight,
|
||||
}
|
||||
|
||||
/// Build a `Color` from a packed `0xRRGGBB` literal — keeps the palette tables
|
||||
@@ -70,7 +73,7 @@ fn hex(c: u32) -> Color {
|
||||
|
||||
impl AppTheme {
|
||||
/// Every theme, in picker order.
|
||||
pub const ALL: [AppTheme; 10] = [
|
||||
pub const ALL: [AppTheme; 13] = [
|
||||
AppTheme::Mocha,
|
||||
AppTheme::Macchiato,
|
||||
AppTheme::Frappe,
|
||||
@@ -81,6 +84,9 @@ impl AppTheme {
|
||||
AppTheme::GruvboxDark,
|
||||
AppTheme::SolarizedLight,
|
||||
AppTheme::GruvboxLight,
|
||||
AppTheme::AyuDark,
|
||||
AppTheme::AyuMirage,
|
||||
AppTheme::AyuLight,
|
||||
];
|
||||
|
||||
/// Human-readable name for the picker.
|
||||
@@ -96,6 +102,9 @@ impl AppTheme {
|
||||
AppTheme::GruvboxDark => "Gruvbox Dark",
|
||||
AppTheme::SolarizedLight => "Solarized Light",
|
||||
AppTheme::GruvboxLight => "Gruvbox Light",
|
||||
AppTheme::AyuDark => "Ayu Dark",
|
||||
AppTheme::AyuMirage => "Ayu Mirage",
|
||||
AppTheme::AyuLight => "Ayu Light",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +112,10 @@ impl AppTheme {
|
||||
pub fn is_dark(self) -> bool {
|
||||
!matches!(
|
||||
self,
|
||||
AppTheme::Latte | AppTheme::SolarizedLight | AppTheme::GruvboxLight
|
||||
AppTheme::Latte
|
||||
| AppTheme::SolarizedLight
|
||||
| AppTheme::GruvboxLight
|
||||
| AppTheme::AyuLight
|
||||
)
|
||||
}
|
||||
|
||||
@@ -120,6 +132,8 @@ impl AppTheme {
|
||||
AppTheme::GruvboxDark => iced::Theme::GruvboxDark,
|
||||
AppTheme::SolarizedLight => iced::Theme::SolarizedLight,
|
||||
AppTheme::GruvboxLight => iced::Theme::GruvboxLight,
|
||||
AppTheme::AyuDark | AppTheme::AyuMirage => iced::Theme::TokyoNight,
|
||||
AppTheme::AyuLight => iced::Theme::Light,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,6 +295,52 @@ impl AppTheme {
|
||||
green: hex(0x79740e),
|
||||
yellow: hex(0xb57614),
|
||||
},
|
||||
AppTheme::AyuDark => Palette {
|
||||
crust: hex(0x06080a),
|
||||
mantle: hex(0x0b0e14),
|
||||
base: hex(0x0d1017),
|
||||
surface: hex(0x1c222b),
|
||||
overlay: hex(0x565b66),
|
||||
text: hex(0xbfbdb6),
|
||||
subtext: hex(0x9da1a6),
|
||||
blue: hex(0xe6b450),
|
||||
lavender: hex(0x59c2ff),
|
||||
red: hex(0xf07178),
|
||||
maroon: hex(0xff8f40),
|
||||
green: hex(0xaad94c),
|
||||
yellow: hex(0xffb454),
|
||||
},
|
||||
AppTheme::AyuMirage => Palette {
|
||||
crust: hex(0x171b24),
|
||||
mantle: hex(0x1a1f29),
|
||||
base: hex(0x1f2430),
|
||||
surface: hex(0x232834),
|
||||
overlay: hex(0x707a8c),
|
||||
text: hex(0xcccac2),
|
||||
subtext: hex(0xa6abb4),
|
||||
blue: hex(0xffcc66),
|
||||
lavender: hex(0x73d0ff),
|
||||
red: hex(0xf28779),
|
||||
maroon: hex(0xffa759),
|
||||
green: hex(0xd5ff80),
|
||||
yellow: hex(0xffd173),
|
||||
},
|
||||
// Ayu Light's canonical orange is deepened for legibility on white.
|
||||
AppTheme::AyuLight => Palette {
|
||||
crust: hex(0xe6e9ec),
|
||||
mantle: hex(0xf3f4f5),
|
||||
base: hex(0xfcfcfc),
|
||||
surface: hex(0xe8eaed),
|
||||
overlay: hex(0x8a9199),
|
||||
text: hex(0x5c6166),
|
||||
subtext: hex(0x737980),
|
||||
blue: hex(0xc7500e),
|
||||
lavender: hex(0x399ee6),
|
||||
red: hex(0xf07171),
|
||||
maroon: hex(0xfa8d3e),
|
||||
green: hex(0x86b300),
|
||||
yellow: hex(0xff9940),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -371,11 +431,11 @@ mod tests {
|
||||
fn all_themes_distinct_and_labeled() {
|
||||
// ALL covers exactly the variants once, each with a unique non-empty label
|
||||
// and a distinct base colour (so swatches don't look identical).
|
||||
assert_eq!(AppTheme::ALL.len(), 10);
|
||||
assert_eq!(AppTheme::ALL.len(), 13);
|
||||
let mut labels: Vec<&str> = AppTheme::ALL.iter().map(|t| t.label()).collect();
|
||||
labels.sort_unstable();
|
||||
labels.dedup();
|
||||
assert_eq!(labels.len(), 10, "labels must be unique + non-empty");
|
||||
assert_eq!(labels.len(), 13, "labels must be unique + non-empty");
|
||||
assert!(labels.iter().all(|l| !l.is_empty()));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user