feat(qbz-ui): settings export modal + Developer row (04 §4.2)

Add the desktop "Export settings…" surface for the qbzd daemon epic (T18):
a Developer-settings row that opens a modal with the single default-off
"Include Qobuz login and integration tokens" gate, its warning line, and a
Cancel/Export footer. Confirm() is a Rust callback (wired next). New
SettingsExportState/SettingsExportActions globals, exported from app.slint
so the Rust layer binds them, and the modal mounted in AppShell. New strings
translated across all 8 locales (en es de fr pt ru ja nl).

cc
This commit is contained in:
vicrodh committed 2026-07-15 07:50:27 -06:00
1 parent d658a501ad
commit 897ba7128c
13 files changed
+512 -2

No files matched your search

@@ -4519,3 +4519,38 @@ msgstr "Gibt zwischengespeicherte Daten frei. Deine heruntergeladenen Alben blei
msgid "Couldn't clear the cache"
msgstr "Cache konnte nicht geleert werden"
# Task 18 — Settings > Developer > Export settings modal (daemon 04 §4.2)
msgid "SETTINGS PORTABILITY"
msgstr "EINSTELLUNGEN ÜBERTRAGEN"
msgid "Export settings…"
msgstr "Einstellungen exportieren…"
msgid "Save a portable bundle of your settings to move to another machine or the qbzd daemon."
msgstr "Speichert ein portables Bündel deiner Einstellungen, um sie auf einen anderen Rechner oder den qbzd-Daemon zu übertragen."
msgid "Export…"
msgstr "Exportieren…"
msgid "Export settings"
msgstr "Einstellungen exportieren"
msgid "Save your settings as a bundle to import on the qbzd daemon or another machine."
msgstr "Speichere deine Einstellungen als Bündel, um sie auf dem qbzd-Daemon oder einem anderen Rechner zu importieren."
msgid "Include Qobuz login and integration tokens"
msgstr "Qobuz-Anmeldung und Integrations-Tokens einschließen"
msgid "Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing."
msgstr "Wer die Datei lesen kann, kann deine Konten nutzen. Sie wird nur für dich lesbar gespeichert; lösche sie nach dem Import."
msgid "Export"
msgstr "Exportieren"
msgid "Bundle saved. On the daemon box:"
msgstr "Bündel gespeichert. Auf dem Daemon-Rechner:"
msgid "Could not export settings"
msgstr "Einstellungen konnten nicht exportiert werden"
@@ -291,3 +291,38 @@ msgstr "Cache cleared"
msgid "Couldn't clear the cache"
msgstr "Couldn't clear the cache"
# Task 18 — Settings > Developer > Export settings modal (daemon 04 §4.2)
msgid "SETTINGS PORTABILITY"
msgstr "SETTINGS PORTABILITY"
msgid "Export settings…"
msgstr "Export settings…"
msgid "Save a portable bundle of your settings to move to another machine or the qbzd daemon."
msgstr "Save a portable bundle of your settings to move to another machine or the qbzd daemon."
msgid "Export…"
msgstr "Export…"
msgid "Export settings"
msgstr "Export settings"
msgid "Save your settings as a bundle to import on the qbzd daemon or another machine."
msgstr "Save your settings as a bundle to import on the qbzd daemon or another machine."
msgid "Include Qobuz login and integration tokens"
msgstr "Include Qobuz login and integration tokens"
msgid "Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing."
msgstr "Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing."
msgid "Export"
msgstr "Export"
msgid "Bundle saved. On the daemon box:"
msgstr "Bundle saved. On the daemon box:"
msgid "Could not export settings"
msgstr "Could not export settings"
@@ -4549,3 +4549,38 @@ msgstr "Libera datos en caché. Tus álbumes descargados se conservan — elimí
msgid "Couldn't clear the cache"
msgstr "No se pudo limpiar el caché"
# Task 18 — Settings > Developer > Export settings modal (daemon 04 §4.2)
msgid "SETTINGS PORTABILITY"
msgstr "PORTABILIDAD DE AJUSTES"
msgid "Export settings…"
msgstr "Exportar ajustes…"
msgid "Save a portable bundle of your settings to move to another machine or the qbzd daemon."
msgstr "Guarda un paquete portátil de tus ajustes para llevarlos a otra máquina o al daemon qbzd."
msgid "Export…"
msgstr "Exportar…"
msgid "Export settings"
msgstr "Exportar ajustes"
msgid "Save your settings as a bundle to import on the qbzd daemon or another machine."
msgstr "Guarda tus ajustes como un paquete para importarlos en el daemon qbzd o en otra máquina."
msgid "Include Qobuz login and integration tokens"
msgstr "Incluir el inicio de sesión de Qobuz y los tokens de integraciones"
msgid "Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing."
msgstr "Cualquiera que tenga el archivo puede usar tus cuentas. Se guarda de modo que solo tú puedas leerlo; elimínalo después de importarlo."
msgid "Export"
msgstr "Exportar"
msgid "Bundle saved. On the daemon box:"
msgstr "Paquete guardado. En la máquina del daemon:"
msgid "Could not export settings"
msgstr "No se pudieron exportar los ajustes"
@@ -4519,3 +4519,38 @@ msgstr "Libère les données en cache. Vos albums téléchargés sont conservés
msgid "Couldn't clear the cache"
msgstr "Impossible de vider le cache"
# Task 18 — Settings > Developer > Export settings modal (daemon 04 §4.2)
msgid "SETTINGS PORTABILITY"
msgstr "PORTABILITÉ DES RÉGLAGES"
msgid "Export settings…"
msgstr "Exporter les réglages…"
msgid "Save a portable bundle of your settings to move to another machine or the qbzd daemon."
msgstr "Enregistre un ensemble portable de vos réglages pour les transférer vers une autre machine ou le démon qbzd."
msgid "Export…"
msgstr "Exporter…"
msgid "Export settings"
msgstr "Exporter les réglages"
msgid "Save your settings as a bundle to import on the qbzd daemon or another machine."
msgstr "Enregistrez vos réglages sous forme d'un ensemble à importer sur le démon qbzd ou une autre machine."
msgid "Include Qobuz login and integration tokens"
msgstr "Inclure la connexion Qobuz et les jetons d'intégration"
msgid "Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing."
msgstr "Quiconque peut lire le fichier peut utiliser vos comptes. Il est enregistré de façon lisible par vous seul ; supprimez-le après l'import."
msgid "Export"
msgstr "Exporter"
msgid "Bundle saved. On the daemon box:"
msgstr "Ensemble enregistré. Sur la machine du démon :"
msgid "Could not export settings"
msgstr "Impossible d'exporter les réglages"
@@ -4508,3 +4508,38 @@ msgstr "キャッシュデータを解放します。ダウンロード済みの
msgid "Couldn't clear the cache"
msgstr "キャッシュを削除できませんでした"
# Task 18 — Settings > Developer > Export settings modal (daemon 04 §4.2)
msgid "SETTINGS PORTABILITY"
msgstr "設定の移行"
msgid "Export settings…"
msgstr "設定をエクスポート…"
msgid "Save a portable bundle of your settings to move to another machine or the qbzd daemon."
msgstr "設定を持ち運び可能なバンドルとして保存し、別のマシンや qbzd デーモンに移せます。"
msgid "Export…"
msgstr "エクスポート…"
msgid "Export settings"
msgstr "設定をエクスポート"
msgid "Save your settings as a bundle to import on the qbzd daemon or another machine."
msgstr "設定をバンドルとして保存し、qbzd デーモンや別のマシンでインポートできます。"
msgid "Include Qobuz login and integration tokens"
msgstr "Qobuz のログインと連携トークンを含める"
msgid "Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing."
msgstr "ファイルを読める人は誰でもあなたのアカウントを使用できます。自分だけが読み取れる形で保存されます。インポート後は削除してください。"
msgid "Export"
msgstr "エクスポート"
msgid "Bundle saved. On the daemon box:"
msgstr "バンドルを保存しました。デーモンのマシンで:"
msgid "Could not export settings"
msgstr "設定をエクスポートできませんでした"
@@ -4531,3 +4531,38 @@ msgstr "Maakt cachegegevens vrij. Je gedownloade albums blijven behouden — ver
msgid "Couldn't clear the cache"
msgstr "Kan de cache niet wissen"
# Task 18 — Settings > Developer > Export settings modal (daemon 04 §4.2)
msgid "SETTINGS PORTABILITY"
msgstr "INSTELLINGEN OVERZETTEN"
msgid "Export settings…"
msgstr "Instellingen exporteren…"
msgid "Save a portable bundle of your settings to move to another machine or the qbzd daemon."
msgstr "Slaat een overdraagbare bundel van je instellingen op om ze naar een andere machine of de qbzd-daemon te verplaatsen."
msgid "Export…"
msgstr "Exporteren…"
msgid "Export settings"
msgstr "Instellingen exporteren"
msgid "Save your settings as a bundle to import on the qbzd daemon or another machine."
msgstr "Sla je instellingen op als bundel om ze op de qbzd-daemon of een andere machine te importeren."
msgid "Include Qobuz login and integration tokens"
msgstr "Qobuz-login en integratietokens meenemen"
msgid "Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing."
msgstr "Iedereen die het bestand kan lezen, kan je accounts gebruiken. Het wordt opgeslagen zodat alleen jij het kunt lezen; verwijder het na het importeren."
msgid "Export"
msgstr "Exporteren"
msgid "Bundle saved. On the daemon box:"
msgstr "Bundel opgeslagen. Op de daemon-machine:"
msgid "Could not export settings"
msgstr "Kan instellingen niet exporteren"
@@ -4519,3 +4519,38 @@ msgstr "Libera dados em cache. Seus álbuns baixados são mantidos — remova-os
msgid "Couldn't clear the cache"
msgstr "Não foi possível limpar o cache"
# Task 18 — Settings > Developer > Export settings modal (daemon 04 §4.2)
msgid "SETTINGS PORTABILITY"
msgstr "PORTABILIDADE DAS DEFINIÇÕES"
msgid "Export settings…"
msgstr "Exportar definições…"
msgid "Save a portable bundle of your settings to move to another machine or the qbzd daemon."
msgstr "Guarda um pacote portátil das suas definições para as levar para outra máquina ou para o daemon qbzd."
msgid "Export…"
msgstr "Exportar…"
msgid "Export settings"
msgstr "Exportar definições"
msgid "Save your settings as a bundle to import on the qbzd daemon or another machine."
msgstr "Guarde as suas definições como um pacote para importar no daemon qbzd ou noutra máquina."
msgid "Include Qobuz login and integration tokens"
msgstr "Incluir o início de sessão do Qobuz e os tokens de integrações"
msgid "Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing."
msgstr "Qualquer pessoa que consiga ler o ficheiro pode usar as suas contas. É guardado de forma legível apenas para si; elimine-o após a importação."
msgid "Export"
msgstr "Exportar"
msgid "Bundle saved. On the daemon box:"
msgstr "Pacote guardado. Na máquina do daemon:"
msgid "Could not export settings"
msgstr "Não foi possível exportar as definições"
@@ -4532,3 +4532,38 @@ msgstr "Освобождает кэшированные данные. Загру
msgid "Couldn't clear the cache"
msgstr "Не удалось очистить кэш"
# Task 18 — Settings > Developer > Export settings modal (daemon 04 §4.2)
msgid "SETTINGS PORTABILITY"
msgstr "ПЕРЕНОС НАСТРОЕК"
msgid "Export settings…"
msgstr "Экспорт настроек…"
msgid "Save a portable bundle of your settings to move to another machine or the qbzd daemon."
msgstr "Сохраняет переносимый набор ваших настроек для переноса на другой компьютер или в демон qbzd."
msgid "Export…"
msgstr "Экспорт…"
msgid "Export settings"
msgstr "Экспорт настроек"
msgid "Save your settings as a bundle to import on the qbzd daemon or another machine."
msgstr "Сохраните настройки в виде набора для импорта на демон qbzd или другой компьютер."
msgid "Include Qobuz login and integration tokens"
msgstr "Включить вход в Qobuz и токены интеграций"
msgid "Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing."
msgstr "Любой, кто получит файл, сможет пользоваться вашими аккаунтами. Он сохраняется доступным для чтения только вам; удалите его после импорта."
msgid "Export"
msgstr "Экспорт"
msgid "Bundle saved. On the daemon box:"
msgstr "Набор сохранён. На машине демона:"
msgid "Could not export settings"
msgstr "Не удалось экспортировать настройки"
+1 -1
View File
@@ -31,7 +31,7 @@ export { ThemeState } from "foundation/theme-state.slint";
export { Typography } from "foundation/typography.slint";
// Re-export the state globals so the Rust layer can populate them.
export { HomeState, HomeActions, RecentAlbumsState, DiscoverState, DiscoverActions, SectionDescriptor, ConfigRow, DiscoverBrowseState, DiscoverBrowseActions, ForYouState, ExternalRecoState, ExternalRecoActions, MixState, GenreFilterState, GenreFilterActions, AlbumState, ArtistState, NavState, ShellState, SessionState, SettingsState, AlbumActions, ArtistActions, ArtworkActions, NowPlayingState, QueueState, LyricsState, LyricsLineItem, SearchState, SearchActions, NetworkSidebarState, NetworkSidebarActions, MusicianState, MusicianActions, LabelState, LabelActions, AwardState, AwardActions, AwardEntry, ArtistReleasesState, ArtistReleasesActions, LocationViewState, LocationViewActions, FavoritesState, FavoritesActions, PlaylistPickerState, PlaylistPickerActions, DuplicateConfirmState, DuplicateConfirmActions, PlaylistState, PlaylistActions, SidebarState, SidebarActions, SidebarFolderPopupState, CreatePlaylistState, CreatePlaylistActions, EditPlaylistState, EditPlaylistActions, CreateFolderState, CreateFolderActions, MyQbzCreateState, MyQbzCreateActions, DragState, DragActions, PlaylistManagerState, PlaylistManagerActions, OfflineManagerState, OfflineManagerActions, BlacklistState, BlacklistActions, BlacklistedArtistItem, MyQbzState, MyQbzActions, MixtapeCardItem, MyQbzAddState, MyQbzAddActions, MyQbzAddRow, MyQbzDetailState, MyQbzDetailActions, MixtapeDetailItem, MyQbzEditState, MyQbzEditActions, MyQbzMixState, MyQbzMixActions, DiscoBuilderState, DiscoBuilderActions, DiscoGroup, DiscoCandidate, LocalLibraryState, LocalLibraryActions, LibraryFoldersState, LibFolderEditState, LibraryManageActions, LibraryScanState, LibAlbumFilterState, LocalAlbumState, LocalAlbumActions, TagEditorState, TagEditorActions, FolderEditState, FolderEditActions, ToastState, TextUtil, QconnectDevState, QconnectDevice, CastState, CastDevice, CastActions, AppearanceState, MyQbzBrandingState, EphemeralPlayChoiceState, EphemeralPlayChoiceActions, PlexSettingsState, PlexAuthActions, PlexSectionItem, ScrobbleState, ScrobbleActions, DiscordState, OfflineState, LoginState, OfflineModeActions, OfflineFavoritesState, OfflineFavoritesActions, ImportLogEntry, PlaylistImportState, PlaylistImportActions, DacWizardState, DacWizardActions, DacCandidateRow, RemediationRow, DacConfigRow, InfoCreditRow, InfoCreditPair, AlbumCreditPerformer, AlbumCreditTrack, TrackInfoState, TrackInfoActions, AlbumInfoState, AlbumInfoActions, BookletState, BookletActions, SuggestionsState, SuggestionsActions, SuggestionCard, PlaylistSuggestionsState, PlaylistSuggestionsActions, PlaylistSuggestionRow, VisualizerState, ImmersiveState, ImmersiveSearchActions, ImmersiveActions, MiniPlayerState, WindowControlActions, PurchasesState, PurchasesActions, PurchaseAlbumItem, PurchaseTrackItem, PurchaseAlbumGroup, PurchaseTrackGroup, PurchaseFormatItem, PurchaseDetailState, PurchaseDetailActions, PurchaseDetailTrack, KeybindingRow, KeybindingCategoryGroup, KeybindingsState, KeybindingsActions, KeyboardShortcutsState, LinkResolverState, LinkResolverActions, UiFocusState, UiScale, SleepTimerState, SleepTimerActions, LogRow, LogViewerState, DiagRow, DiagnosticsState, ReportIssueState, ReportIssueActions, AboutState, AboutActions, AboutContributorRow, AboutContributorGroup, WhatsNewState, WhatsNewActions, WhatsNewBlock, WhatsNewTocEntry } from "state.slint";
export { HomeState, HomeActions, RecentAlbumsState, DiscoverState, DiscoverActions, SectionDescriptor, ConfigRow, DiscoverBrowseState, DiscoverBrowseActions, ForYouState, ExternalRecoState, ExternalRecoActions, MixState, GenreFilterState, GenreFilterActions, AlbumState, ArtistState, NavState, ShellState, SessionState, SettingsState, AlbumActions, ArtistActions, ArtworkActions, NowPlayingState, QueueState, LyricsState, LyricsLineItem, SearchState, SearchActions, NetworkSidebarState, NetworkSidebarActions, MusicianState, MusicianActions, LabelState, LabelActions, AwardState, AwardActions, AwardEntry, ArtistReleasesState, ArtistReleasesActions, LocationViewState, LocationViewActions, FavoritesState, FavoritesActions, PlaylistPickerState, PlaylistPickerActions, DuplicateConfirmState, DuplicateConfirmActions, PlaylistState, PlaylistActions, SidebarState, SidebarActions, SidebarFolderPopupState, CreatePlaylistState, CreatePlaylistActions, EditPlaylistState, EditPlaylistActions, CreateFolderState, CreateFolderActions, SettingsExportState, SettingsExportActions, MyQbzCreateState, MyQbzCreateActions, DragState, DragActions, PlaylistManagerState, PlaylistManagerActions, OfflineManagerState, OfflineManagerActions, BlacklistState, BlacklistActions, BlacklistedArtistItem, MyQbzState, MyQbzActions, MixtapeCardItem, MyQbzAddState, MyQbzAddActions, MyQbzAddRow, MyQbzDetailState, MyQbzDetailActions, MixtapeDetailItem, MyQbzEditState, MyQbzEditActions, MyQbzMixState, MyQbzMixActions, DiscoBuilderState, DiscoBuilderActions, DiscoGroup, DiscoCandidate, LocalLibraryState, LocalLibraryActions, LibraryFoldersState, LibFolderEditState, LibraryManageActions, LibraryScanState, LibAlbumFilterState, LocalAlbumState, LocalAlbumActions, TagEditorState, TagEditorActions, FolderEditState, FolderEditActions, ToastState, TextUtil, QconnectDevState, QconnectDevice, CastState, CastDevice, CastActions, AppearanceState, MyQbzBrandingState, EphemeralPlayChoiceState, EphemeralPlayChoiceActions, PlexSettingsState, PlexAuthActions, PlexSectionItem, ScrobbleState, ScrobbleActions, DiscordState, OfflineState, LoginState, OfflineModeActions, OfflineFavoritesState, OfflineFavoritesActions, ImportLogEntry, PlaylistImportState, PlaylistImportActions, DacWizardState, DacWizardActions, DacCandidateRow, RemediationRow, DacConfigRow, InfoCreditRow, InfoCreditPair, AlbumCreditPerformer, AlbumCreditTrack, TrackInfoState, TrackInfoActions, AlbumInfoState, AlbumInfoActions, BookletState, BookletActions, SuggestionsState, SuggestionsActions, SuggestionCard, PlaylistSuggestionsState, PlaylistSuggestionsActions, PlaylistSuggestionRow, VisualizerState, ImmersiveState, ImmersiveSearchActions, ImmersiveActions, MiniPlayerState, WindowControlActions, PurchasesState, PurchasesActions, PurchaseAlbumItem, PurchaseTrackItem, PurchaseAlbumGroup, PurchaseTrackGroup, PurchaseFormatItem, PurchaseDetailState, PurchaseDetailActions, PurchaseDetailTrack, KeybindingRow, KeybindingCategoryGroup, KeybindingsState, KeybindingsActions, KeyboardShortcutsState, LinkResolverState, LinkResolverActions, UiFocusState, UiScale, SleepTimerState, SleepTimerActions, LogRow, LogViewerState, DiagRow, DiagnosticsState, ReportIssueState, ReportIssueActions, AboutState, AboutActions, AboutContributorRow, AboutContributorGroup, WhatsNewState, WhatsNewActions, WhatsNewBlock, WhatsNewTocEntry } from "state.slint";
// Which top-level screen is shown. The app starts on `splash` while it
// restores a saved session, then resolves to `shell` or `login`.
@@ -6,7 +6,7 @@
import { Theme } from "../foundation/semantic-colors.slint";
import { Typography } from "../foundation/typography.slint";
import { Radius } from "../foundation/radius.slint";
import { QconnectDevState, LogViewerState } from "../state.slint";
import { QconnectDevState, LogViewerState, SettingsExportState } from "../state.slint";
import { SettingRow } from "SettingRow.slint";
import { DiagnosticsPanel } from "DiagnosticsPanel.slint";
@@ -74,5 +74,20 @@ export component DeveloperSettings inherits VerticalLayout {
}
}
GroupHeader { text: @tr("SETTINGS PORTABILITY"); }
SettingRow {
label: @tr("Export settings…");
description: @tr("Save a portable bundle of your settings to move to another machine or the qbzd daemon.");
SecondaryButton {
label: @tr("Export…");
clicked => {
// Always reset the auth gate so it opens default-OFF (04 §4.2).
SettingsExportState.include-auth = false;
SettingsExportState.open = true;
}
}
}
DiagnosticsPanel { }
}
@@ -0,0 +1,192 @@
// "Export settings" modal (Settings > Developer > Export settings…, 04
// §4.2). Saves a portable settings bundle via the shared
// `qbz_app::settings::bundle` engine — the modal adds UI only.
//
// One checkbox, default OFF, is the single `--include-auth` gate (one
// checkbox, not two, to stay 1:1 with the CLI). Its warning line sits
// under it, indented to the label's edge. Confirm() is wired in Rust
// (crate::settings::export_settings): it reads `include-auth`, closes the
// modal, opens a native save dialog seeded with
// `qbz-settings-YYYYMMDD.qbzb`, writes the bundle 0600, and toasts the
// import command.
//
// Chrome follows the alignment standard: Radius.md surface-card panel,
// heading + close-X, checkbox row (18px box + 10px + label), footer
// alignment:end with Cancel before the accent primary. No pills
// (ADR-008); z via declaration order in AppShell (ADR-009/010).
import { Theme } from "../foundation/semantic-colors.slint";
import { Typography } from "../foundation/typography.slint";
import { Radius } from "../foundation/radius.slint";
import { SettingsExportState, SettingsExportActions } from "../state.slint";
import { QbzIcon } from "../primitives/QbzIcon.slint";
export component SettingsExportModal inherits Rectangle {
visible: SettingsExportState.open;
if SettingsExportState.open: Rectangle {
background: #000000bf;
TouchArea {
mouse-cursor: default;
clicked => {
SettingsExportState.open = false;
}
}
Rectangle {
width: Math.min(root.width - 80px, 420px);
height: panel.preferred-height;
x: Math.round((parent.width - self.width) / 2 / 1px) * 1px;
y: Math.round((parent.height - self.height) / 2 / 1px) * 1px;
border-radius: Radius.md;
background: Theme.surface-card;
border-width: 1px;
border-color: Theme.border-subtle;
drop-shadow-blur: 32px;
drop-shadow-color: #00000080;
TouchArea { }
panel := VerticalLayout {
padding: 20px;
spacing: 16px;
// Header: title + close X.
HorizontalLayout {
Text {
text: @tr("Export settings");
color: Theme.text-primary;
font-size: Typography.heading;
font-weight: Typography.semibold;
horizontal-stretch: 1;
vertical-alignment: center;
}
close-x := TouchArea {
width: 28px;
height: 28px;
mouse-cursor: pointer;
clicked => {
SettingsExportState.open = false;
}
QbzIcon {
source: @image-url("../assets/icons/x.svg");
width: 17px;
height: 17px;
x: Math.round((parent.width - self.width) / 2 / 1px) * 1px;
y: Math.round((parent.height - self.height) / 2 / 1px) * 1px;
tint: close-x.has-hover ? Theme.text-primary : Theme.text-muted;
}
}
}
// What the export produces.
Text {
text: @tr("Save your settings as a bundle to import on the qbzd daemon or another machine.");
color: Theme.text-muted;
font-size: Typography.legal;
wrap: word-wrap;
}
// Include-auth checkbox (default OFF) — the single
// --include-auth gate, with its warning line indented to the
// label's left edge.
VerticalLayout {
spacing: 6px;
HorizontalLayout {
spacing: 10px;
auth-toggle := TouchArea {
width: 20px;
height: 20px;
mouse-cursor: pointer;
clicked => {
SettingsExportState.include-auth = !SettingsExportState.include-auth;
}
Rectangle {
width: 18px;
height: 18px;
y: Math.round((parent.height - self.height) / 2 / 1px) * 1px;
border-radius: 4px;
background: SettingsExportState.include-auth ? Theme.accent : transparent;
border-width: SettingsExportState.include-auth ? 0px : 1.5px;
border-color: Theme.text-muted;
QbzIcon {
source: @image-url("../assets/icons/check.svg");
width: 12px;
height: 12px;
x: Math.round((parent.width - self.width) / 2 / 1px) * 1px;
y: Math.round((parent.height - self.height) / 2 / 1px) * 1px;
tint: #ffffff;
visible: SettingsExportState.include-auth;
}
}
}
Text {
text: @tr("Include Qobuz login and integration tokens");
color: Theme.text-secondary;
font-size: Typography.body;
vertical-alignment: center;
horizontal-stretch: 1;
wrap: word-wrap;
}
}
// Warning line — indented to the label's left edge (20px
// box + 10px spacing = 30px).
HorizontalLayout {
padding-left: 30px;
Text {
text: @tr("Anyone with the file can use your accounts. It is saved readable only by you; delete it after importing.");
color: Theme.text-muted;
font-size: Typography.legal;
wrap: word-wrap;
}
}
}
// Footer: Cancel before the accent Export primary.
HorizontalLayout {
alignment: end;
spacing: 10px;
// Cancel.
Rectangle {
width: cancel-label.preferred-width + 28px;
height: 36px;
border-radius: Radius.sm;
background: cancel-ta.has-hover ? Theme.surface-hover : Theme.surface-elevated;
cancel-label := Text {
text: @tr("Cancel");
color: Theme.text-primary;
font-size: Typography.body;
x: Math.round((parent.width - self.width) / 2 / 1px) * 1px;
y: Math.round((parent.height - self.height) / 2 / 1px) * 1px;
}
cancel-ta := TouchArea {
mouse-cursor: pointer;
clicked => {
SettingsExportState.open = false;
}
}
}
// Export (opens the native save dialog via Rust).
Rectangle {
width: export-label.preferred-width + 36px;
height: 36px;
border-radius: Radius.sm;
background: export-ta.has-hover ? #ffffffd6 : Theme.accent;
export-label := Text {
text: @tr("Export");
color: #ffffff;
font-size: Typography.body;
font-weight: Typography.semibold;
x: Math.round((parent.width - self.width) / 2 / 1px) * 1px;
y: Math.round((parent.height - self.height) / 2 / 1px) * 1px;
}
export-ta := TouchArea {
mouse-cursor: pointer;
clicked => {
SettingsExportActions.confirm();
}
}
}
}
}
}
}
}
+8
View File
@@ -30,6 +30,7 @@ import { AddToMixtapeModal } from "../myqbz/AddToMixtapeModal.slint";
import { EphemeralPlayChoiceModal } from "../primitives/EphemeralPlayChoiceModal.slint";
import { FolderEditModal } from "../primitives/FolderEditModal.slint";
import { LibFolderEditModal } from "../settings/LibFolderEditModal.slint";
import { SettingsExportModal } from "../settings/SettingsExportModal.slint";
import { TagEditorModal } from "../primitives/TagEditorModal.slint";
import { PlaylistImportModal } from "../primitives/PlaylistImportModal.slint";
import { DacWizardModal } from "../primitives/DacWizardModal.slint";
@@ -719,6 +720,13 @@ export component AppShell inherits Rectangle {
height: 100%;
}
// "Export settings" modal (Developer settings, 04 §4.2). Self-gated on
// SettingsExportState.open; declaration-order z keeps it above the page.
SettingsExportModal {
width: 100%;
height: 100%;
}
// Report-an-issue modal (header hamburger). Mounted after the log viewer so
// "Go to logs" stacks the viewer on top. Self-gated on ReportIssueState.open.
ReportIssueModal {
+15
View File
@@ -1858,6 +1858,21 @@ export global CreateFolderActions {
callback close();
}
// "Export settings" modal state (Settings > Developer, 04 §4.2). Opened from
// the Export settings… row, which resets `include-auth` to false first so the
// single --include-auth gate is always default-OFF. confirm() is wired in
// Rust (crate::settings::export_settings): build the bundle via the shared
// engine, open a native save dialog, write it 0600, and toast the import
// command. Cancel / backdrop / close-X set `open = false` directly.
export global SettingsExportState {
in-out property <bool> open: false;
in-out property <bool> include-auth: false;
}
export global SettingsExportActions {
callback confirm();
}
// "Create Mixtape / Collection" modal state (My QBZ). Opened from either
// grid's "+ New" CTA / empty-state button. `kind` is preset by the opening
// grid ("mixtape" | "collection") and can be flipped via the radio toggle