diff --git a/proto/anki/frontend.proto b/proto/anki/frontend.proto index 5385da051..1f3e7b6b3 100644 --- a/proto/anki/frontend.proto +++ b/proto/anki/frontend.proto @@ -31,6 +31,10 @@ service FrontendService { // Editor rpc editorUpdateNote(notes.UpdateNotesRequest) returns (generic.Empty); + + // Profile config + rpc GetProfileConfigJson(generic.String) returns (generic.Json); + rpc SetProfileConfigJson(SetProfileConfigJsonRequest) returns (generic.Empty); } service BackendFrontendService {} @@ -44,3 +48,8 @@ message SetSchedulingStatesRequest { string key = 1; scheduler.SchedulingStates states = 2; } + +message SetProfileConfigJsonRequest { + string key = 1; + bytes value_json = 2; +} diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index b3b647a8b..b35d11a90 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -457,16 +457,6 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too return new_state - elif cmd.startswith("lastTextColor"): - (_, textColor) = cmd.split(":", 1) - assert self.mw.pm.profile is not None - self.mw.pm.profile["lastTextColor"] = textColor - - elif cmd.startswith("lastHighlightColor"): - (_, highlightColor) = cmd.split(":", 1) - assert self.mw.pm.profile is not None - self.mw.pm.profile["lastHighlightColor"] = highlightColor - elif cmd.startswith("saveTags"): gui_hooks.editor_did_update_tags(self.note) diff --git a/qt/aqt/mediasrv.py b/qt/aqt/mediasrv.py index d507dfdd5..636d88545 100644 --- a/qt/aqt/mediasrv.py +++ b/qt/aqt/mediasrv.py @@ -4,6 +4,7 @@ from __future__ import annotations import enum +import json import logging import mimetypes import os @@ -28,7 +29,7 @@ from waitress.server import create_server import aqt import aqt.main import aqt.operations -from anki import hooks +from anki import frontend_pb2, generic_pb2, hooks from anki.collection import OpChanges, OpChangesOnly, Progress, SearchNode from anki.decks import UpdateDeckConfigs from anki.scheduler.v3 import SchedulingStatesWithContext, SetSchedulingStatesRequest @@ -621,6 +622,23 @@ def editor_update_note() -> bytes: return output +def get_profile_config_json() -> bytes: + key = generic_pb2.String() + key.ParseFromString(request.data) + value = aqt.mw.pm.profile.get(key.val, None) + output = generic_pb2.Json(json=json.dumps(value).encode()).SerializeToString() + + return output + + +def set_profile_config_json() -> bytes: + req = frontend_pb2.SetProfileConfigJsonRequest() + req.ParseFromString(request.data) + aqt.mw.pm.profile[req.key] = json.loads(req.value_json) + + return b"" + + post_handler_list = [ congrats_info, get_deck_configs_for_update, @@ -637,6 +655,8 @@ post_handler_list = [ deck_options_require_close, deck_options_ready, editor_update_note, + get_profile_config_json, + set_profile_config_json, ] diff --git a/ts/lib/tslib/profile.ts b/ts/lib/tslib/profile.ts new file mode 100644 index 000000000..3ec10eff7 --- /dev/null +++ b/ts/lib/tslib/profile.ts @@ -0,0 +1,16 @@ +// Copyright: Ankitects Pty Ltd and contributors +// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +import { getProfileConfigJson, setProfileConfigJson } from "@generated/backend"; + +export async function getProfileConfig(key: string): Promise { + const decoder = new TextDecoder(); + const json = decoder.decode((await getProfileConfigJson({ val: key })).json); + return JSON.parse(json); +} + +export async function setProfileConfig(key: string, value: any): Promise { + const encoder = new TextEncoder(); + const json = JSON.stringify(value); + await setProfileConfigJson({ key: key, valueJson: encoder.encode(json) }); +} diff --git a/ts/routes/editor/NoteEditor.svelte b/ts/routes/editor/NoteEditor.svelte index 4d937f824..4e2159d5e 100644 --- a/ts/routes/editor/NoteEditor.svelte +++ b/ts/routes/editor/NoteEditor.svelte @@ -446,7 +446,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html decodeIriPaths, } from "@generated/backend"; import { wrapInternal } from "@tslib/wrap"; - + import { getProfileConfig } from "@tslib/profile"; import Shortcut from "$lib/components/Shortcut.svelte"; import { mathjaxConfig } from "$lib/editable/mathjax-element.svelte"; @@ -465,6 +465,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import ButtonGroupItem from "$lib/components/ButtonGroupItem.svelte"; import PreviewButton from "./PreviewButton.svelte"; import type { Note } from "@generated/anki/notes_pb"; + import InlineButtons from "./editor-toolbar/InlineButtons.svelte"; $: isIOImageLoaded = false; $: ioImageLoadedStore.set(isIOImageLoaded); @@ -613,6 +614,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html ) ).map((field) => field.val); const tags = note!.tags; + const lastTextColor = (await getProfileConfig("lastTextColor")) ?? "#0000ff"; + const lastHighlightColor = + (await getProfileConfig("lastHighlightColor")) ?? "#0000ff"; saveSession(); setFields(fieldNames, fieldValues); @@ -635,8 +639,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html ]), ); focusField(focusTo); - // TODO: lastTextColor/lastHighlightColor profile config - // setColorButtons(["#0000ff", "#0000ff"]); + toolbar.inlineButtons?.setColorButtons([lastTextColor, lastHighlightColor]); setTags(tags); // TODO: mw.pm.tags_collapsed() setTagsCollapsed(false); diff --git a/ts/routes/editor/editor-toolbar/EditorToolbar.svelte b/ts/routes/editor/editor-toolbar/EditorToolbar.svelte index 9266792b9..1ea545f8f 100644 --- a/ts/routes/editor/editor-toolbar/EditorToolbar.svelte +++ b/ts/routes/editor/editor-toolbar/EditorToolbar.svelte @@ -26,7 +26,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html export interface EditorToolbarAPI { toolbar: DefaultSlotInterface; notetypeButtons: DefaultSlotInterface; - inlineButtons: DefaultSlotInterface; + inlineButtons: InlineButtonsAPI; blockButtons: DefaultSlotInterface; templateButtons: DefaultSlotInterface; removeFormats: Writable; @@ -62,14 +62,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import OptionsButtons from "./OptionsButtons.svelte"; import RichTextClozeButtons from "./RichTextClozeButtons.svelte"; import TemplateButtons from "./TemplateButtons.svelte"; - + import type { InlineButtonsAPI } from "./InlineButtons.svelte"; export let size: number; export let wrap: boolean; const toolbar = {} as DefaultSlotInterface; const notetypeButtons = {} as DefaultSlotInterface; const optionsButtons = {} as DefaultSlotInterface; - const inlineButtons = {} as DefaultSlotInterface; + const inlineButtons = {} as InlineButtonsAPI; const blockButtons = {} as DefaultSlotInterface; const templateButtons = {} as DefaultSlotInterface; const removeFormats = writable([]); diff --git a/ts/routes/editor/editor-toolbar/HighlightColorButton.svelte b/ts/routes/editor/editor-toolbar/HighlightColorButton.svelte index 865ec5668..707f76872 100644 --- a/ts/routes/editor/editor-toolbar/HighlightColorButton.svelte +++ b/ts/routes/editor/editor-toolbar/HighlightColorButton.svelte @@ -4,7 +4,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> + diff --git a/ts/routes/editor/editor-toolbar/TextColorButton.svelte b/ts/routes/editor/editor-toolbar/TextColorButton.svelte index 165953180..ba27ddb27 100644 --- a/ts/routes/editor/editor-toolbar/TextColorButton.svelte +++ b/ts/routes/editor/editor-toolbar/TextColorButton.svelte @@ -4,7 +4,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -->