feat(myqbz): My QBZ rename/change-icon in Settings>Appearance (DQ3)
Phase-2 Slice 12a. Per the user's decision (DQ3), the "My QBZ" rename/change-icon
lives in Settings > Appearance, not a sidebar context menu:
- src/myqbz_prefs.rs: per-user {label, icon_path} persisted to
users/<id>/myqbz_branding.json (scoped like plex_settings/tray_settings);
init_for_user/seed/set_label/pick_icon(rfd)/reset_icon. Blank label coerces to
"My QBZ"; a missing/deleted custom icon falls back to the default my-qbz.svg
without crashing (path preserved). 4 unit tests.
- ui/settings/AppearanceSettings.slint: a "My QBZ" SettingRow (icon preview +
label LineEdit + Change icon... + Reset).
- ui/shell/Sidebar.slint: the My QBZ row binds label/icon to MyQbzBrandingState
(raw-icon flag renders a custom user image untinted; default glyph stays tinted).
- Seeded on enter_shell.
Backend crates untouched. cargo check -p qbz-slint green.
cc
This commit is contained in:
6 files changed
+419
-6
No files matched your search
@@ -14,7 +14,7 @@ import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { ThemeState } from "../foundation/theme-state.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { AppearanceState, SidebarState, ShellState, ToastState } from "../state.slint";
|
||||
import { AppearanceState, SidebarState, ShellState, ToastState, MyQbzBrandingState } from "../state.slint";
|
||||
import { QbzToggle } from "../primitives/QbzToggle.slint";
|
||||
import { QbzSelect } from "../primitives/QbzSelect.slint";
|
||||
import { QbzIcon } from "../primitives/QbzIcon.slint";
|
||||
@@ -298,6 +298,64 @@ export component AppearanceSettings inherits VerticalLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
// "My QBZ" nav branding — rename + change-icon, re-homed from the Tauri
|
||||
// sidebar context-menu modal (DQ3). The label input commits on edit
|
||||
// (blank coerces to "My QBZ" in Rust); the icon picker / reset persist a
|
||||
// custom image path. The sidebar "My QBZ" row reflects both live.
|
||||
SettingRow {
|
||||
label: @tr("My QBZ");
|
||||
description: @tr("Rename the My QBZ hub and pick a custom icon. Leave the name blank to restore the default.");
|
||||
HorizontalLayout {
|
||||
spacing: 8px;
|
||||
// Icon preview — the user image as-is (custom) or the default
|
||||
// branded glyph tinted to text colour (matches the picker preview
|
||||
// being a raw image, not the sidebar's accent mask).
|
||||
Rectangle {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: Radius.sm;
|
||||
border-width: 1px;
|
||||
border-color: Theme.border-subtle;
|
||||
background: Theme.surface-elevated;
|
||||
if MyQbzBrandingState.has-custom-icon: Image {
|
||||
source: MyQbzBrandingState.custom-icon;
|
||||
image-fit: contain;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
if !MyQbzBrandingState.has-custom-icon: QbzIcon {
|
||||
source: @image-url("../assets/icons/my-qbz.svg");
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
tint: Theme.text-secondary;
|
||||
}
|
||||
}
|
||||
// Label input — commits on edit; the placeholder is the default.
|
||||
VerticalLayout {
|
||||
alignment: center;
|
||||
width: 150px;
|
||||
name-edit := LineEdit {
|
||||
text: MyQbzBrandingState.label;
|
||||
placeholder-text: @tr("My QBZ");
|
||||
edited(s) => {
|
||||
MyQbzBrandingState.set-label(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
SecondaryButton {
|
||||
label: @tr("Change icon...");
|
||||
clicked => {
|
||||
MyQbzBrandingState.pick-icon();
|
||||
}
|
||||
}
|
||||
SecondaryButton {
|
||||
label: @tr("Reset");
|
||||
clicked => {
|
||||
MyQbzBrandingState.reset-icon();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SettingRow {
|
||||
label: @tr("Show playlist cover collages in sidebar");
|
||||
description: @tr("Render a 2×2 thumbnail of track covers next to each playlist. Disable on low-end machines to skip the extra images.");
|
||||
|
||||
Reference in new issue
Block a user