summaryrefslogtreecommitdiff
path: root/.local/share/Anki2/addons21/anki_reworked
diff options
context:
space:
mode:
authorThanos Apollo <[email protected]>2022-08-04 09:50:48 +0300
committerThanos Apollo <[email protected]>2022-08-04 09:50:48 +0300
commit4ddb7273098bee179bb77e0937e560fc0100960c (patch)
treecebc2f9412e45910408a7885ca78d7dedb77de78 /.local/share/Anki2/addons21/anki_reworked
parente83759ae9d0513024e390810ddcb18ffdd84675e (diff)
Add anki addons
Diffstat (limited to '.local/share/Anki2/addons21/anki_reworked')
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/__init__.py705
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/config.json8
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/config.md9
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/config.py22
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/BottomBar.css40
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/CardLayout.css1
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/DeckBrowser.css48
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/Editor.css1
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/Overview.css59
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/QAbout.css0
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/QAddCards.css1
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/QAddonsDialog.css0
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/QBrowser.css0
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/QEditCurrent.css0
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/QFilteredDeckConfigDialog.css0
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/QNewDeckStats.css3
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/QPreferences.css0
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/Reviewer.css9
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/ReviewerBottomBar.css60
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/TopToolbar.css25
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/global.css96
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/files/legacy.css18
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/manifest.json10
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/meta.json1
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/themes/Anki.json230
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/themes/Catppuccin.json230
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/themes/Nord.json230
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/themes/readme.txt8
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/user_files/readme.txt11
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/utils/css_files.py37
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/utils/logger.py17
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/utils/modules.py18
-rw-r--r--.local/share/Anki2/addons21/anki_reworked/utils/themes.py34
33 files changed, 1931 insertions, 0 deletions
diff --git a/.local/share/Anki2/addons21/anki_reworked/__init__.py b/.local/share/Anki2/addons21/anki_reworked/__init__.py
new file mode 100644
index 0000000..81b2627
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/__init__.py
@@ -0,0 +1,705 @@
+import json
+### Custom util functions
+from .utils.modules import *
+### Logger for debuging
+from .utils.logger import logger
+
+from typing import Any, List, Optional
+from PyQt5.QtWidgets import QWidget
+from platform import system, version, release
+from ctypes import *
+# import the main window object (mw) from aqt
+from aqt import AnkiQt, DialogManager, mw
+from aqt.theme import theme_manager, colors
+from aqt import gui_hooks
+## QT dialog windows
+# Browser import legacy check (2.1.22)
+if module_exists("aqt.browser.browser"):
+ from aqt.browser.browser import Browser
+else:
+ from aqt.browser import Browser
+# DeckStats import legacy check
+if module_has_attribute("aqt.stats", "NewDeckStats"):
+ from aqt.stats import DeckStats, NewDeckStats
+else:
+ from aqt.stats import DeckStats
+from aqt.addcards import AddCards
+from aqt.editcurrent import EditCurrent
+from aqt.about import ClosableQDialog
+from aqt.preferences import Preferences
+from aqt.addons import AddonsDialog
+# FilteredDeckConfigDialog import non-legacy check
+if module_exists("aqt.filtered_deck"):
+ from aqt.filtered_deck import FilteredDeckConfigDialog
+# QT page views
+from aqt.toolbar import Toolbar, TopToolbar
+from aqt.deckbrowser import DeckBrowser, DeckBrowserBottomBar
+from aqt.overview import Overview, OverviewBottomBar
+from aqt.editor import Editor
+from aqt.reviewer import Reviewer, ReviewerBottomBar
+from aqt.webview import AnkiWebView, WebContent
+
+### Load config data here
+from .config import config, write_config, get_config
+
+## Addon compatibility fixes
+# More Overview Stats 2.1 addon compatibility fix
+addon_more_overview_stats_fix = config['addon_more_overview_stats']
+addon_advanced_review_bottom_bar = config['addon_advanced_review_bottom_bar']
+
+## Customization
+theme = config['theme']
+# Init script/file path
+from .utils.css_files import css_files_dir
+from .utils.themes import themes, write_theme, get_theme
+logger.debug(css_files_dir)
+logger.debug(themes)
+themes_parsed = get_theme(theme)
+color_mode = 2 if theme_manager.get_night_mode() else 1 # 1 = light and 2 = dark
+
+dwmapi = None
+## Darkmode windows titlebar thanks to miere43
+def set_dark_titlebar(window, dwmapi) -> None:
+ if dwmapi:
+ handler_window = c_void_p(int(window.winId()))
+ DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = c_int(19)
+ DWMWA_USE_IMMERSIVE_DARK_MODE = c_int(20)
+ windows_version = int(version().split('.')[2])
+ attribute = DWMWA_USE_IMMERSIVE_DARK_MODE if windows_version >= 18985 else DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1
+ if windows_version >= 17763 and int(release()) >= 10:
+ dwmapi.DwmSetWindowAttribute(handler_window, attribute, byref(c_int(1)), c_size_t(4))
+def set_dark_titlebar_qt(obj, dwmapi, fix=True) -> None:
+ if dwmapi and theme_manager.get_night_mode():
+ set_dark_titlebar(obj, dwmapi)
+ # Trick to refresh the titlebar after dark titlebar is set
+ if fix:
+ obj.showFullScreen()
+ obj.showNormal()
+if system() == "Windows" and theme_manager.get_night_mode():
+ dwmapi = WinDLL("dwmapi")
+ if dwmapi:
+ dwmapi.DwmSetWindowAttribute.argtypes = [c_void_p, c_int, c_void_p, c_size_t]
+ dwmapi.DwmSetWindowAttribute.restype = c_int
+ set_dark_titlebar(mw, dwmapi)
+logger.debug(dwmapi)
+
+### CSS injections
+def load_custom_style():
+ theme_colors = ""
+ for color_name in themes_parsed.get("colors"):
+ color = themes_parsed.get("colors").get(color_name)
+ if color[3]:
+ theme_colors += f"{color[3]}: {color[color_mode]};\n "
+ else:
+ theme_colors += f"--{color_name.lower().replace('_','-')}: {color[color_mode]};\n "
+ custom_style = """
+<style>
+ :root,
+ :root .isMac,
+ :root .isWin,
+ :root .isLin {
+ %s
+ }
+ html {
+ font-family: %s;
+ font-size: %spx;
+ }
+</style>
+ """ % (theme_colors, config["font"], config["font_size"])
+ return custom_style
+
+## Adds styling on the different webview contents, before the content is set
+def on_webview_will_set_content(web_content: WebContent, context: Optional[Any]) -> None:
+ logger.debug(context) # Logs content being loaded, find out the instance
+ web_content.css.append(css_files_dir['global']) # Global css
+ web_content.head += load_custom_style() # Custom styling
+ # Deckbrowser
+ if isinstance(context, DeckBrowser):
+ web_content.css.append(css_files_dir['DeckBrowser'])
+ # TopToolbar
+ elif isinstance(context, TopToolbar):
+ web_content.css.append(css_files_dir['TopToolbar'])
+ # BottomToolbar (Buttons)
+ elif isinstance(context, DeckBrowserBottomBar) or isinstance(context, OverviewBottomBar):
+ web_content.css.append(css_files_dir['BottomBar'])
+ # Overview
+ elif isinstance(context, Overview):
+ if addon_more_overview_stats_fix:
+ web_content.head += "<style>center > table tr:first-of-type {display: table-row; flex-direction: unset;}</style>"
+ web_content.css.append(css_files_dir['Overview'])
+ # Editor
+ elif isinstance(context, Editor):
+ web_content.css.append(css_files_dir['Editor'])
+ # Reviewer
+ elif isinstance(context, Reviewer):
+ web_content.css.append(css_files_dir['Reviewer'])
+ elif isinstance(context, ReviewerBottomBar):
+ if addon_advanced_review_bottom_bar:
+ #web_content.head += "<style>td.stat[align='left']:nth-of-type(2) {position: absolute; z-index: 1;}</style>"
+ web_content.body += "<script>const center = document.getElementById('outer');center.classList.add('arbb');</script>"
+ else:
+ web_content.css.append(css_files_dir['BottomBar'])
+ web_content.css.append(css_files_dir['ReviewerBottomBar'])
+ # Button padding bottom
+ web_content.body += "<div style='height: 9px; opacity: 0; pointer-events: none;'></div>"
+ web_content.body += "<div id='padFix' style='height: 30px; opacity: 0; pointer-events: none;'><script>const e = document.getElementById('padFix');e.parentElement.removeChild(e);</script></div>"
+ mw.bottomWeb.adjustHeightToFit()
+ # CardLayout
+ elif context_name_includes(context, "aqt.clayout.CardLayout"):
+ web_content.css.append(css_files_dir['CardLayout'])
+ ## Legacy webviews
+ # ResetRequired on card edit (legacy)
+ elif context_name_includes(context, "aqt.main.ResetRequired"):
+ web_content.css.append(css_files_dir['legacy'])
+gui_hooks.webview_will_set_content.append(on_webview_will_set_content)
+
+# TopToolbar styling fix through height change by adding <br> tag
+def redraw_toolbar() -> None:
+ # Reload the webview content with added <br/> tag, making the bar larger in height
+ mw.toolbar.web.setFixedHeight(60)
+ mw.toolbar.web.eval("""
+ var br = document.createElement("br");
+ document.body.appendChild(br);
+ """)
+
+ if 'Qt6' in QPalette.ColorRole.__module__:
+ mw.toolbar.web.eval("""
+ var div = document.createElement("div");
+ div.style.width = "5px";
+ div.style.height = "10px";
+ document.body.appendChild(div);
+ """)
+ # Auto adjust the height, then redraw the toolbar
+ mw.toolbar.web.adjustHeightToFit()
+ mw.toolbar.redraw()
+
+def redraw_toolbar_legacy(links: List[str], _: Toolbar) -> None:
+ # Utilizing the link hook, we inject <br/> tag through javascript
+ inject_br = """
+ <script>
+ while (document.body.querySelectorAll("br").length > 1)
+ document.body.querySelectorAll("br")[0].remove();
+ var br = document.createElement("br");
+ document.body.appendChild(br);
+ </script>
+ """
+ mw.toolbar.web.setFixedHeight(60)
+ links.append(inject_br)
+ mw.toolbar.web.adjustHeightToFit()
+
+if attribute_exists(gui_hooks, "main_window_did_init"):
+ pass
+ #gui_hooks.main_window_did_init.append(redraw_toolbar)
+elif attribute_exists(gui_hooks, "top_toolbar_did_init_links"):
+ gui_hooks.top_toolbar_did_init_links.append(redraw_toolbar_legacy)
+ pass
+
+# Dialog window styling
+def on_dialog_manager_did_open_dialog(dialog_manager: DialogManager, dialog_name: str, dialog_instance: QWidget) -> None:
+ logger.debug(dialog_name)
+ dialog: AnkiQt = dialog_manager._dialogs[dialog_name][1]
+ # If dwmapi found and nightmode is enabled, set dark titlebar to dialog window
+ set_dark_titlebar_qt(dialog, dwmapi)
+ # AddCards
+ if dialog_name == "AddCards":
+ context: AddCards = dialog_manager._dialogs[dialog_name][1]
+ context.setStyleSheet(open(css_files_dir['QAddCards'], encoding='utf-8').read())
+ # Addons popup
+ elif dialog_name == "AddonsDialog":
+ context: AddonsDialog = dialog_manager._dialogs[dialog_name][1]
+ context.setStyleSheet(open(css_files_dir['QAddonsDialog'], encoding='utf-8').read())
+ # Browser
+ elif dialog_name == "Browser":
+ context: Browser = dialog_manager._dialogs[dialog_name][1]
+ context.setStyleSheet(open(css_files_dir['QBrowser'], encoding='utf-8').read())
+ pass
+ # EditCurrent
+ elif dialog_name == "EditCurrent":
+ context: EditCurrent = dialog_manager._dialogs[dialog_name][1]
+ context.setStyleSheet(open(css_files_dir['QEditCurrent'], encoding='utf-8').read())
+ # FilteredDeckConfigDialog
+ elif module_exists("aqt.filtered_deck") and dialog_name == "FilteredDeckConfigDialog":
+ context: FilteredDeckConfigDialog = dialog_manager._dialogs[dialog_name][1]
+ context.setStyleSheet(open(css_files_dir['QFilteredDeckConfigDialog'], encoding='utf-8').read())
+ # Statistics / NewDeckStats
+ elif dialog_name == "NewDeckStats":
+ context: NewDeckStats = dialog_manager._dialogs[dialog_name][1]
+ context.setStyleSheet(open(css_files_dir['QNewDeckStats'], encoding='utf-8').read())
+ # About
+ elif dialog_name == "About":
+ context: ClosableQDialog = dialog_manager._dialogs[dialog_name][1]
+ context.setStyleSheet(open(css_files_dir['QAbout'], encoding='utf-8').read())
+ # Preferences
+ elif dialog_name == "Preferences":
+ context: Preferences = dialog_manager._dialogs[dialog_name][1]
+ context.setStyleSheet(open(css_files_dir['QPreferences'], encoding='utf-8').read())
+ # sync_log - kore ha nani desu???
+ elif dialog_name == "sync_log":
+ pass
+
+if attribute_exists(gui_hooks, "dialog_manager_did_open_dialog"):
+ gui_hooks.dialog_manager_did_open_dialog.append(on_dialog_manager_did_open_dialog)
+else:
+ ## Legacy dialog window styling
+ # Sad monkey patch, instead of hooks :c
+ # setupDialogGC is being called on almost all dialog windows, utilizing this, the
+ # function is used as a type of hook to inject CSS styling on the QT instances
+ def monkey_setup_dialog_gc(obj: Any) -> None:
+ obj.finished.connect(lambda: mw.gcWindow(obj))
+ logger.debug(obj)
+ set_dark_titlebar_qt(obj, dwmapi)
+ # AddCards
+ if isinstance(obj, AddCards):
+ obj.setStyleSheet(open(css_files_dir['QAddCards'], encoding='utf-8').read())
+ # EditCurrent
+ elif isinstance(obj, EditCurrent):
+ obj.setStyleSheet(open(css_files_dir['QEditCurrent'], encoding='utf-8').read())
+ # Statistics / DeckStats
+ elif isinstance(obj, DeckStats):
+ obj.setStyleSheet(open(css_files_dir['QNewDeckStats'], encoding='utf-8').read())
+ # About
+ elif isinstance(obj, ClosableQDialog):
+ obj.setStyleSheet(open(css_files_dir['QAbout'], encoding='utf-8').read())
+ # Preferences
+ ## Haven't found a solution for preferences yet :c
+ mw.setupDialogGC = monkey_setup_dialog_gc # Should be rare enough for other addons to also patch this I hope.
+
+ # Addons popup
+ if attribute_exists(gui_hooks, "addons_dialog_will_show"):
+ def on_addons_dialog_will_show(dialog: AddonsDialog) -> None:
+ logger.debug(dialog)
+ set_dark_titlebar_qt(dialog, dwmapi)
+ dialog.setStyleSheet(open(css_files_dir['QAddonsDialog'], encoding='utf-8').read())
+ gui_hooks.addons_dialog_will_show.append(on_addons_dialog_will_show)
+ # Browser
+ if attribute_exists(gui_hooks, "browser_will_show"):
+ def on_browser_will_show(browser: Browser) -> None:
+ logger.debug(browser)
+ set_dark_titlebar_qt(browser, dwmapi)
+ browser.setStyleSheet(open(css_files_dir['QBrowser'], encoding='utf-8').read())
+ gui_hooks.browser_will_show.append(on_browser_will_show)
+
+## CONFIG DIALOG
+from aqt import mw, gui_hooks
+from aqt.qt import *
+from .config import config
+from aqt.utils import showInfo
+from aqt.webview import AnkiWebView
+
+class ThemeEditor(QDialog):
+ def __init__(self, parent, *args, **kwargs):
+ super().__init__(parent=parent or mw, *args, **kwargs)
+ self.config_editor = parent
+ self.setWindowModality(Qt.ApplicationModal)
+ self.setWindowTitle(f'Anki-redesign Advanced Editor')
+ self.setSizePolicy(self.make_size_policy())
+ self.setMinimumSize(420, 420)
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
+ set_dark_titlebar_qt(self, dwmapi, fix=False)
+ # Root layout
+ self.root_layout = QVBoxLayout(self)
+ # Main layout
+ self.layout = QVBoxLayout()
+ self.textedit = QTextEdit()
+ themes_plaintext = open(themes[theme], encoding='utf-8').read()
+ self.textedit.setPlainText(themes_plaintext)
+ self.layout.addWidget(self.textedit)
+ self.root_layout.addLayout(self.layout)
+ self.root_layout.addLayout(self.make_button_box())
+
+ def save_edit(self) -> None:
+ themes_parsed = json.loads(self.textedit.toPlainText())
+ write_theme(themes[theme], themes_parsed)
+ self.config_editor.update()
+ self.accept()
+
+ def make_button_box(self) -> QWidget:
+ def cancel():
+ button = QPushButton('Cancel')
+ button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
+ qconnect(button.clicked, self.accept)
+ return button
+ def save():
+ button = QPushButton('Save')
+ button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
+ button.setDefault(True)
+ button.setShortcut("Ctrl+Return")
+ button.clicked.connect(lambda _: self.save_edit())
+ return button
+
+ button_box = QHBoxLayout()
+ button_box.addStretch()
+ button_box.addWidget(cancel())
+ button_box.addWidget(save())
+ return button_box
+
+ def make_size_policy(self) -> QSizePolicy:
+ size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
+ size_policy.setHorizontalStretch(0)
+ size_policy.setVerticalStretch(0)
+ size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
+ return size_policy
+
+class ConfigDialog(QDialog):
+ def __init__(self, parent: QWidget, *args, **kwargs):
+ super().__init__(parent=parent or mw, *args, **kwargs)
+ self.setWindowModality(Qt.ApplicationModal)
+ self.setWindowTitle(f'Anki-redesign Configuration')
+ self.setSizePolicy(self.make_size_policy())
+ self.setMinimumSize(420, 580)
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
+ set_dark_titlebar_qt(self, dwmapi, fix=False)
+
+ # Color/theme
+ ## Loads theme color
+ self.theme_colors = themes_parsed.get("colors")
+ self.updates = []
+ self.theme_general = ["TEXT_FG", "WINDOW_BG", "FRAME_BG", "BUTTON_BG", "TOOLTIP_BG", "BORDER", "MEDIUM_BORDER", "FAINT_BORDER", "HIGHLIGHT_BG", "HIGHLIGHT_FG" , "LINK", "DISABLED", "SLIGHTLY_GREY_TEXT", "PRIMARY_COLOR"]
+ self.theme_decks = ["CURRENT_DECK", "NEW_COUNT", "LEARN_COUNT", "REVIEW_COUNT", "ZERO_COUNT"]
+ self.theme_browse = ["BURIED_FG", "SUSPENDED_FG", "MARKED_BG", "FLAG1_BG", "FLAG1_FG", "FLAG2_BG", "FLAG2_FG", "FLAG3_BG", "FLAG3_FG", "FLAG4_BG", "FLAG4_FG", "FLAG5_BG", "FLAG5_FG", "FLAG6_BG", "FLAG6_FG", "FLAG7_BG", "FLAG7_FG"]
+ self.theme_extra = []
+
+ # Root layout
+ self.root_layout = QVBoxLayout(self)
+ # Main layout
+ self.layout = QVBoxLayout()
+ ## Initialize tab screen
+ self.tabs = QTabWidget(objectName="tabs")
+ self.tabs.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
+ self.tab_general = QWidget(objectName="general")
+ self.tab_general.setLayout(self.create_color_picker_layout(self.theme_general))
+ self.tab_decks = QWidget(objectName="decks")
+ self.tab_decks.setLayout(self.create_color_picker_layout(self.theme_decks))
+ self.tab_browse = QWidget(objectName="browse")
+ self.tab_browse.setLayout(self.create_color_picker_layout(self.theme_browse))
+ self.tab_extra = QWidget(objectName="extra")
+ self.tab_extra.setLayout(self.create_color_picker_layout(self.theme_extra))
+
+ self.tab_settings = QWidget(objectName="settings")
+ self.settings_layout = QFormLayout()
+ self.theme_label = QLabel("Theme:")
+ self.theme_label.setStyleSheet('QLabel { font-size: 14px; font-weight: bold }')
+ self.settings_layout.addRow(self.theme_label)
+ for key in themes:
+ self.radio = self.radio_button(key)
+ self.settings_layout.addRow(key, self.radio)
+ self.settings_layout.addRow(QLabel())
+
+ self.font_label = QLabel("Font:")
+ self.font_label.setStyleSheet('QLabel { font-size: 14px; font-weight: bold }')
+ self.settings_layout.addRow(self.font_label)
+ self.interface_font = QFontComboBox()
+ self.interface_font.setFixedWidth(200)
+ self.interface_font.setCurrentFont(QFont(config["font"]))
+ self.settings_layout.addRow(self.interface_font)
+
+ self.font_size = QSpinBox()
+ self.font_size.setFixedWidth(200)
+ self.font_size.setValue(config["font_size"])
+ self.font_size.setSuffix("px")
+ self.settings_layout.addRow(self.font_size)
+
+ self.settings_layout.addRow(QLabel())
+
+
+ self.fix_label = QLabel("Addon-Compatibility Fixes: ")
+ self.fix_label.setStyleSheet('QLabel { font-size: 14px; font-weight: bold }')
+ self.settings_layout.addRow(self.fix_label)
+ self.reload_theme = self.checkbox("theme_reload")
+ self.settings_layout.addRow("QT6 theme on-start reload fix", self.reload_theme)
+ self.addon_more_overview_stats_check = self.checkbox("addon_more_overview_stats")
+ self.settings_layout.addRow("More Overview Stats 21", self.addon_more_overview_stats_check)
+ self.addon_advanced_review_bottom_bar_check = self.checkbox("addon_advanced_review_bottom_bar")
+ self.settings_layout.addRow("Advanced Review Bottom Bar", self.addon_advanced_review_bottom_bar_check)
+
+ self.tab_settings.setLayout(self.settings_layout)
+
+ ## Add tabs
+ self.tabs.resize(300,200)
+ self.tabs.addTab(self.tab_settings,"Settings")
+ self.tabs.addTab(self.tab_general,"General")
+ self.tabs.addTab(self.tab_decks,"Decks")
+ self.tabs.addTab(self.tab_browse,"Browse")
+ #self.tabs.addTab(self.tab_extra,"Extra")
+
+ ## Add tabs to widget
+ self.layout.addWidget(self.tabs)
+
+ self.root_layout.addLayout(self.layout)
+ self.root_layout.addLayout(self.make_button_box())
+ self.setLayout(self.root_layout)
+ self.show()
+
+ def update(self) -> None:
+ global themes_parsed
+ themes_parsed = get_theme(theme)
+ self.theme_colors = themes_parsed.get("colors")
+ for update in self.updates:
+ update()
+
+ def checkbox(self, key: str) -> QCheckBox:
+ checkbox = QCheckBox()
+
+ def update() -> None:
+ value = config[key]
+ checkbox.setChecked(value)
+
+ self.updates.append(update)
+ update()
+ return checkbox
+
+ def radio_button(self, key: str) -> QRadioButton:
+ radio = QRadioButton()
+
+ def update() -> None:
+ if theme == key:
+ radio.setChecked(True)
+ elif radio.isChecked():
+ radio.setChecked(False)
+
+ def toggle(checked) -> None:
+ global theme
+ if checked:
+ theme = key
+ self.update()
+
+ self.updates.append(update)
+ radio.toggled.connect(lambda checked: toggle(checked))
+ update()
+ return radio
+
+ def color_input(self, key: str) -> QPushButton:
+ button = QPushButton()
+ button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
+ button.setFixedWidth(25)
+ button.setFixedHeight(25)
+
+ color_dialog = QColorDialog(self)
+
+ def set_color(rgb: str) -> None:
+ # Check for valid color
+ color = QColor()
+ color.setNamedColor(rgb)
+ if not color.isValid():
+ return
+ # Update color
+ color_dialog.setCurrentColor(color)
+ button.setStyleSheet('QPushButton{ background-color: "%s"; border: none; border-radius: 2px}' % rgb)
+
+ def update() -> None:
+ rgb = self.theme_colors.get(key)[color_mode]
+ set_color(rgb)
+
+ def save(color: QColor) -> None:
+ rgb = color.name(QColor.NameFormat.HexRgb)
+ self.theme_colors[key][color_mode] = rgb
+ set_color(rgb)
+
+ self.updates.append(update)
+ color_dialog.colorSelected.connect(lambda color: save(color))
+ button.clicked.connect(lambda _: color_dialog.exec())
+ return button
+
+ def create_color_picker_layout(self, colors) -> None:
+ layout = QFormLayout()
+ for key in colors:
+ self.test = self.color_input(key)
+ layout.addRow(self.theme_colors.get(key)[0], self.test)
+ return layout
+
+ def theme_file_editor(self) -> None:
+ diag = ThemeEditor(self)
+ diag.show()
+
+ def make_button_box(self) -> QWidget:
+ def advanced():
+ button = QPushButton('Advanced')
+ button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
+ qconnect(button.clicked, self.theme_file_editor)
+ return button
+ def cancel():
+ button = QPushButton('Cancel')
+ button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
+ qconnect(button.clicked, self.accept)
+ return button
+ def save():
+ button = QPushButton('Save')
+ button.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
+ button.setDefault(True)
+ button.setShortcut("Ctrl+Return")
+ button.clicked.connect(lambda _: self.save())
+ return button
+
+ button_box = QHBoxLayout()
+ button_box.addWidget(advanced())
+ button_box.addStretch()
+ button_box.addWidget(cancel())
+ button_box.addWidget(save())
+ return button_box
+
+ def make_size_policy(self) -> QSizePolicy:
+ size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
+ size_policy.setHorizontalStretch(0)
+ size_policy.setVerticalStretch(0)
+ size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
+ return size_policy
+
+ def save(self) -> None:
+ # Save settings and update config
+ global config, color_mode
+ config["font"] = self.interface_font.currentFont().family()
+ config["font_size"] = self.font_size.value()
+ config['addon_more_overview_stats'] = self.addon_more_overview_stats_check.isChecked()
+ config['addon_advanced_review_bottom_bar'] = self.addon_advanced_review_bottom_bar_check.isChecked()
+ config['theme_reload'] = self.reload_theme.isChecked()
+ config["theme"] = theme
+ write_config(config)
+ config = get_config()
+
+ # Write and update theme
+ color_mode = 2 if theme_manager.get_night_mode() else 1 # 1 = light and 2 = dark
+ themes_parsed["colors"] = self.theme_colors
+ write_theme(themes[theme], themes_parsed)
+ update_theme()
+
+ # mw.reset()
+ # ShowInfo for both new and legacy support
+ showInfo(_("Changes will take effect when you restart Anki."))
+ #showInfo(tr.preferences_changes_will_take_effect_when_you())
+ self.accept()
+
+def check_legacy_colors() -> None:
+ try:
+ _ = colors.items()
+ except:
+ return False
+ return True
+
+def refresh_all_windows() -> None:
+ # Redraw top toolbar
+ mw.toolbar.draw()
+ if attribute_exists(gui_hooks, "top_toolbar_did_init_links"):
+ gui_hooks.top_toolbar_did_init_links.append(lambda a,b: [redraw_toolbar_legacy(a,b), gui_hooks.top_toolbar_did_init_links.remove(print)])
+
+ # Redraw main body
+ if mw.state == "review":
+ mw.reviewer._initWeb()
+ if mw.reviewer.state == "question":
+ mw.reviewer._showQuestion()
+ else:
+ mw.reviewer._showAnswer()
+ elif mw.state == "overview":
+ mw.overview.refresh()
+ elif mw.state == "deckBrowser":
+ mw.deckBrowser.show()
+
+ if attribute_exists(gui_hooks, "top_toolbar_did_init_links"):
+ gui_hooks.top_toolbar_did_init_links.remove(redraw_toolbar)
+
+def update_theme() -> None:
+ themes_parsed = get_theme(theme)
+ theme_colors = themes_parsed.get("colors")
+ # Apply theme on colors
+ ncolors = {}
+ # Legacy color check
+ logger.debug(dir(colors))
+ legacy = check_legacy_colors()
+ for color_name in theme_colors:
+ c = theme_colors.get(color_name)
+ ncolors[color_name] = c[color_mode]
+ if legacy:
+ colors[f"day{c[3].replace('--','-')}"] = c[1]
+ colors[f"night{c[3].replace('--','-')}"] = c[2]
+ # Potentially add fusion fixes too?
+ else:
+ logger.debug(getattr(colors, color_name, False))
+ if getattr(colors, color_name, False):
+ setattr(colors, color_name, (c[1], c[2]))
+ # Apply theme on palette
+ apply_theme(ncolors)
+ refresh_all_windows()
+
+def apply_theme(colors) -> None:
+ # Load palette
+ palette = QPalette()
+ # QT mappings
+ #logger.debug(QPalette.ColorRole.__dict__)
+ color_map = {
+ QPalette.ColorRole.Window: "WINDOW_BG",
+ QPalette.ColorRole.WindowText: "TEXT_FG",
+ QPalette.ColorRole.Base: "FRAME_BG",
+ QPalette.ColorRole.AlternateBase: "WINDOW_BG",
+ QPalette.ColorRole.ToolTipBase: "TOOLTIP_BG",
+ QPalette.ColorRole.ToolTipText: "TEXT_FG",
+ QPalette.ColorRole.Text: "TEXT_FG",
+ QPalette.ColorRole.Button: "BUTTON_BG",
+ QPalette.ColorRole.ButtonText: "TEXT_FG",
+ QPalette.ColorRole.BrightText: "HIGHLIGHT_FG",
+ QPalette.ColorRole.HighlightedText: "HIGHLIGHT_FG",
+ QPalette.ColorRole.Link: "LINK",
+ QPalette.ColorRole.NoRole: "WINDOW_BG",
+ }
+ for color_role in color_map:
+ palette.setColor(color_role, QColor(colors[color_map[color_role]]))
+
+ highlight_bg = QColor(colors["HIGHLIGHT_BG"])
+ highlight_bg.setAlpha(64)
+ palette.setColor(QPalette.ColorRole.Highlight, highlight_bg)
+
+ disabled_color = QColor(colors["DISABLED"])
+ palette.setColor(QPalette.ColorRole.PlaceholderText, disabled_color)
+ palette.setColor(QPalette.ColorGroup.Disabled, QPalette.ColorRole.Text, disabled_color)
+ palette.setColor(QPalette.ColorGroup.Disabled, QPalette.ColorRole.ButtonText, disabled_color)
+ palette.setColor(QPalette.ColorGroup.Disabled, QPalette.ColorRole.HighlightedText, disabled_color)
+
+ # Update palette
+ mw.app.setPalette(palette)
+ theme_manager.default_palette = palette
+ theme_manager._apply_style(mw.app)
+
+ # Update webview bg
+ AnkiWebView._getWindowColor = lambda *args: QColor(colors["WINDOW_BG"])
+ AnkiWebView.get_window_bg_color = lambda *args: QColor(colors["WINDOW_BG"])
+
+# Create menu actions
+def create_menu_action(parent: QWidget, dialog_class: QDialog, dialog_name: str) -> QAction:
+ def open_dialog():
+ dialog = dialog_class(mw)
+ return dialog.exec()
+
+ action = QAction(dialog_name, parent)
+ #qconnect(action.triggered, open_dialog)
+ action.triggered.connect(open_dialog)
+ return action
+
+# Load in the Anki-redesign menu
+if not hasattr(mw, 'anki_redesign'):
+ mw.anki_redesign = QMenu("&Anki-redesign", mw)
+ mw.form.menubar.insertMenu(mw.form.menuHelp.menuAction(), mw.anki_redesign)
+
+ mw.anki_redesign.addAction(create_menu_action(mw.anki_redesign, ConfigDialog, "&Config"))
+ mw.anki_redesign.addSeparator()
+ mw.reset()
+ update_theme()
+ mw.reset()
+
+ # Rereload view to fix theme change on startup
+ if 'Qt6' in QPalette.ColorRole.__module__:
+ logger.debug('QT6 DETECTED....')
+ config = get_config()
+ if config["theme_reload"]:
+ update_theme()
+
+def on_theme_did_change() -> None:
+ global color_mode
+ color_mode = 2 if theme_manager.get_night_mode() else 1 # 1 = light and 2 = dark
+ update_theme()
+ logger.debug("THEME CHANGEEEED")
+ refresh_all_windows()
+ mw.reset()
+ update_theme()
+
+
+if attribute_exists(gui_hooks, "theme_did_change"):
+ gui_hooks.theme_did_change.append(on_theme_did_change)
+ logger.debug("YEP") \ No newline at end of file
diff --git a/.local/share/Anki2/addons21/anki_reworked/config.json b/.local/share/Anki2/addons21/anki_reworked/config.json
new file mode 100644
index 0000000..b1e6ac5
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/config.json
@@ -0,0 +1,8 @@
+{
+ "addon_more_overview_stats": "false",
+ "addon_advanced_review_bottom_bar": "false",
+ "font": "Segoe UI",
+ "font_size": "12",
+ "theme": "Catppuccin",
+ "theme_reload": "false"
+}
diff --git a/.local/share/Anki2/addons21/anki_reworked/config.md b/.local/share/Anki2/addons21/anki_reworked/config.md
new file mode 100644
index 0000000..33498b4
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/config.md
@@ -0,0 +1,9 @@
+This is the advanced documentation for Anki-redesign's configuration:
+Use the built-in config at the menu (Anki-redesign > Config) for a better user experience.
+
+- addon_more_overview_stats: either `true` or `false`
+- addon_advanced_review_bottom_bar: either `true` or `false`
+- font: customize own font here
+- font_size: customize own font size here
+- theme: customize theme here
+- theme_reload: either `true` or `false`
diff --git a/.local/share/Anki2/addons21/anki_reworked/config.py b/.local/share/Anki2/addons21/anki_reworked/config.py
new file mode 100644
index 0000000..9e508f8
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/config.py
@@ -0,0 +1,22 @@
+from aqt import mw
+
+def get_config() -> dict:
+ config: dict = mw.addonManager.getConfig(__name__) or dict()
+ ## Addon fix
+ config['addon_more_overview_stats'] = True if config.get('addon_more_overview_stats', "false").lower() == "true" else False
+ config['addon_advanced_review_bottom_bar'] = True if config.get('addon_advanced_review_bottom_bar', "false").lower() == "true" else False
+ ## Customization
+ config['font'] = config.get('font', "Segoe UI")
+ config['font_size'] = int(config.get('font_size', "12"))
+ config['theme'] = config.get('theme', 'Anki')
+ config['theme_reload'] = True if config.get('theme_reload', "false").lower() == "true" else False
+
+ return config
+
+def write_config(config):
+ for key in config.keys():
+ if not isinstance(config[key], str):
+ config[key] = str(config[key])
+ mw.addonManager.writeConfig(__name__, config)
+
+config = get_config()
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/BottomBar.css b/.local/share/Anki2/addons21/anki_reworked/files/BottomBar.css
new file mode 100644
index 0000000..1e07817
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/BottomBar.css
@@ -0,0 +1,40 @@
+body #outer button {
+ color: var(--text-fg, var(--legacy-text-fg));
+ border: none;
+ border-radius: 15px;
+ padding: 6px 24px;
+ margin: 0 5px;
+ cursor: pointer;
+ font-weight: 500;
+ font-size: 0.875rem;
+ line-height: 1.75;
+ letter-spacing: 0.02857em;
+ text-transform: uppercase;
+ min-width: 64px;
+ background-color: var(--frame-bg, var(--legacy-frame-bg));
+ transition: background 0.2s linear, color 0.3s ease-out;
+ box-shadow: rgb(0 0 0 / 20%) 0px 3px 7px -2px,
+ rgb(0 0 0 / 5%) 0px 5px 10px 0px, rgb(0 0 0 / 12%) 0px 1px 5px 0px;
+}
+body.nightMode #outer button {
+ background: initial;
+ background-color: var(--frame-bg, var(--legacy-frame-bg));
+}
+
+body #outer button:focus,
+body #outer button.focus {
+ background-color: var(--primary-color);
+ color: var(--frame-bg, var(--legacy-frame-bg));
+ outline: none;
+}
+body.nightMode #outer button:focus,
+body.nightMode #outer button.focus {
+ color: var(--text-fg, var(--legacy-text-fg));
+}
+
+body #outer button:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+body.nightMode #outer button:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+}
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/CardLayout.css b/.local/share/Anki2/addons21/anki_reworked/files/CardLayout.css
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/CardLayout.css
@@ -0,0 +1 @@
+
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/DeckBrowser.css b/.local/share/Anki2/addons21/anki_reworked/files/DeckBrowser.css
new file mode 100644
index 0000000..0b8f82c
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/DeckBrowser.css
@@ -0,0 +1,48 @@
+body table:first-of-type {
+ width: 90%;
+ max-width: 600px;
+}
+body table:first-of-type th {
+ padding: 0 6px;
+}
+body table:first-of-type td {
+ padding: 6px;
+}
+body table:first-of-type tr.deck td {
+ border-bottom: none;
+}
+body table:first-of-type tr.deck td.opts {
+ padding-left: 20px;
+}
+body table:first-of-type tr.deck td.opts > a {
+ display: flex;
+}
+body table:first-of-type tr.current {
+ background-color: transparent;
+}
+body table:first-of-type tr.current td {
+ background-color: var(--faint-border, var(--legacy-faint-border));
+}
+body table:first-of-type tr.current td:first-of-type {
+ border-radius: 10px 0 0 10px;
+}
+body table:first-of-type tr.current td:last-of-type {
+ border-radius: 0 10px 10px 0;
+}
+body table:first-of-type tr a {
+ color: var(--text-fg, var(--legacy-text-fg)) !important;
+}
+body table:first-of-type tr a.filtered {
+ color: var(--link, var(--legacy-link)) !important;
+}
+a.deck {
+ padding: 5px 10px 5px 5px;
+ transition: padding 1s, background-color 0.5s, margin-right 1s;
+ border-radius: 6px;
+ margin-right: 5px;
+}
+body table:first-of-type tr a.deck:hover {
+ padding: 5px 10px 5px 10px;
+ background-color: rgba(0, 0, 0, 0.1);
+ margin-right: 0;
+}
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/Editor.css b/.local/share/Anki2/addons21/anki_reworked/files/Editor.css
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/Editor.css
@@ -0,0 +1 @@
+
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/Overview.css b/.local/share/Anki2/addons21/anki_reworked/files/Overview.css
new file mode 100644
index 0000000..7c7571a
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/Overview.css
@@ -0,0 +1,59 @@
+body .descmid {
+ text-align: center;
+}
+center > table tr:first-of-type {
+ display: flex;
+ flex-direction: column;
+}
+td table {
+ width: 50%;
+}
+td table tr:first-of-type {
+ display: table-row;
+ flex-direction: unset;
+}
+td table tr td:last-of-type {
+ text-align: right;
+}
+button#study.but,
+button#main.but {
+ padding: 10px 27px;
+ box-sizing: border-box;
+ width: 100%;
+ margin-bottom: 20px;
+
+ color: var(--text-fg, var(--legacy-text-fg));
+ border: none;
+ border-radius: 15px;
+ margin: 0 5px;
+ cursor: pointer;
+ font-weight: 500;
+ font-size: 0.875rem;
+ line-height: 1.75;
+ letter-spacing: 0.02857em;
+ text-transform: uppercase;
+ min-width: 64px;
+ background: initial;
+ background-color: var(--frame-bg, var(--legacy-frame-bg));
+ transition: background 0.2s linear, color 0.3s ease-out;
+ box-shadow: rgb(0 0 0 / 20%) 0px 3px 7px -2px,
+ rgb(0 0 0 / 5%) 0px 5px 10px 0px, rgb(0 0 0 / 12%) 0px 1px 5px 0px;
+}
+body.nightMode button#study.but:hover,
+body.nightMode button#main.but:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+}
+button#study.but:focus,
+button#main.but:focus {
+ background-color: var(--primary-color) !important;
+ color: var(--frame-bg, var(--legacy-frame-bg));
+ outline: none;
+}
+body.nightMode button#study.but:focus,
+body.nightMode button#main.but:focus {
+ color: var(--text-fg);
+}
+button#study.but:hover,
+button#main.but:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/QAbout.css b/.local/share/Anki2/addons21/anki_reworked/files/QAbout.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/QAbout.css
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/QAddCards.css b/.local/share/Anki2/addons21/anki_reworked/files/QAddCards.css
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/QAddCards.css
@@ -0,0 +1 @@
+
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/QAddonsDialog.css b/.local/share/Anki2/addons21/anki_reworked/files/QAddonsDialog.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/QAddonsDialog.css
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/QBrowser.css b/.local/share/Anki2/addons21/anki_reworked/files/QBrowser.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/QBrowser.css
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/QEditCurrent.css b/.local/share/Anki2/addons21/anki_reworked/files/QEditCurrent.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/QEditCurrent.css
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/QFilteredDeckConfigDialog.css b/.local/share/Anki2/addons21/anki_reworked/files/QFilteredDeckConfigDialog.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/QFilteredDeckConfigDialog.css
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/QNewDeckStats.css b/.local/share/Anki2/addons21/anki_reworked/files/QNewDeckStats.css
new file mode 100644
index 0000000..88cb00c
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/QNewDeckStats.css
@@ -0,0 +1,3 @@
+body {
+ background-color: red;
+} \ No newline at end of file
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/QPreferences.css b/.local/share/Anki2/addons21/anki_reworked/files/QPreferences.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/QPreferences.css
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/Reviewer.css b/.local/share/Anki2/addons21/anki_reworked/files/Reviewer.css
new file mode 100644
index 0000000..9e47f09
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/Reviewer.css
@@ -0,0 +1,9 @@
+body #typeans {
+ padding: 8px 12px;
+ border-radius: 5px;
+}
+body.card {
+ width: 90%;
+ margin: 20px auto;
+ max-width: 1080px;
+}
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/ReviewerBottomBar.css b/.local/share/Anki2/addons21/anki_reworked/files/ReviewerBottomBar.css
new file mode 100644
index 0000000..768270e
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/ReviewerBottomBar.css
@@ -0,0 +1,60 @@
+body {
+ overflow: hidden;
+}
+body #outer {
+ border-top: 1px solid transparent;
+}
+body.nightMode #outer {
+ border-top-color: transparent;
+}
+body #outer table#innertable {
+ padding: 6px;
+ transform: translateY(8px);
+}
+body button {
+ margin: 0;
+}
+body .stat {
+ position: relative;
+ padding-top: 0px;
+ min-width: 120px;
+}
+body .stat2 {
+ padding-top: 0px;
+ font-weight: normal;
+}
+td[align="center"] {
+ position: relative;
+}
+body .stattxt,
+td[align="center"] > span {
+ position: absolute;
+ display: block;
+ left: 50%;
+ transform: translate(-50%, -13px);
+ color: var(--text-fg, var(--legacy-text-fg));
+}
+body .stattxt#time {
+ transform: translate(-50%, -6px);
+}
+body #outer button#ansbut,
+body #outer table button {
+ transform: translateY(-4px);
+}
+/* ARBb addon fix */
+body #outer.arbb .stat {
+ min-width: auto;
+ padding-left: 2px;
+ padding-right: 2px;
+}
+body #outer.arbb table#innertable {
+ padding: initial;
+ width: calc(100% - 10px);
+}
+body #outer.arbb button {
+ /* color: var(--text-fg, var(--legacy-text-fg)); */
+ letter-spacing: 0.02857em;
+ text-transform: uppercase;
+ margin-left: 2px;
+ margin-right: 2px;
+}
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/TopToolbar.css b/.local/share/Anki2/addons21/anki_reworked/files/TopToolbar.css
new file mode 100644
index 0000000..3b4b6ee
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/TopToolbar.css
@@ -0,0 +1,25 @@
+body #outer {
+ display: flex;
+ justify-content: center;
+}
+body center #header {
+ width: auto;
+ border-bottom: none;
+ border-radius: 0 0 12px 12px;
+ background-color: var(--frame-bg, var(--legacy-frame-bg));
+ height: 40px;
+ box-shadow: rgb(0 0 0 / 10%) 0px 0px 11px -2px,
+ rgb(0 0 0 / 14%) 0px 2px 2px 0px, rgb(0 0 0 / 12%) 0px 4px 5px 0px;
+}
+body.nightMode center #header {
+ background-color: var(--faint-border, var(--legacy-faint-border));
+}
+body center #header .hitem {
+ padding-left: initial;
+ padding-right: initial;
+ padding: 0 15px;
+ color: var(--text-fg, var(--legacy-text-fg)) !important;
+}
+body center #header a#sync {
+ color: var(--link, var(--legacy-link)) !important;
+}
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/global.css b/.local/share/Anki2/addons21/anki_reworked/files/global.css
new file mode 100644
index 0000000..a145312
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/global.css
@@ -0,0 +1,96 @@
+:root,
+:root .isWin,
+:root .isMac,
+:root .isLin {
+ --focus-color: rgba(81, 135, 169, 0.7);
+}
+/* Force LIGHT MODE Background */
+:root body:not(.nightMode),
+:root body.isWin:not(.nightMode),
+:root body.isMac:not(.nightMode),
+:root body.isLin:not(.nightMode) {
+ /* Force variable styling on legacy versions */
+ --legacy-text-fg: black;
+ --legacy-frame-bg: white;
+ --legacy-border: #aaa;
+ --legacy-medium-border: #b6b6b6;
+ --legacy-faint-border: #e7e7e7;
+ --legacy-link: #00a;
+ --legacy-review-count: #0a0;
+ --legacy-new-count: #00a;
+ --legacy-learn-count: #c35617;
+ --legacy-zero-count: #ddd;
+ --legacy-slightly-grey-text: #333;
+ --legacy-highlight-bg: #77ccff;
+ --legacy-highlight-fg: black;
+ --legacy-disabled: #777;
+ --legacy-flag1-fg: #e25252;
+ --legacy-flag2-fg: #ffb347;
+ --legacy-flag3-fg: #54c414;
+ --legacy-flag4-fg: #578cff;
+ --legacy-flag5-fg: #ff82ee;
+ --legacy-flag6-fg: #00d1b5;
+ --legacy-flag7-fg: #9649dd;
+ --legacy-flag1-bg: #ff9b9b;
+ --legacy-flag2-bg: #ffb347;
+ --legacy-flag3-bg: #93e066;
+ --legacy-flag4-bg: #9dbcff;
+ --legacy-flag5-bg: #f5a8eb;
+ --legacy-flag6-bg: #7edbd7;
+ --legacy-flag7-bg: #cca3f1;
+ --legacy-buried-fg: #aaaa33;
+ --legacy-suspended-fg: #dd0;
+ --legacy-suspended-bg: #ffffb2;
+ --legacy-marked-bg: #cce;
+ --legacy-tooltip-bg: #fcfcfc;
+}
+/* Force DARK MODE Background */
+:root body.nightMode,
+:root body.isWin.nightMode,
+:root body.isMac.nightMode,
+:root body.isLin.nightMode {
+ /* Force variable styling on legacy versions */
+ --legacy-text-fg: white;
+ --legacy-frame-bg: #3a3a3a;
+ --legacy-border: #777;
+ --legacy-medium-border: #444;
+ --legacy-faint-border: #29292b;
+ --legacy-link: #77ccff;
+ --legacy-review-count: #5ccc00;
+ --legacy-new-count: #77ccff;
+ --legacy-learn-count: #ff935b;
+ --legacy-zero-count: #444;
+ --legacy-slightly-grey-text: #ccc;
+ --legacy-highlight-bg: #77ccff;
+ --legacy-highlight-fg: white;
+ --legacy-disabled: #777;
+ --legacy-flag1-fg: #ff7b7b;
+ --legacy-flag2-fg: #f5aa41;
+ --legacy-flag3-fg: #86ce5d;
+ --legacy-flag4-fg: #6f9dff;
+ --legacy-flag5-fg: #f097e4;
+ --legacy-flag6-fg: #5ccfca;
+ --legacy-flag7-fg: #9f63d3;
+ --legacy-flag1-bg: #aa5555;
+ --legacy-flag2-bg: #ac653a;
+ --legacy-flag3-bg: #559238;
+ --legacy-flag4-bg: #506aa3;
+ --legacy-flag5-bg: #975d8f;
+ --legacy-flag6-bg: #399185;
+ --legacy-flag7-bg: #624b77;
+ --legacy-buried-fg: #777733;
+ --legacy-suspended-fg: #ffffb2;
+ --legacy-suspended-bg: #aaaa33;
+ --legacy-marked-bg: #77c;
+ --legacy-tooltip-bg: #272727;
+}
+
+body {
+ background-color: var(--window-bg) !important;
+}
+html {
+ font-size: 12px;
+}
+html body a {
+ color: var(--link, var(--legacy-link)) !important;
+}
diff --git a/.local/share/Anki2/addons21/anki_reworked/files/legacy.css b/.local/share/Anki2/addons21/anki_reworked/files/legacy.css
new file mode 100644
index 0000000..2ce3692
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/files/legacy.css
@@ -0,0 +1,18 @@
+button {
+ box-sizing: border-box;
+ color: var(--text-fg, var(--legacy-text-fg));
+ border: none;
+ border-radius: 15px;
+ cursor: pointer;
+ padding: 6px 24px;
+ font-weight: 500;
+ font-size: 0.875rem;
+ line-height: 1.75;
+ letter-spacing: 0.02857em;
+ text-transform: uppercase;
+ background: initial;
+ background-color: var(--frame-bg, var(--legacy-frame-bg));
+ transition: background 0.2s linear, color 0.3s ease-out;
+ box-shadow: rgb(0 0 0 / 20%) 0px 3px 7px -2px,
+ rgb(0 0 0 / 5%) 0px 5px 10px 0px, rgb(0 0 0 / 12%) 0px 1px 5px 0px;
+} \ No newline at end of file
diff --git a/.local/share/Anki2/addons21/anki_reworked/manifest.json b/.local/share/Anki2/addons21/anki_reworked/manifest.json
new file mode 100644
index 0000000..33ce43f
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/manifest.json
@@ -0,0 +1,10 @@
+{
+ "name": "Anki Redesign",
+ "package": "anki-redesign",
+ "ankiweb_id": "308574457",
+ "author": "Shirajuki",
+ "version": "0.1.3",
+ "homepage": "https://github.com/shirajuki/anki-redesign",
+ "conflicts": ["308574457", "688199788"],
+ "manifest_version": 2
+}
diff --git a/.local/share/Anki2/addons21/anki_reworked/meta.json b/.local/share/Anki2/addons21/anki_reworked/meta.json
new file mode 100644
index 0000000..17e78d2
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/meta.json
@@ -0,0 +1 @@
+{"homepage": "https://github.com/shirajuki/anki-redesign", "name": "Anki-redesign", "conflicts": ["308574457", "688199788"], "mod": 1656801893, "min_point_version": 20, "max_point_version": 54, "branch_index": 0, "disabled": true, "config": {"addon_more_overview_stats": "True", "addon_advanced_review_bottom_bar": "True", "font": "3270Medium Nerd Font", "font_size": "12", "theme": "Catppuccin", "theme_reload": "True"}, "update_enabled": true} \ No newline at end of file
diff --git a/.local/share/Anki2/addons21/anki_reworked/themes/Anki.json b/.local/share/Anki2/addons21/anki_reworked/themes/Anki.json
new file mode 100644
index 0000000..31a4818
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/themes/Anki.json
@@ -0,0 +1,230 @@
+{
+ "colors": {
+ "BORDER": [
+ "Border",
+ "#aaa",
+ "#777",
+ "--border"
+ ],
+ "BURIED_FG": [
+ "Buried Foreground",
+ "#aaaa33",
+ "#777733",
+ "--buried-fg"
+ ],
+ "BUTTON_BG": [
+ "Button Background",
+ "#eff0f1",
+ "#454545",
+ ""
+ ],
+ "CURRENT_DECK": [
+ "Selected Deck",
+ "#e7e7e7",
+ "#29292b",
+ "--current-deck"
+ ],
+ "DISABLED": [
+ "Disabled",
+ "#777",
+ "#777",
+ "--disabled"
+ ],
+ "FAINT_BORDER": [
+ "Faint Border",
+ "#e7e7e7",
+ "#29292b",
+ "--faint-border"
+ ],
+ "FLAG1_BG": [
+ "Flag1 (Browse Cards List)",
+ "#ff9b9b",
+ "#aa5555",
+ "--flag1-bg"
+ ],
+ "FLAG1_FG": [
+ "Flag1 (Browse Sidebar)",
+ "#e25252",
+ "#ff7b7b",
+ "--flag1-fg"
+ ],
+ "FLAG2_BG": [
+ "Flag2 (Browse Cards List)",
+ "#ffb347",
+ "#ac653a",
+ "--flag2-bg"
+ ],
+ "FLAG2_FG": [
+ "Flag2 (Browse Sidebar)",
+ "#ffb347",
+ "#f5aa41",
+ "--flag2-fg"
+ ],
+ "FLAG3_BG": [
+ "Flag3 (Browse Cards List)",
+ "#93e066",
+ "#559238",
+ "--flag3-bg"
+ ],
+ "FLAG3_FG": [
+ "Flag3 (Browse Sidebar)",
+ "#54c414",
+ "#86ce5d",
+ "--flag3-fg"
+ ],
+ "FLAG4_BG": [
+ "Flag4 (Browse Cards List)",
+ "#9dbcff",
+ "#506aa3",
+ "--flag4-bg"
+ ],
+ "FLAG4_FG": [
+ "Flag4 (Browse Sidebar)",
+ "#578cff",
+ "#6f9dff",
+ "--flag4-fg"
+ ],
+ "FLAG5_BG": [
+ "Flag5 (Browse Cards List)",
+ "#f5a8eb",
+ "#975d8f",
+ "--flag5-bg"
+ ],
+ "FLAG5_FG": [
+ "Flag5 (Browse Sidebar)",
+ "#ff82ee",
+ "#f097e4",
+ "--flag5-fg"
+ ],
+ "FLAG6_BG": [
+ "Flag6 (Browse Cards List)",
+ "#7edbd7",
+ "#399185",
+ "--flag6-bg"
+ ],
+ "FLAG6_FG": [
+ "Flag6 (Browse Sidebar)",
+ "#00d1b5",
+ "#5ccfca",
+ "--flag6-fg"
+ ],
+ "FLAG7_BG": [
+ "Flag7 (Browse Cards List)",
+ "#cca3f1",
+ "#624b77",
+ "--flag7-bg"
+ ],
+ "FLAG7_FG": [
+ "Flag7 (Browse Sidebar)",
+ "#9649dd",
+ "#9f63d3",
+ "--flag7-fg"
+ ],
+ "FRAME_BG": [
+ "Frame Background",
+ "white",
+ "#3a3a3a",
+ "--frame-bg"
+ ],
+ "HIGHLIGHT_BG": [
+ "Highlighted Background",
+ "#77ccff",
+ "#77ccff",
+ "--highlight-bg"
+ ],
+ "HIGHLIGHT_FG": [
+ "Highlighted Text",
+ "black",
+ "white",
+ "--highlight-fg"
+ ],
+ "LEARN_COUNT": [
+ "Learn Count",
+ "#c35617",
+ "#ff935b",
+ "--learn-count"
+ ],
+ "LINK": [
+ "Hyperlink",
+ "#00a",
+ "#77ccff",
+ "--link"
+ ],
+ "MARKED_BG": [
+ "Marked Background",
+ "#cce",
+ "#77c",
+ "--marked-bg"
+ ],
+ "MEDIUM_BORDER": [
+ "Medium Border",
+ "#b6b6b6",
+ "#444",
+ "--medium-border"
+ ],
+ "NEW_COUNT": [
+ "New Count",
+ "#00a",
+ "#77ccff",
+ "--new-count"
+ ],
+ "PRIMARY_COLOR": [
+ "Primary Color",
+ "#0093d0",
+ "#0093d0",
+ "--primary-color"
+ ],
+ "REVIEW_COUNT": [
+ "Review Count",
+ "#0a0",
+ "#5ccc00",
+ "--review-count"
+ ],
+ "SLIGHTLY_GREY_TEXT": [
+ "Switch Text",
+ "#333",
+ "#ccc",
+ "--slightly-grey-text"
+ ],
+ "SUSPENDED_BG": [
+ "Suspended Background",
+ "#ffffb2",
+ "#aaaa33",
+ "--suspended-bg"
+ ],
+ "SUSPENDED_FG": [
+ "Suspended Foreground",
+ "#dd0",
+ "#ffffb2",
+ "--suspended-fg"
+ ],
+ "TEXT_FG": [
+ "Text Foreground",
+ "black",
+ "white",
+ "--text-fg"
+ ],
+ "TOOLTIP_BG": [
+ "Tooltip Background",
+ "#fcfcfc",
+ "#272727",
+ "--tooltip-bg"
+ ],
+ "WINDOW_BG": [
+ "Window Background",
+ "#fafafa",
+ "#2f2f31",
+ "--window-bg"
+ ],
+ "ZERO_COUNT": [
+ "Zero Count",
+ "#ddd",
+ "#444",
+ "--zero-count"
+ ]
+ },
+ "version": {
+ "major": -1,
+ "minor": -1
+ }
+} \ No newline at end of file
diff --git a/.local/share/Anki2/addons21/anki_reworked/themes/Catppuccin.json b/.local/share/Anki2/addons21/anki_reworked/themes/Catppuccin.json
new file mode 100644
index 0000000..39684d2
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/themes/Catppuccin.json
@@ -0,0 +1,230 @@
+{
+ "colors": {
+ "BORDER": [
+ "Border",
+ "#aaa",
+ "#434c5e",
+ "--border"
+ ],
+ "BURIED_FG": [
+ "Buried Foreground",
+ "#aaaa33",
+ "#777733",
+ "--buried-fg"
+ ],
+ "BUTTON_BG": [
+ "Button Background",
+ "#e7e7e7",
+ "#1A1826",
+ "--button-bg"
+ ],
+ "CURRENT_DECK": [
+ "Selected Deck",
+ "#e7e7e7",
+ "#1A1826",
+ "--current-deck"
+ ],
+ "DISABLED": [
+ "Disabled",
+ "#777",
+ "#C3BAC6",
+ "--disabled"
+ ],
+ "FAINT_BORDER": [
+ "Faint Border",
+ "#e7e7e7",
+ "#1A1826",
+ "--faint-border"
+ ],
+ "FLAG1_BG": [
+ "Flag1 (Browse Cards List)",
+ "#BF616A",
+ "#BF616A",
+ "--flag1-bg"
+ ],
+ "FLAG1_FG": [
+ "Flag1 (BrowseSidebar)",
+ "#BF616A",
+ "#BF616A",
+ "--flag1-fg"
+ ],
+ "FLAG2_BG": [
+ "Flag2 (Browse Cards List)",
+ "#D08770",
+ "#D08770",
+ "--flag2-bg"
+ ],
+ "FLAG2_FG": [
+ "Flag2 (Browse Sidebar)",
+ "#D08770",
+ "#D08770",
+ "--flag2-fg"
+ ],
+ "FLAG3_BG": [
+ "Flag3 (Browse Cards List)",
+ "#A3BE8C",
+ "#A3BE8C",
+ "--flag3-bg"
+ ],
+ "FLAG3_FG": [
+ "Flag3 (Browse Sidebar)",
+ "#A3BE8C",
+ "#A3BE8C",
+ "--flag3-fg"
+ ],
+ "FLAG4_BG": [
+ "Flag4 (Browse Cards List)",
+ "#5E81AC",
+ "#5E81AC",
+ "--flag4-bg"
+ ],
+ "FLAG4_FG": [
+ "Flag4 (Browse Sidebar)",
+ "#5E81AC",
+ "#5E81AC",
+ "--flag4-fg"
+ ],
+ "FLAG5_BG": [
+ "Flag5 (Browse Cards List)",
+ "#B48EAD",
+ "#B48EAD",
+ "--flag5-bg"
+ ],
+ "FLAG5_FG": [
+ "Flag5 (Browse Sidebar)",
+ "#B48EAD",
+ "#B48EAD",
+ "--flag5-fg"
+ ],
+ "FLAG6_BG": [
+ "Flag6 (Browse Cards List)",
+ "#7edbd7",
+ "#399185",
+ "--flag6-bg"
+ ],
+ "FLAG6_FG": [
+ "Flag6 (Browse Sidebar)",
+ "#00d1b5",
+ "#5ccfca",
+ "--flag6-fg"
+ ],
+ "FLAG7_BG": [
+ "Flag7 (Browse Cards List)",
+ "#cca3f1",
+ "#624b77",
+ "--flag7-bg"
+ ],
+ "FLAG7_FG": [
+ "Flag7 (Browse Sidebar)",
+ "#9649dd",
+ "#9f63d3",
+ "--flag7-fg"
+ ],
+ "FRAME_BG": [
+ "Frame Background",
+ "white",
+ "#1A1826",
+ "--frame-bg"
+ ],
+ "HIGHLIGHT_BG": [
+ "Highlighted Background",
+ "#77ccff",
+ "#81A1C1",
+ "--highlight-bg"
+ ],
+ "HIGHLIGHT_FG": [
+ "Highlighted Text",
+ "black",
+ "#ECEFF4",
+ "--highlight-fg"
+ ],
+ "LEARN_COUNT": [
+ "Learn Count",
+ "#c35617",
+ "#D08770",
+ "--learn-count"
+ ],
+ "LINK": [
+ "Hyperlink",
+ "#6e9fda",
+ "#89DCEB",
+ "--link"
+ ],
+ "MARKED_BG": [
+ "Marked Background",
+ "#cce",
+ "#ebcb8b",
+ "--marked-bg"
+ ],
+ "MEDIUM_BORDER": [
+ "Medium Border",
+ "#b6b6b6",
+ "#434C5E",
+ "--medium-border"
+ ],
+ "NEW_COUNT": [
+ "New Count",
+ "#00a",
+ "#5E81AC",
+ "--new-count"
+ ],
+ "PRIMARY_COLOR": [
+ "Primary Color",
+ "#0093d0",
+ "#0093d0",
+ "--primary-color"
+ ],
+ "REVIEW_COUNT": [
+ "Review Count",
+ "#0a0",
+ "#A3BE8C",
+ "--review-count"
+ ],
+ "SLIGHTLY_GREY_TEXT": [
+ "Switch Text",
+ "#333",
+ "#D8DEE9",
+ "--slightly-grey-text"
+ ],
+ "SUSPENDED_BG": [
+ "Suspended Background",
+ "#ffffb2",
+ "#161320",
+ "--suspended-bg"
+ ],
+ "SUSPENDED_FG": [
+ "Suspended Foreground",
+ "#dd0",
+ "#ECEFF4",
+ "--suspended-fg"
+ ],
+ "TEXT_FG": [
+ "Text Foreground",
+ "black",
+ "#d9e0ee",
+ "--text-fg"
+ ],
+ "TOOLTIP_BG": [
+ "Tooltip Background",
+ "#fcfcfc",
+ "#4C566A",
+ "--tooltip-bg"
+ ],
+ "WINDOW_BG": [
+ "Window Background",
+ "#fafafa",
+ "#1E1E2E",
+ "--window-bg"
+ ],
+ "ZERO_COUNT": [
+ "Zero Count",
+ "#ddd",
+ "#434C5E",
+ "--zero-count"
+ ]
+ },
+ "version": {
+ "major": 1,
+ "minor": 5
+ }
+} \ No newline at end of file
diff --git a/.local/share/Anki2/addons21/anki_reworked/themes/Nord.json b/.local/share/Anki2/addons21/anki_reworked/themes/Nord.json
new file mode 100644
index 0000000..25c507b
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/themes/Nord.json
@@ -0,0 +1,230 @@
+{
+ "colors": {
+ "BORDER": [
+ "Border",
+ "#D8DEE9",
+ "#434C5E",
+ "--border"
+ ],
+ "BURIED_FG": [
+ "Buried Foreground",
+ "#aaaa33",
+ "#777733",
+ "--buried-fg"
+ ],
+ "BUTTON_BG": [
+ "Button Background",
+ "#D8DEE9",
+ "#3B4252",
+ ""
+ ],
+ "CURRENT_DECK": [
+ "Selected Deck",
+ "#E5E9F0",
+ "#3B4252",
+ "--current-deck"
+ ],
+ "DISABLED": [
+ "Disabled",
+ "#D8DEE9",
+ "#D8DEE9",
+ "--disabled"
+ ],
+ "FAINT_BORDER": [
+ "Faint Border",
+ "#ECEFF4",
+ "#3B4252",
+ "--faint-border"
+ ],
+ "FLAG1_BG": [
+ "Flag1 (Browse Cards List)",
+ "#BF616A",
+ "#BF616A",
+ "--flag1-bg"
+ ],
+ "FLAG1_FG": [
+ "Flag1 (BrowseSidebar)",
+ "#BF616A",
+ "#BF616A",
+ "--flag1-fg"
+ ],
+ "FLAG2_BG": [
+ "Flag2 (Browse Cards List)",
+ "#D08770",
+ "#D08770",
+ "--flag2-bg"
+ ],
+ "FLAG2_FG": [
+ "Flag2 (Browse Sidebar)",
+ "#D08770",
+ "#D08770",
+ "--flag2-fg"
+ ],
+ "FLAG3_BG": [
+ "Flag3 (Browse Cards List)",
+ "#A3BE8C",
+ "#A3BE8C",
+ "--flag3-bg"
+ ],
+ "FLAG3_FG": [
+ "Flag3 (Browse Sidebar)",
+ "#A3BE8C",
+ "#A3BE8C",
+ "--flag3-fg"
+ ],
+ "FLAG4_BG": [
+ "Flag4 (Browse Cards List)",
+ "#5E81AC",
+ "#5E81AC",
+ "--flag4-bg"
+ ],
+ "FLAG4_FG": [
+ "Flag4 (Browse Sidebar)",
+ "#5E81AC",
+ "#5E81AC",
+ "--flag4-fg"
+ ],
+ "FLAG5_BG": [
+ "Flag5 (Browse Cards List)",
+ "#B48EAD",
+ "#B48EAD",
+ "--flag5-bg"
+ ],
+ "FLAG5_FG": [
+ "Flag5 (Browse Sidebar)",
+ "#B48EAD",
+ "#B48EAD",
+ "--flag5-fg"
+ ],
+ "FLAG6_BG": [
+ "Flag6 (Browse Cards List)",
+ "#7edbd7",
+ "#399185",
+ "--flag6-bg"
+ ],
+ "FLAG6_FG": [
+ "Flag6 (Browse Sidebar)",
+ "#00d1b5",
+ "#5ccfca",
+ "--flag6-fg"
+ ],
+ "FLAG7_BG": [
+ "Flag7 (Browse Cards List)",
+ "#cca3f1",
+ "#624b77",
+ "--flag7-bg"
+ ],
+ "FLAG7_FG": [
+ "Flag7 (Browse Sidebar)",
+ "#9649dd",
+ "#9f63d3",
+ "--flag7-fg"
+ ],
+ "FRAME_BG": [
+ "Frame Background",
+ "#E5E9F0",
+ "#3B4252",
+ "--frame-bg"
+ ],
+ "HIGHLIGHT_BG": [
+ "Highlighted Background",
+ "#81A1C1",
+ "#81A1C1",
+ "--highlight-bg"
+ ],
+ "HIGHLIGHT_FG": [
+ "Highlighted Text",
+ "white",
+ "#ECEFF4",
+ "--highlight-fg"
+ ],
+ "LEARN_COUNT": [
+ "Learn Count",
+ "#D08770",
+ "#D08770",
+ "--learn-count"
+ ],
+ "LINK": [
+ "Hyperlink",
+ "#8FBCBB",
+ "#8FBCBB",
+ "--link"
+ ],
+ "MARKED_BG": [
+ "Marked Background",
+ "#EBCB8B",
+ "#EBCB8B",
+ "--marked-bg"
+ ],
+ "MEDIUM_BORDER": [
+ "Medium Border",
+ "#E5E9F0",
+ "#434C5E",
+ "--medium-border"
+ ],
+ "NEW_COUNT": [
+ "New Count",
+ "#5E81AC",
+ "#5E81AC",
+ "--new-count"
+ ],
+ "PRIMARY_COLOR": [
+ "Primary Color",
+ "#0093d0",
+ "#0093d0",
+ "--primary-color"
+ ],
+ "REVIEW_COUNT": [
+ "Review Count",
+ "#A3BE8C",
+ "#A3BE8C",
+ "--review-count"
+ ],
+ "SLIGHTLY_GREY_TEXT": [
+ "Switch Text",
+ "#3B4252",
+ "#D8DEE9",
+ "--slightly-grey-text"
+ ],
+ "SUSPENDED_BG": [
+ "Suspended Background",
+ "#88C0D0",
+ "#88C0D0",
+ "--suspended-bg"
+ ],
+ "SUSPENDED_FG": [
+ "Suspended Foreground",
+ "#3B4252",
+ "#ECEFF4",
+ "--suspended-fg"
+ ],
+ "TEXT_FG": [
+ "Text Foreground",
+ "#2E3440",
+ "#E5E9F0",
+ "--text-fg"
+ ],
+ "TOOLTIP_BG": [
+ "Tooltip Background",
+ "#D8DEE9",
+ "#4C566A",
+ "--tooltip-bg"
+ ],
+ "WINDOW_BG": [
+ "Window Background",
+ "white",
+ "#2E3440",
+ "--window-bg"
+ ],
+ "ZERO_COUNT": [
+ "Zero Count",
+ "#D8DEE9",
+ "#434C5E",
+ "--zero-count"
+ ]
+ },
+ "version": {
+ "major": 1,
+ "minor": 5
+ }
+} \ No newline at end of file
diff --git a/.local/share/Anki2/addons21/anki_reworked/themes/readme.txt b/.local/share/Anki2/addons21/anki_reworked/themes/readme.txt
new file mode 100644
index 0000000..43f5cc1
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/themes/readme.txt
@@ -0,0 +1,8 @@
+To create your own customized themes
+make a copy of Anki.json, name and edit it according
+to your wishes.
+
+This addon is also compatible with the themes of ReColor,
+which means that the uploaded community themes can also
+be downloaded and used:
+- https://github.com/AnKingMed/AnkiRecolor/wiki/Themes
diff --git a/.local/share/Anki2/addons21/anki_reworked/user_files/readme.txt b/.local/share/Anki2/addons21/anki_reworked/user_files/readme.txt
new file mode 100644
index 0000000..f612d51
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/user_files/readme.txt
@@ -0,0 +1,11 @@
+To create your own customized style design,
+copy over the css files from ./files to ./user_files
+you would like to edit.
+
+CSS files starting with "Q" indicates that the syntax is of
+Qt CSS, which is in it's core quite similar to the usual CSS.
+Documentation here:
+- https://doc.qt.io/qt-5/stylesheet-syntax.html
+
+User edited themes should that is also customized will be saved
+in this folder.
diff --git a/.local/share/Anki2/addons21/anki_reworked/utils/css_files.py b/.local/share/Anki2/addons21/anki_reworked/utils/css_files.py
new file mode 100644
index 0000000..0b88564
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/utils/css_files.py
@@ -0,0 +1,37 @@
+import os
+from aqt import mw
+
+mw.addonManager.setWebExports(__name__, r"files/.*\.(css|svg|gif|png)|user_files/.*\.(css|svg|gif|png)")
+addon_package = mw.addonManager.addonFromModule(__name__)
+
+this_script_dir = os.path.join(os.path.dirname(__file__), "..")
+files_dir = os.path.join(this_script_dir, 'files')
+user_files_dir = os.path.join(this_script_dir, 'user_files')
+css_files_dir = {
+ 'BottomBar': f"/_addons/{addon_package}/files/BottomBar.css",
+ 'CardLayout': f"/_addons/{addon_package}/files/CardLayout.css",
+ 'DeckBrowser': f"/_addons/{addon_package}/files/DeckBrowser.css",
+ 'Editor': f"/_addons/{addon_package}/files/Editor.css",
+ 'global': f"/_addons/{addon_package}/files/global.css",
+ 'legacy': f"/_addons/{addon_package}/files/legacy.css",
+ 'Overview': f"/_addons/{addon_package}/files/Overview.css",
+ 'QAbout': os.path.join(files_dir, 'QAbout.css'),
+ 'QAddCards': os.path.join(files_dir, 'QAddCards.css'),
+ 'QAddonsDialog': os.path.join(files_dir, 'QAddonsDialog.css'),
+ 'QBrowser': os.path.join(files_dir, 'QBrowser.css'),
+ 'QFilteredDeckConfigDialog': os.path.join(files_dir, 'QFilteredDeckConfigDialog.css'),
+ 'QEditCurrent': os.path.join(files_dir, 'QEditCurrent.css'),
+ 'QNewDeckStats': os.path.join(files_dir, 'QNewDeckStats.css'),
+ 'QPreferences': os.path.join(files_dir, 'QPreferences.css'),
+ 'Reviewer': f"/_addons/{addon_package}/files/Reviewer.css",
+ 'ReviewerBottomBar': f"/_addons/{addon_package}/files/ReviewerBottomBar.css",
+ 'TopToolbar': f"/_addons/{addon_package}/files/TopToolbar.css",
+}
+# Replace pathing for user customised styled files
+for file in os.listdir(user_files_dir):
+ file = file.replace(".css", "")
+ if css_files_dir.get(file, "") != "":
+ if file.startswith("Q"):
+ css_files_dir[file] = os.path.join(user_files_dir, file+'.css')
+ else:
+ css_files_dir[file] = f"/_addons/{addon_package}/user_files/{file}.css"
diff --git a/.local/share/Anki2/addons21/anki_reworked/utils/logger.py b/.local/share/Anki2/addons21/anki_reworked/utils/logger.py
new file mode 100644
index 0000000..3c67988
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/utils/logger.py
@@ -0,0 +1,17 @@
+import os
+import logging
+# declare an empty logger class
+class EmptyLogger():
+ def debug(self, *_):
+ return None
+logger = EmptyLogger()
+# init logger
+if 'ANKI_REDESIGN_DEBUG_LOGGING' in os.environ:
+ filename = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "user_files", "test.log")
+ logging.basicConfig(format='%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
+ datefmt='%Y%m%d-%H:%M:%S',
+ filename=filename,
+ level=logging.DEBUG)
+ logger = logging.getLogger('anki-redesign')
+ logger.setLevel(logging.DEBUG)
+ logger.debug("Initialized anki")
diff --git a/.local/share/Anki2/addons21/anki_reworked/utils/modules.py b/.local/share/Anki2/addons21/anki_reworked/utils/modules.py
new file mode 100644
index 0000000..fc55a12
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/utils/modules.py
@@ -0,0 +1,18 @@
+def module_exists(module_name):
+ try:
+ __import__(module_name)
+ except ImportError:
+ return False
+ else:
+ return True
+
+def module_has_attribute(module_name, attribute):
+ if module_exists(module_name):
+ return hasattr(__import__(module_name), attribute)
+ return False
+
+def attribute_exists(object, attribute):
+ return attribute in object.__dict__
+
+def context_name_includes(context, classname):
+ return classname in str(context.__class__) \ No newline at end of file
diff --git a/.local/share/Anki2/addons21/anki_reworked/utils/themes.py b/.local/share/Anki2/addons21/anki_reworked/utils/themes.py
new file mode 100644
index 0000000..36af2d9
--- /dev/null
+++ b/.local/share/Anki2/addons21/anki_reworked/utils/themes.py
@@ -0,0 +1,34 @@
+import os
+import json
+from aqt import mw
+from .logger import logger
+
+this_script_dir = os.path.join(os.path.dirname(__file__), "..")
+themes_dir = os.path.join(this_script_dir, 'themes')
+
+def get_themes_dict() -> dict:
+ # Replace pathing for theme files (ReColor compatible)
+ themes = {}
+ for file in os.listdir(themes_dir):
+ if "json" in file:
+ file = file.replace(".json", "")
+ if themes.get(file, "") == "":
+ themes[file] = os.path.join(themes_dir, file+'.json')
+ return themes
+
+def get_theme(theme: str) -> dict:
+ themes_parsed = json.loads(open(themes[theme], encoding='utf-8').read())
+ theme_colors = themes_parsed.get("colors")
+ # Add extra color_keys on theme files if not exist (ReColor compatible)
+ if not theme_colors.get("PRIMARY_COLOR", False):
+ theme_colors["PRIMARY_COLOR"] = ["Primary Color", "#0093d0", "#0093d0", "--primary-color"]
+ if not theme_colors.get("FOCUS_SHADOW", False):
+ theme_colors["FOCUS_SHADOW"] = ["Focus Shadow", "#ff93d0", "#0093d0", "--focus-shadow-color"]
+ themes_parsed["colors"] = theme_colors
+ return themes_parsed
+
+def write_theme(file, theme_content):
+ with open(file, "w") as f:
+ json.dump(theme_content, f, indent=2, sort_keys=True)
+
+themes = get_themes_dict()