feat(settings): refine density, group detailed options and add edge maximize gestures

This commit is contained in:
aria committed 2026-10-28 04:49:27 +09:00
1 parent d7e122711a
commit 9908dde9f8
11 files changed
+588 -195

No files matched your search

+154 -114
View File
@@ -17,7 +17,7 @@ impl App {
fn page_layout(&self, compact: bool, height: f32, width: f32) -> Element<'_, Message> {
let palette = visuals::Palette::from_resolved(&self.resolved.presented);
let mut sidebar = column([])
let sidebar = column([])
.spacing(4)
.push(
widget::mouse_area(
@@ -31,7 +31,8 @@ impl App {
)
.width(Length::Fill),
)
.on_press(Message::DragWindow)
.on_drag(Message::DragWindow)
.on_double_click(Message::ToggleMaximize)
.interaction(cosmic::iced::mouse::Interaction::Grab),
)
.push(widget::Space::new().height(14))
@@ -44,15 +45,7 @@ impl App {
.size(12),
)
.push(widget::Space::new().height(8));
if compact {
sidebar = sidebar.push(self.settings_button(
ferese_config::tr!("Close navigation"),
"M6 6l12 12 M6 18L18 6",
Some(Message::Sidebar(false)),
false,
));
}
let mut navigation = column([]).spacing(24);
let mut navigation = column([]).spacing(20);
for (title, pages) in Page::NAVIGATION {
let mut section = column([]).spacing(3).push(
container(
@@ -62,8 +55,12 @@ impl App {
} else {
title
}),
11.,
visuals::SECTION_TITLE_SIZE,
)
.font(cosmic::iced::Font {
weight: cosmic::iced::font::Weight::Bold,
..self.font
})
.class(cosmic::theme::Text::Color(palette.muted)),
)
.padding([0, 8]),
@@ -140,35 +137,21 @@ impl App {
.height(Length::Fill)
.padding([24, 12])
.class(visuals::sidebar(palette));
let mut heading = row([]).align_y(Alignment::Center).spacing(12).push(
column([])
.spacing(3)
.push(
self.label(
if self.search.is_empty() {
self.page.navigation_page().title()
} else {
"Search"
},
24.,
)
.font(cosmic::iced::Font {
weight: cosmic::iced::font::Weight::Medium,
..self.font
}),
)
.push(
self.label(
if self.search.is_empty() {
self.page.subtitle()
} else {
"Find a setting for your desktop."
},
12.,
)
.class(cosmic::theme::Text::Color(palette.muted)),
)
.width(Length::Fill),
let sidebar = self.window_chrome(sidebar);
let mut heading = row([]).align_y(Alignment::Center).spacing(16).push(
self.label(
if self.search.is_empty() {
self.page.navigation_page().title()
} else {
ferese_config::tr!("Search")
},
visuals::PAGE_TITLE_SIZE,
)
.font(cosmic::iced::Font {
weight: cosmic::iced::font::Weight::Medium,
..self.font
})
.width(Length::Fill),
);
if self.page == Page::Theme && self.search.is_empty() {
let automatic = self.draft.string("theme.mode", "dark") == "auto";
@@ -223,7 +206,7 @@ impl App {
));
}
let mut body = column([]).spacing(6);
let mut body = column([]).spacing(20);
if !self.search.is_empty() {
let pages = || {
@@ -260,23 +243,12 @@ impl App {
} else {
if self.page == Page::Appearance {
body = body.push(
self.settings_hub((width - if compact { 0. } else { 208. }).min(1040.) - 62.),
self.settings_hub((width - if compact { 0. } else { 208. }).min(1280.) - 54.),
);
}
if self.page == Page::Configuration {
body = body.push(self.all_options_view());
}
if self.page == Page::Tray {
body = body
.push(self.tray_application_controls())
.push(self.tray_status_controls());
}
if self.page == Page::Windows {
body = body.push(visuals::preview_resolved(
&self.draft,
&self.resolved.presented,
));
}
if self.page == Page::Theme {
let split = visuals::split(&self.draft);
if split {
@@ -315,55 +287,84 @@ impl App {
schema::fields(self.page)
};
if !fields.is_empty() {
let mut group = column([]).spacing(1);
if self.page == Page::Theme && self.auto_details {
group = group.push(self.auto_controls());
}
for field in fields {
if self.page == Page::Theme
&& (field.path == "theme.mode"
let fields = fields
.into_iter()
.filter(|field| {
self.page != Page::Theme
|| !(field.path == "theme.mode"
|| field.path.starts_with("theme.schedule.")
|| field.path.ends_with(".file"))
{
continue;
}
group = group.push(self.field(field));
})
.collect();
for group in schema::grouped_fields(self.page, fields) {
let title = group.title;
let mut rows = column([]).spacing(4);
if self.page == Page::Windows && title == "Focus and window effects" {
rows = rows.push(visuals::preview_resolved(
&self.draft,
&self.resolved.presented,
));
}
if self.page == Page::Theme {
group = group.push(
button::custom(
row([])
.spacing(8)
.align_y(Alignment::Center)
.push(self.label(ferese_config::tr!("Advanced customization"), 13.))
.push(visuals::action_icon(
if self.advanced_theme {
"M6 15l6-6 6 6"
} else {
"M6 9l6 6 6-6"
},
palette.muted,
)),
)
.name(if self.advanced_theme {
"Collapse advanced customization"
} else {
"Expand advanced customization"
})
.padding([7, 10])
.width(Length::Fill)
.class(visuals::button_style(palette, false))
.on_press(Message::AdvancedTheme(!self.advanced_theme)),
for field in group.fields {
rows = rows.push(self.field(field));
}
body = body.push(
column([])
.spacing(10)
.push(self.panel_heading(
ferese_config::locale::text(title),
visuals::SECTION_TITLE_SIZE,
))
.push(container(rows).padding(4).class(visuals::section(palette))),
);
}
if self.page == Page::Theme {
if self.auto_details {
body = body.push(
column([])
.spacing(10)
.push(
self.panel_heading(ferese_config::tr!("Automatic appearance"), 14.),
)
.push(self.auto_controls()),
);
if self.advanced_theme {
group = group.push(self.theme_file_picker());
}
}
body = body.push(container(group).padding(4).class(visuals::section(palette)));
body = body.push(
button::custom(
row([])
.spacing(10)
.align_y(Alignment::Center)
.push(self.label(ferese_config::tr!("Advanced customization"), 13.))
.push(visuals::action_icon(
if self.advanced_theme {
"M6 15l6-6 6 6"
} else {
"M6 9l6 6 6-6"
},
palette.muted,
)),
)
.name(if self.advanced_theme {
"Collapse advanced customization"
} else {
"Expand advanced customization"
})
.padding([8, 12])
.width(Length::Fill)
.class(visuals::button_style(palette, false))
.on_press(Message::AdvancedTheme(!self.advanced_theme)),
);
if self.advanced_theme {
body = body.push(self.theme_file_picker());
}
}
match self.page {
Page::Tray => {
body = body
.push(self.tray_application_controls())
.push(self.tray_status_controls())
}
Page::Connections => body = body.push(self.connections_view()),
Page::LockScreen => {
body = body.push(self.note(ferese_config::tr!("Uses your wallpaper, shell colors, font and corner radius from Appearance. Changes apply when the locker or preview opens.")));
@@ -443,6 +444,8 @@ impl App {
);
}
Page::Shortcuts => {
body =
body.push(self.panel_heading(ferese_config::tr!("Custom shortcuts"), 14.));
body = body.push(self.note(ferese_config::tr!("Keyboard, mouse and swipe bindings share the same actions. Mouse shortcuts can use MouseLeft, MouseRight, MouseMiddle, MouseBack, MouseForward or WheelUp/Down/Left/Right with modifiers. Use pointer-move or pointer-resize for dragging. Swipes use Swipe3Up, Swipe3Down, Swipe3Left or Swipe3Right (also supports 4 or 5 fingers). Actions such as toggle-overview and none need no argument.")));
let mut gestures = row([]).spacing(6);
for (keys, label) in [
@@ -536,7 +539,8 @@ impl App {
}
page_heading = page_heading.push(
widget::mouse_area(heading.width(Length::Fill))
.on_press(Message::DragWindow)
.on_drag(Message::DragWindow)
.on_double_click(Message::ToggleMaximize)
.interaction(cosmic::iced::mouse::Interaction::Grab),
);
let mut content = column([]).spacing(16).push(page_heading);
@@ -700,28 +704,64 @@ impl App {
} else {
sidebar.into()
};
let body_width = (width - if compact { 0. } else { 208. }).max(0.);
let outer_gutter = ((body_width - 1280.) / 2.).max(0.);
let blank = |id: &'static str, w: Length, h: Length| {
self.window_chrome(container(widget::Space::new().width(w).height(h)).id(id))
};
let frame = column([])
.push(blank(
"settings-top-blank",
Length::Fill,
Length::Fixed(16.),
))
.push(
row([])
.push(blank(
"settings-left-blank",
Length::Fixed(20.),
Length::Fill,
))
.push(
column([])
.push(content.height(Length::Fill))
.push(footer)
.spacing(8)
.width(Length::Fill)
.height(Length::Fill),
)
.push(blank(
"settings-right-blank",
Length::Fixed(20.),
Length::Fill,
))
.height(Length::Fill),
)
.push(blank(
"settings-bottom-blank",
Length::Fill,
Length::Fixed(12.),
))
.width(Length::Fill)
.height(Length::Fill);
let view = row([]).push(sidebar).push(
container(
container(
column([])
.push(content.height(Length::Fill))
.push(footer)
.spacing(6),
)
.padding(cosmic::iced::Padding {
top: 24.,
right: 24.,
bottom: 8.,
left: 24.,
})
.max_width(if self.page == Page::Bar { 1120 } else { 1040 })
.width(Length::Fill)
.height(Length::Fill),
row([])
.push(blank(
"settings-outer-left-blank",
Length::Fixed(outer_gutter),
Length::Fill,
))
.push(frame)
.push(blank(
"settings-outer-right-blank",
Length::Fixed(outer_gutter),
Length::Fill,
)),
)
.width(Length::Fill)
.center_x(Length::Fill)
.height(Length::Fill)
.id("settings-page")
.width(Length::Fill)
.height(Length::Fill)
.class(visuals::surface(palette.background, 0.)),
);
// Keep the page mounted and full-width while compact navigation is open.