mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
graphs now work in night mode
This commit is contained in:
parent
1b37398503
commit
101deb002b
13 changed files with 88 additions and 20 deletions
|
@ -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
2
ts/css.d.ts
vendored
|
@ -1 +1 @@
|
|||
declare module "*.css";
|
||||
declare module "*.scss";
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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} />
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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) =>
|
||||
|
|
|
@ -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)$/,
|
||||
|
|
Loading…
Reference in a new issue