feat(settings): add grouped configuration hub, languages and tray controls

This commit is contained in:
aria committed 2026-10-28 03:37:22 +09:00
1 parent 6f34fd080f
commit cc3b6f903f
90 files changed
+3625 -408

No files matched your search

+8 -2
View File
@@ -21,8 +21,14 @@ pub(super) fn view<'a>(
opacity: p,
} = style;
if let Some(a) = &shell.status.audio {
let mut volume_heading = row![shell.render.text("Volume").size(13).width(Length::Fill)]
.align_y(Alignment::Center);
let mut volume_heading = row![
shell
.render
.text(ferese_config::tr!("Volume"))
.size(13)
.width(Length::Fill)
]
.align_y(Alignment::Center);
if combined {
volume_heading = volume_heading.push(shell_switch(
shell.render,
+2
View File
@@ -146,6 +146,7 @@ impl FereseShell {
fn status_label(kind: Menu, s: &Snapshot) -> String {
match kind {
Menu::Tray => "Application tray".into(),
Menu::Network => match &s.network {
Some(n) if n.enabled => format!(
"Wi-Fi: {}",
@@ -202,6 +203,7 @@ pub(super) fn audio_icon(volume: u8, muted: bool) -> &'static [u8] {
pub(super) fn status_icon(kind: Menu, s: &Snapshot) -> (&'static [u8], bool) {
match kind {
Menu::Tray => (ferese_theme::icons::APPLICATION, true),
Menu::NightLight => (
ferese_theme::icons::MOON,
s.night_light.as_ref().is_some_and(|s| s.enabled),
+2 -2
View File
@@ -73,7 +73,7 @@ pub(super) fn view<'a>(
rows = rows.push(
shell
.render
.text("Power Profiles service unavailable")
.text(ferese_config::tr!("Power Profiles service unavailable"))
.size(12)
.class(theme::Text::Color(muted)),
);
@@ -136,7 +136,7 @@ pub(super) fn brightness<'a>(
} = style;
if let Some(value) = shell.status.brightness {
let brightness = column![
shell.render.text("Brightness").size(13),
shell.render.text(ferese_config::tr!("Brightness")).size(13),
slider_row(
shell.render,
ferese_theme::icons::BRIGHTNESS,
@@ -50,7 +50,7 @@ pub(super) fn view<'a>(
shell.render.text(device).size(14),
shell
.render
.text("Connected")
.text(ferese_config::tr!("Connected"))
.size(12)
.class(theme::Text::Color(muted)),
]
+21 -3
View File
@@ -18,9 +18,27 @@ pub(super) fn view<'a>(
render.font,
opacity,
[
menu_button(render, "‹", Message::CalendarMonth(-1), primary, opacity),
menu_button(render, "Today", Message::CalendarToday, primary, opacity),
menu_button(render, "›", Message::CalendarMonth(1), primary, opacity),
menu_button(
render,
ferese_config::tr!("‹"),
Message::CalendarMonth(-1),
primary,
opacity,
),
menu_button(
render,
ferese_config::tr!("Today"),
Message::CalendarToday,
primary,
opacity,
),
menu_button(
render,
ferese_config::tr!("›"),
Message::CalendarMonth(1),
primary,
opacity,
),
],
)
}
+1 -1
View File
@@ -82,7 +82,7 @@ pub(super) fn level_meter(
opacity: f32,
) -> Element<'static, cosmic::Action<Message>> {
let segment = move |amount: u16, filled: bool| {
container(render.text(""))
container(render.text(ferese_config::tr!("")))
.width(Length::FillPortion(amount))
.height(5)
.class(theme::Container::custom(move |_| container::Style {
+3 -3
View File
@@ -79,7 +79,7 @@ pub(super) fn bar<'a>(
width: Option<f32>,
) -> Element<'a, cosmic::Action<Message>> {
let Some(player) = &shell.media.snapshot.selected else {
return shell.render.text("").into();
return shell.render.text(ferese_config::tr!("")).into();
};
let foreground = color(if selected {
palette.accent
@@ -302,7 +302,7 @@ pub(super) fn hub<'a>(
return rows.push(
shell
.render
.text("No active player")
.text(ferese_config::tr!("No active player"))
.size(14)
.class(theme::Text::Color(style.muted)),
);
@@ -624,7 +624,7 @@ pub(super) fn view<'a>(
rows = rows.push(
shell
.render
.text("No active player")
.text(ferese_config::tr!("No active player"))
.size(13)
.class(theme::Text::Color(style.muted)),
);
+17 -13
View File
@@ -39,6 +39,7 @@ struct MenuStyle {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Menu {
Tray,
NightLight,
Activities,
Workspaces,
@@ -90,7 +91,8 @@ impl Menu {
}
fn title(self) -> &'static str {
match self {
ferese_config::locale::text(match self {
Self::Tray => "Application tray",
Self::NightLight => "Night light",
Self::Activities => "Activities",
Self::Workspaces => "Workspaces",
@@ -105,12 +107,12 @@ impl Menu {
Self::CaptureStatus => "Capture status",
Self::Media => "Now playing",
Self::Notifications => "Notifications",
}
})
}
fn available(self, status: &Snapshot) -> bool {
match self {
Self::NightLight => true,
Self::Tray | Self::NightLight => true,
Self::Network => status.network.is_some(),
Self::Bluetooth => status.bluetooth.is_some(),
Self::Audio => status.audio.is_some(),
@@ -207,7 +209,7 @@ impl FereseShell {
{
rows = rows.push(toggle_row(
self.render,
"Wi-Fi",
ferese_config::tr!("Wi-Fi"),
network.enabled,
Action::Wifi(!network.enabled),
theme,
@@ -219,7 +221,7 @@ impl FereseShell {
{
rows = rows.push(toggle_row(
self.render,
"Mute",
ferese_config::tr!("Mute"),
audio.muted,
Action::Mute(!audio.muted),
theme,
@@ -227,6 +229,7 @@ impl FereseShell {
));
}
let mut rows = match kind {
Menu::Tray => rows.push(self.tray_menu()),
Menu::System => system::view(self, rows, style, true),
Menu::NightLight => night_light::view(self, rows, style),
Menu::Network => network::view(self, rows, style),
@@ -245,14 +248,14 @@ impl FereseShell {
if self.notifications.entries.is_empty() {
rows = rows.push(
self.render
.text("No notifications")
.text(ferese_config::tr!("No notifications"))
.size(13)
.class(theme::Text::Color(style.muted)),
);
} else {
rows = rows.push(menu_button(
self.render,
"Clear notifications",
ferese_config::tr!("Clear notifications"),
Message::ClearNotifications,
style.muted,
opacity,
@@ -269,7 +272,7 @@ impl FereseShell {
.width(Length::Fill),
menu_button(
self.render,
"×",
ferese_config::tr!("×"),
Message::RemoveNotification(notice.id),
style.muted,
opacity
@@ -322,7 +325,7 @@ impl FereseShell {
if !self.capture_status.active() {
rows = rows.push(
self.render
.text("No active screen sharing or OBS output")
.text(ferese_config::tr!("No active screen sharing or OBS output"))
.size(13)
.class(theme::Text::Color(style.muted)),
);
@@ -349,7 +352,7 @@ impl FereseShell {
if !kind.available(&self.status) {
rows = rows.push(
self.render
.text("Service unavailable")
.text(ferese_config::tr!("Service unavailable"))
.size(13)
.class(theme::Text::Color(style.muted)),
);
@@ -378,7 +381,7 @@ impl FereseShell {
fn view_status_menu(&self) -> Element<'_, cosmic::Action<Message>> {
let Some(menu) = &self.menu else {
return self.render.text("").into();
return self.render.text(ferese_config::tr!("")).into();
};
motion::frame_driven(
menu.motion.revision(),
@@ -405,7 +408,7 @@ impl FereseShell {
fn view_status_menu_at(&self, now: Instant) -> Element<'_, cosmic::Action<Message>> {
let Some(menu) = &self.menu else {
return self.render.text("").into();
return self.render.text(ferese_config::tr!("")).into();
};
if menu.kind == Menu::Notifications && self.notifications.ready {
return cosmic::widget::autosize::autosize(
@@ -461,6 +464,7 @@ impl FereseShell {
rows = rows.push(heading);
}
rows = match kind {
Menu::Tray => rows.push(self.tray_menu()),
Menu::System => system::view(self, rows, style, false),
Menu::NightLight => night_light::view(self, rows, style),
Menu::Network => network::view(self, rows, style),
@@ -480,7 +484,7 @@ impl FereseShell {
if kind != Menu::Calendar && !kind.available(&self.status) {
rows = rows.push(
self.render
.text("Service unavailable")
.text(ferese_config::tr!("Service unavailable"))
.size(13)
.class(theme::Text::Color(muted)),
);
+1 -1
View File
@@ -50,7 +50,7 @@ pub(super) fn view<'a>(
row![
shell
.render
.text("Signal strength")
.text(ferese_config::tr!("Signal strength"))
.size(12)
.width(Length::Fill),
shell.render.text(strength).size(12)
@@ -8,7 +8,12 @@ pub(super) fn view<'a>(
style: MenuStyle,
) -> MenuRows<'a> {
let Some(status) = &shell.status.night_light else {
return rows.push(shell.render.text("Night light is unavailable").size(13));
return rows.push(
shell
.render
.text(ferese_config::tr!("Night light is unavailable"))
.size(13),
);
};
rows = rows.push(toggle_row(
shell.render,
@@ -29,7 +34,10 @@ pub(super) fn view<'a>(
))
.step(100u16)
.on_release(cosmic::Action::App(Message::CommitNightLightTemperature)),
shell.render.text("Lower temperatures are warmer").size(12),
shell
.render
.text(ferese_config::tr!("Lower temperatures are warmer"))
.size(12),
]
.spacing(8);
rows = rows.push(control_card(
@@ -42,14 +50,16 @@ pub(super) fn view<'a>(
rows = rows.push(
shell
.render
.text("No display supports night light")
.text(ferese_config::tr!("No display supports night light"))
.size(13),
);
} else if status.enabled && status.failed_outputs > 0 {
rows = rows.push(
shell
.render
.text("Night light could not be applied to some displays")
.text(ferese_config::tr!(
"Night light could not be applied to some displays"
))
.size(12),
);
}
+7 -4
View File
@@ -56,7 +56,7 @@ pub(super) fn view<'a>(
)
.opacity(p),
)
.name("Open Ferese Settings")
.name(ferese_config::tr!("Open Ferese Settings"))
.width(30)
.height(28)
.padding([5, 3])
@@ -67,7 +67,10 @@ pub(super) fn view<'a>(
);
modes = modes.push(cosmic::widget::tooltip(
settings,
shell.render.text("Open Ferese Settings").size(12),
shell
.render
.text(ferese_config::tr!("Open Ferese Settings"))
.size(12),
cosmic::widget::tooltip::Position::Left,
));
}
@@ -129,7 +132,7 @@ pub(super) fn view<'a>(
.center_y(28),
shell
.render
.text("Battery")
.text(ferese_config::tr!("Battery"))
.size(11)
.width(Length::Fill)
.height(16)
@@ -281,7 +284,7 @@ pub(super) fn heading<'a>(
color_with_opacity(theme.accent, p),
))
.padding(6)
.name("Open Settings")
.name(ferese_config::tr!("Open Settings"))
.on_press(cosmic::Action::App(Message::Control(Action::Settings))),
primary,
false,