diff --git a/anki/utils.py b/anki/utils.py
index 7e534c994..b01fc1b90 100644
--- a/anki/utils.py
+++ b/anki/utils.py
@@ -188,6 +188,12 @@ def entsToTxt(html):
return text # leave as is
return reEnts.sub(fixup, html)
+def bodyClass(col, card):
+ bodyclass = "card card%d" % (card.ord+1)
+ if col.conf.get("nightMode"):
+ bodyclass += " nightMode"
+ return bodyclass
+
# IDs
##############################################################################
diff --git a/aqt/browser.py b/aqt/browser.py
index 9778abdf5..369b929b8 100644
--- a/aqt/browser.py
+++ b/aqt/browser.py
@@ -13,8 +13,9 @@ import json
from aqt.qt import *
import anki
import aqt.forms
-from anki.utils import fmtTimeSpan, ids2str, stripHTMLMedia, htmlToTextLine, isWin, intTime,\
- isMac, isLin
+from anki.utils import fmtTimeSpan, ids2str, stripHTMLMedia, htmlToTextLine, \
+ isWin, intTime, \
+ isMac, isLin, bodyClass
from aqt.utils import saveGeom, restoreGeom, saveSplitter, restoreSplitter, \
saveHeader, restoreHeader, saveState, restoreState, applyStyles, getTag, \
showInfo, askUser, tooltip, openHelp, showWarning, shortcut, mungeQA, \
@@ -1347,7 +1348,7 @@ where id in %s""" % ids2str(sf))
txt = c.a()
txt = re.sub("\[\[type:[^]]+\]\]", "", txt)
- bodyclass="card card%d" % (c.ord+1)
+ bodyclass = bodyClass(self.mw.col, c)
clearAudioQueue()
if self.mw.reviewer.autoplay(c):
diff --git a/aqt/clayout.py b/aqt/clayout.py
index 7be98f7b5..da6e24375 100644
--- a/aqt/clayout.py
+++ b/aqt/clayout.py
@@ -12,7 +12,7 @@ from anki.sound import playFromText, clearAudioQueue
from aqt.utils import saveGeom, restoreGeom, mungeQA,\
showInfo, askUser, getOnlyText, \
showWarning, openHelp, downArrow
-from anki.utils import isMac, isWin, joinFields
+from anki.utils import isMac, isWin, joinFields, bodyClass
from aqt.webview import AnkiWebView
import json
from anki.hooks import runFilter
@@ -297,7 +297,8 @@ Please create a new card type first."""))
c = self.card
ti = self.maybeTextInput
- bodyclass="card card%d" % (c.ord+1)
+
+ bodyclass = bodyClass(self.mw.col, c)
q = ti(mungeQA(self.mw.col, c.q(reload=True)))
q = runFilter("prepareQA", q, c, "clayoutQuestion")
diff --git a/aqt/preferences.py b/aqt/preferences.py
index b08f37058..1fbf5f3f2 100644
--- a/aqt/preferences.py
+++ b/aqt/preferences.py
@@ -80,6 +80,7 @@ class Preferences(QDialog):
f.timeLimit.setValue(qc['timeLim']/60.0)
f.showEstimates.setChecked(qc['estTimes'])
f.showProgress.setChecked(qc['dueCounts'])
+ f.nightMode.setChecked(qc.get("nightMode", False))
f.newSpread.addItems(list(c.newCardSchedulingLabels().values()))
f.newSpread.setCurrentIndex(qc['newSpread'])
f.useCurrent.setCurrentIndex(int(not qc.get("addToCur", True)))
@@ -91,6 +92,7 @@ class Preferences(QDialog):
qc['dueCounts'] = f.showProgress.isChecked()
qc['estTimes'] = f.showEstimates.isChecked()
qc['newSpread'] = f.newSpread.currentIndex()
+ qc['nightMode'] = f.nightMode.isChecked()
qc['timeLim'] = f.timeLimit.value()*60
qc['collapseTime'] = f.lrnCutoff.value()*60
qc['addToCur'] = not f.useCurrent.currentIndex()
diff --git a/aqt/reviewer.py b/aqt/reviewer.py
index f87b1be57..300300f42 100644
--- a/aqt/reviewer.py
+++ b/aqt/reviewer.py
@@ -10,7 +10,7 @@ import html.parser
from anki.lang import _, ngettext
from aqt.qt import *
-from anki.utils import stripHTML, json
+from anki.utils import stripHTML, json, bodyClass
from anki.hooks import addHook, runHook, runFilter
from anki.sound import playFromText, clearAudioQueue, play
from aqt.utils import mungeQA, tooltip, askUserDialog, \
@@ -167,7 +167,7 @@ The front of this card is empty. Please run Tools>Empty Cards.""")
q = self._mungeQA(q)
q = runFilter("prepareQA", q, c, "reviewQuestion")
- bodyclass = "card card%d" % (c.ord+1)
+ bodyclass = bodyClass(self.mw.col, c)
self.web.eval("_showQuestion(%s,'%s');" % (json.dumps(q), bodyclass))
self._drawFlag()
diff --git a/designer/preferences.ui b/designer/preferences.ui
index 5a9f8f5b0..7efd5e8bd 100644
--- a/designer/preferences.ui
+++ b/designer/preferences.ui
@@ -78,6 +78,13 @@
+ -
+
+
+ Show cards as white on black (night mode)
+
+
+
-
-
@@ -429,6 +436,7 @@
showEstimates
showProgress
pastePNG
+ nightMode
useCurrent
newSpread
dayOffset
diff --git a/web/reviewer.css b/web/reviewer.css
index 738de242d..6ddf431fc 100644
--- a/web/reviewer.css
+++ b/web/reviewer.css
@@ -8,6 +8,11 @@ body {
overflow-wrap: break-word;
}
+body.nightMode {
+ background-color: black;
+ color: white;
+}
+
img {
max-width: 95%;
max-height: 95%;