diff --git a/qt/aqt/data/web/pages/BUILD.bazel b/qt/aqt/data/web/pages/BUILD.bazel
index ff6090782..699a0a46a 100644
--- a/qt/aqt/data/web/pages/BUILD.bazel
+++ b/qt/aqt/data/web/pages/BUILD.bazel
@@ -6,6 +6,7 @@ _pages = [
"deck-options",
"change-notetype",
"card-info",
+ "fields",
]
[copy_files_into_group(
diff --git a/qt/aqt/fields.py b/qt/aqt/fields.py
index 7c4733ebb..46b9e3488 100644
--- a/qt/aqt/fields.py
+++ b/qt/aqt/fields.py
@@ -1,6 +1,9 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
+from __future__ import annotations
+
+import os
from typing import Optional
import aqt
@@ -41,11 +44,28 @@ class FieldDialog(QDialog):
self.model = nt
self.mm._remove_from_cache(self.model["id"])
self.change_tracker = ChangeTracker(self.mw)
- self.form = aqt.forms.fields.Ui_Dialog()
- self.form.setupUi(self)
+
self.setWindowTitle(
without_unicode_isolation(tr.fields_fields_for(val=self.model["name"]))
)
+
+ if os.getenv("ANKI_EXPERIMENTAL_FIELDS_WEB"):
+ form = aqt.forms.fields_web.Ui_Dialog()
+ form.setupUi(self)
+
+ self.webview = form.webview
+ self.webview.set_title("fields")
+
+ self.show()
+ self.refresh()
+ self.webview.set_bridge_command(self._on_bridge_cmd, self)
+ self.activateWindow()
+ return
+
+ self.form = aqt.forms.fields.Ui_Dialog()
+ self.form.setupUi(self)
+ self.webview = None
+
disable_help_button(self)
self.form.buttonBox.button(QDialogButtonBox.StandardButton.Help).setAutoDefault(
False
@@ -64,6 +84,12 @@ class FieldDialog(QDialog):
self.form.fieldList.setCurrentRow(open_at)
self.exec()
+ def refresh(self) -> None:
+ self.webview.load_ts_page("fields")
+
+ def _on_bridge_cmd(self, cmd: str) -> bool:
+ return False
+
##########################################################################
def fillFields(self) -> None:
@@ -243,6 +269,10 @@ class FieldDialog(QDialog):
self.change_tracker.mark_basic()
def reject(self) -> None:
+ if self.webview:
+ self.webview.cleanup()
+ self.webview = None
+
if self.change_tracker.changed():
if not askUser("Discard changes?"):
return
diff --git a/qt/aqt/forms/__init__.py b/qt/aqt/forms/__init__.py
index 008cd902b..dd1433a83 100644
--- a/qt/aqt/forms/__init__.py
+++ b/qt/aqt/forms/__init__.py
@@ -20,6 +20,7 @@ from . import edithtml
from . import emptycards
from . import exporting
from . import fields
+from . import fields_web
from . import finddupes
from . import findreplace
from . import getaddons
diff --git a/qt/aqt/forms/fields_web.py b/qt/aqt/forms/fields_web.py
new file mode 100644
index 000000000..e3af4c85e
--- /dev/null
+++ b/qt/aqt/forms/fields_web.py
@@ -0,0 +1,5 @@
+from aqt.qt import qtmajor
+if qtmajor > 5:
+ from .fields_web_qt6 import *
+else:
+ from .fields_web_qt5 import * # type: ignore
diff --git a/qt/aqt/forms/fields_web.ui b/qt/aqt/forms/fields_web.ui
new file mode 100644
index 000000000..d00f8b186
--- /dev/null
+++ b/qt/aqt/forms/fields_web.ui
@@ -0,0 +1,49 @@
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Dialog
+
+
+
+ :/icons/anki.png:/icons/anki.png
+
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ about:blank
+
+
+
+
+
+
+
+
+ AnkiWebView
+ QWidget
+
+ 1
+
+
+
+
+
+
diff --git a/qt/aqt/forms/fields_web_qt6.py b/qt/aqt/forms/fields_web_qt6.py
new file mode 120000
index 000000000..33b70f31d
--- /dev/null
+++ b/qt/aqt/forms/fields_web_qt6.py
@@ -0,0 +1 @@
+../../../.bazel/bin/qt/aqt/forms/fields_web_qt6.py
\ No newline at end of file
diff --git a/ts/fields/BUILD.bazel b/ts/fields/BUILD.bazel
new file mode 100644
index 000000000..4724e3d29
--- /dev/null
+++ b/ts/fields/BUILD.bazel
@@ -0,0 +1,73 @@
+load("//ts:prettier.bzl", "prettier_test")
+load("//ts:eslint.bzl", "eslint_test")
+load("//ts/svelte:svelte.bzl", "compile_svelte", "svelte_check")
+load("//ts:esbuild.bzl", "esbuild")
+load("//ts:generate_page.bzl", "generate_page")
+load("//ts:compile_sass.bzl", "compile_sass")
+load("//ts:typescript.bzl", "typescript")
+
+generate_page(page = "fields")
+
+compile_sass(
+ srcs = ["fields-base.scss"],
+ group = "base_css",
+ visibility = ["//visibility:public"],
+ deps = [
+ "//sass:base_lib",
+ "//sass:scrollbar_lib",
+ "//sass/bootstrap",
+ ],
+)
+
+_ts_deps = [
+ "//ts/components",
+ "//ts/lib",
+ "//ts/sveltelib",
+ "@npm//svelte",
+]
+
+compile_svelte(deps = _ts_deps)
+
+typescript(
+ name = "index",
+ deps = _ts_deps + [
+ ":svelte",
+ ],
+)
+
+esbuild(
+ name = "fields",
+ args = {
+ "loader": {".svg": "text"},
+ },
+ entry_point = "index.ts",
+ output_css = "fields.css",
+ visibility = ["//visibility:public"],
+ deps = [
+ ":base_css",
+ ":index",
+ ":svelte",
+ ],
+)
+
+# Tests
+################
+
+prettier_test()
+
+eslint_test()
+
+svelte_check(
+ name = "svelte_check",
+ srcs = glob([
+ "*.ts",
+ "*.svelte",
+ ]) + [
+ "//sass:button_mixins_lib",
+ "//sass/bootstrap",
+ "@npm//@types/bootstrap",
+ "@npm//@types/lodash-es",
+ "@npm//@types/marked",
+ "//ts/components",
+ ],
+)
diff --git a/ts/fields/FieldsPage.svelte b/ts/fields/FieldsPage.svelte
new file mode 100644
index 000000000..68c814dac
--- /dev/null
+++ b/ts/fields/FieldsPage.svelte
@@ -0,0 +1,8 @@
+
+
+
+
Fields
diff --git a/ts/fields/fields-base.scss b/ts/fields/fields-base.scss
new file mode 100644
index 000000000..a03b67bf1
--- /dev/null
+++ b/ts/fields/fields-base.scss
@@ -0,0 +1,29 @@
+@use "sass/vars";
+@use "sass/bootstrap-dark";
+
+@import "sass/base";
+
+@import "sass/bootstrap/scss/alert";
+@import "sass/bootstrap/scss/buttons";
+@import "sass/bootstrap/scss/button-group";
+@import "sass/bootstrap/scss/close";
+@import "sass/bootstrap/scss/grid";
+@import "sass/bootstrap-forms";
+
+.night-mode {
+ @include bootstrap-dark.night-mode;
+}
+
+body {
+ width: min(100vw, 70em);
+ margin: 0 auto;
+}
+
+html {
+ overflow-x: hidden;
+}
+
+#main {
+ padding: 0.5em 0.5em 1em 0.5em;
+ height: 100vh;
+}
diff --git a/ts/fields/index.ts b/ts/fields/index.ts
new file mode 100644
index 000000000..b98a24b58
--- /dev/null
+++ b/ts/fields/index.ts
@@ -0,0 +1,23 @@
+// Copyright: Ankitects Pty Ltd and contributors
+// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
+
+import "./fields-base.css";
+
+import { ModuleName, setupI18n } from "../lib/i18n";
+import { checkNightMode } from "../lib/nightmode";
+import FieldsPage from "./FieldsPage.svelte";
+
+const i18n = setupI18n({
+ modules: [ModuleName.ACTIONS, ModuleName.CHANGE_NOTETYPE, ModuleName.KEYBOARD],
+});
+
+export async function setupFieldsPage(): Promise {
+ checkNightMode();
+
+ await i18n;
+ return new FieldsPage({
+ target: document.body,
+ });
+}
+
+setupFieldsPage();
diff --git a/ts/fields/tsconfig.json b/ts/fields/tsconfig.json
new file mode 100644
index 000000000..b8ee6e3a4
--- /dev/null
+++ b/ts/fields/tsconfig.json
@@ -0,0 +1,10 @@
+{
+ "extends": "../tsconfig.json",
+ "include": ["*"],
+ "references": [
+ { "path": "../lib" },
+ { "path": "../sveltelib" },
+ { "path": "../components" }
+ ],
+ "compilerOptions": {}
+}