graphs now work in night mode

This commit is contained in:
Damien Elmes 2020-06-30 16:23:46 +10:00
parent 1b37398503
commit 101deb002b
13 changed files with 88 additions and 20 deletions

View file

@ -9,6 +9,7 @@ import time
import aqt
from anki.lang import _
from aqt.qt import *
from aqt.theme import theme_manager
from aqt.utils import (
addCloseShortcut,
getSaveFile,
@ -87,4 +88,8 @@ class DeckStats(QDialog):
def refresh(self):
self.form.web.set_open_links_externally(False)
self.form.web.load(QUrl(f"{self.mw.serverURL()}_anki/graphs.html"))
if theme_manager.night_mode:
extra = "#night"
else:
extra = ""
self.form.web.load(QUrl(f"{self.mw.serverURL()}_anki/graphs.html"+extra))

2
ts/css.d.ts vendored
View file

@ -1 +1 @@
declare module "*.css";
declare module "*.scss";

View file

@ -31,6 +31,7 @@
"prettier": "^2.0.0",
"prettier-plugin-svelte": "^1.1.0",
"sass": "^1.26.9",
"sass-loader": "^8.0.2",
"style-loader": "^1.2.1",
"svelte": "^3.23.2",
"svelte-loader": "^2.13.6",

View file

@ -8,6 +8,10 @@
<div id="main"></div>
</body>
<script>
anki.graphs(document.getElementById("main"));
const nightMode = window.location.hash == "#night";
if (nightMode) {
document.body.className = "night-mode";
}
anki.graphs(document.getElementById("main"), nightMode);
</script>
</html>

View file

@ -11,6 +11,7 @@
export let sourceData: pb.BackendProto.GraphsOut | null = null;
export let revlogRange: RevlogRange = RevlogRange.Month;
export let i18n: I18n;
export let nightMode: boolean;
let graphData: GraphData | null = null;
@ -42,7 +43,14 @@
}
$: if (graphData) {
renderCalendar(svg as SVGElement, bounds, graphData, targetYear, i18n);
renderCalendar(
svg as SVGElement,
bounds,
graphData,
targetYear,
i18n,
nightMode
);
}
const title = i18n.tr(i18n.TR.STATISTICS_REVIEWS_TITLE);

View file

@ -1,5 +1,5 @@
<script context="module">
import style from "./graphs.css";
import style from "./graphs.scss";
</script>
<script lang="typescript">
@ -20,6 +20,7 @@
import CalendarGraph from "./CalendarGraph.svelte";
export let i18n: I18n;
export let nightMode: boolean;
let sourceData: pb.BackendProto.GraphsOut | null = null;
@ -142,7 +143,7 @@
<TodayStats {sourceData} {i18n} />
<CardCounts {sourceData} {i18n} />
<CalendarGraph {sourceData} {revlogRange} {i18n} />
<CalendarGraph {sourceData} {revlogRange} {i18n} {nightMode} />
<FutureDue {sourceData} {revlogRange} {i18n} />
<ReviewsGraph {sourceData} {revlogRange} {i18n} />
<IntervalsGraph {sourceData} {i18n} />

View file

@ -154,9 +154,9 @@ export function renderButtons(
.attr("opacity", (d: Datum) => {
switch (d.group) {
case "learning":
return 0.3;
return 0.6;
case "young":
return 0.5;
return 0.8;
case "mature":
return 1;
}

View file

@ -53,7 +53,8 @@ export function renderCalendar(
bounds: GraphBounds,
sourceData: GraphData,
targetYear: number,
i18n: I18n
i18n: I18n,
nightMode: boolean
): void {
const svg = select(svgElem);
const now = new Date();
@ -101,7 +102,11 @@ export function renderCalendar(
}
}
const data = Array.from(dayMap.values());
const blues = scaleSequential(interpolateBlues).domain([0, maxCount]);
const cappedRange = scaleLinear().range([0.2, nightMode ? 0.8 : 1]);
const blues = scaleSequential((n) => interpolateBlues(cappedRange(n))).domain([
0,
maxCount,
]);
function tooltipText(d: DayDatum): string {
const date = d.date.toLocaleString(i18n.langs, {
@ -115,6 +120,10 @@ export function renderCalendar(
}
const height = bounds.height / 10;
let emptyColour = "#eee";
if (nightMode) {
emptyColour = "#333";
}
svg.select(`g.days`)
.selectAll("rect")
.data(data)
@ -132,7 +141,7 @@ export function renderCalendar(
.on("mouseout", hideTooltip)
.attr("fill", (d) => {
if (d.count === 0) {
return "#eee";
return emptyColour;
} else {
return blues(d.count);
}

View file

@ -4,11 +4,11 @@
import { setupI18n } from "../i18n";
import GraphsPage from "./GraphsPage.svelte";
export function graphs(target: HTMLDivElement): void {
export function graphs(target: HTMLDivElement, nightMode: boolean): void {
setupI18n().then((i18n) => {
new GraphsPage({
target,
props: { i18n },
props: { i18n, nightMode },
});
});
}

View file

@ -1,9 +1,16 @@
$day-fg: black;
$day-bg: white;
$night-fg: white;
$night-bg: #222;
* {
box-sizing: border-box;
}
body {
font-family: Arial;
background: $day-bg;
color: $day-fg;
}
.graph-tooltip {
@ -15,7 +22,8 @@ body {
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
background: #fff;
color: $day-fg;
background: $day-bg;
}
.graph {
@ -37,7 +45,8 @@ body {
top: 0;
width: 100%;
height: 4em;
background: white;
color: $day-fg;
background: $day-bg;
padding: 0.5em;
}
@ -57,7 +66,7 @@ body {
.graph .area {
opacity: 0.05;
pointer-events: none;
fill: black;
fill: $day-fg;
}
.axis-label {
@ -110,3 +119,23 @@ body {
.subtitle {
text-align: center;
}
body.night-mode {
background: $night-bg;
color: $night-fg;
}
.night-mode {
.graph-tooltip {
background: $night-bg;
color: $night-fg;
}
.range-box {
background: $night-bg;
color: $night-fg;
}
.graph .area {
fill: $night-fg;
opacity: 0.1;
}
}

View file

@ -40,6 +40,13 @@ export enum RevlogRange {
All = 3,
}
export interface GraphsContext {
cards: pb.BackendProto.Card[];
revlog: pb.BackendProto.RevlogEntry[];
revlogRange: RevlogRange;
nightMode: boolean;
}
export interface GraphBounds {
width: number;
height: number;

View file

@ -74,7 +74,11 @@ export function renderHours(
.transition(trans)
.call(axisBottom(x).tickSizeOuter(0));
const colour = scaleSequential(interpolateBlues).domain([0, yMax]);
const cappedRange = scaleLinear().range([0.1, 0.8]);
const colour = scaleSequential((n) => interpolateBlues(cappedRange(n))).domain([
0,
yMax,
]);
// y scale
@ -114,7 +118,7 @@ export function renderHours(
.attr("x", (d: Hour) => x(d.hour.toString())!)
.attr("y", y(0))
.attr("height", 0)
.attr("opacity", 0.7)
// .attr("opacity", 0.7)
.call(updateBar),
(update) => update.call(updateBar),
(remove) =>

View file

@ -41,8 +41,8 @@ module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
test: /\.s?css$/i,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.(svelte)$/,