From 80cff16250fa1a578177399faf0da904188fce83 Mon Sep 17 00:00:00 2001 From: llama Date: Wed, 17 Sep 2025 14:46:53 +0800 Subject: [PATCH] fix: persist colour picker's custom palette in profile (#4326) * add SaveCustomColours rpc method * restore custom colour palette on editor init * save custom colour palette on colour picker open and input there doesn't seem to be an event fired when the picker is cancelled/closed, so it's still possible for work to be lost * save colours on `change` instead of `input` `input` is supposed to be fired on every adjustment to the picker whereas `change` is only fired when the picker is accepted, but qt seems to treat both as the latter, so this is currently a no-op * Store colors in the collection One minor tweak to the logic while I was there: an invalid color no longer invalidates all the rest. --------- Co-authored-by: Damien Elmes --- proto/anki/frontend.proto | 3 +++ qt/aqt/editor.py | 9 +++++++++ qt/aqt/mediasrv.py | 10 ++++++++++ ts/editor/editor-toolbar/ColorPicker.svelte | 11 ++++++++++- ts/editor/editor-toolbar/HighlightColorButton.svelte | 6 +++++- ts/editor/editor-toolbar/TextColorButton.svelte | 2 ++ 6 files changed, 39 insertions(+), 2 deletions(-) diff --git a/proto/anki/frontend.proto b/proto/anki/frontend.proto index 95b929c5c..1d733a369 100644 --- a/proto/anki/frontend.proto +++ b/proto/anki/frontend.proto @@ -27,6 +27,9 @@ service FrontendService { rpc deckOptionsRequireClose(generic.Empty) returns (generic.Empty); // Warns python that the deck option web view is ready to receive requests. rpc deckOptionsReady(generic.Empty) returns (generic.Empty); + + // Save colour picker's custom colour palette + rpc SaveCustomColours(generic.Empty) returns (generic.Empty); } service BackendFrontendService {} diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index f2f267097..e86f5fe96 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -151,6 +151,7 @@ class Editor: self.add_webview() self.setupWeb() self.setupShortcuts() + self.setupColourPalette() gui_hooks.editor_did_init(self) # Initial setup @@ -349,6 +350,14 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too keys, fn, _ = row QShortcut(QKeySequence(keys), self.widget, activated=fn) # type: ignore + def setupColourPalette(self) -> None: + if not (colors := self.mw.col.get_config("customColorPickerPalette")): + return + for i, colour in enumerate(colors[: QColorDialog.customCount()]): + if not QColor.isValidColorName(colour): + continue + QColorDialog.setCustomColor(i, QColor.fromString(colour)) + def _addFocusCheck(self, fn: Callable) -> Callable: def checkFocus() -> None: if self.currentField is None: diff --git a/qt/aqt/mediasrv.py b/qt/aqt/mediasrv.py index 820e762d9..3a05eec2c 100644 --- a/qt/aqt/mediasrv.py +++ b/qt/aqt/mediasrv.py @@ -599,6 +599,15 @@ def deck_options_ready() -> bytes: return b"" +def save_custom_colours() -> bytes: + colors = [ + QColorDialog.customColor(i).name(QColor.NameFormat.HexArgb) + for i in range(QColorDialog.customCount()) + ] + aqt.mw.col.set_config("customColorPickerPalette", colors) + return b"" + + post_handler_list = [ congrats_info, get_deck_configs_for_update, @@ -614,6 +623,7 @@ post_handler_list = [ search_in_browser, deck_options_require_close, deck_options_ready, + save_custom_colours, ] diff --git a/ts/editor/editor-toolbar/ColorPicker.svelte b/ts/editor/editor-toolbar/ColorPicker.svelte index 746b193a2..f5934441c 100644 --- a/ts/editor/editor-toolbar/ColorPicker.svelte +++ b/ts/editor/editor-toolbar/ColorPicker.svelte @@ -4,6 +4,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> - + saveCustomColours({})} +/> {#if keyCombination} inputRef.click()} /> diff --git a/ts/editor/editor-toolbar/HighlightColorButton.svelte b/ts/editor/editor-toolbar/HighlightColorButton.svelte index 865ec5668..f89f7a99a 100644 --- a/ts/editor/editor-toolbar/HighlightColorButton.svelte +++ b/ts/editor/editor-toolbar/HighlightColorButton.svelte @@ -19,6 +19,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import ColorPicker from "./ColorPicker.svelte"; import { context as editorToolbarContext } from "./EditorToolbar.svelte"; import WithColorHelper from "./WithColorHelper.svelte"; + import { saveCustomColours } from "@generated/backend"; export let color: string; @@ -134,7 +135,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html color = setColor(event); bridgeCommand(`lastHighlightColor:${color}`); }} - on:change={() => setTextColor()} + on:change={() => { + setTextColor(); + saveCustomColours({}); + }} /> diff --git a/ts/editor/editor-toolbar/TextColorButton.svelte b/ts/editor/editor-toolbar/TextColorButton.svelte index 165953180..ce80aae49 100644 --- a/ts/editor/editor-toolbar/TextColorButton.svelte +++ b/ts/editor/editor-toolbar/TextColorButton.svelte @@ -22,6 +22,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import ColorPicker from "./ColorPicker.svelte"; import { context as editorToolbarContext } from "./EditorToolbar.svelte"; import WithColorHelper from "./WithColorHelper.svelte"; + import { saveCustomColours } from "@generated/backend"; export let color: string; @@ -158,6 +159,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html setTimeout(() => { setTextColor(); }, 200); + saveCustomColours({}); }} />