Merge pull request #1431 from RumovZ/non-modal-card-info
Non modal card info
This commit is contained in:
commit
5eb1208714
@ -22,3 +22,9 @@ card-stats-review-log-type-review = Review
|
||||
card-stats-review-log-type-relearn = Relearn
|
||||
card-stats-review-log-type-filtered = Filtered
|
||||
card-stats-review-log-type-manual = Manual
|
||||
card-stats-no-card = (No card to display.)
|
||||
|
||||
## Window Titles
|
||||
|
||||
card-stats-current-card = Current Card ({ $context })
|
||||
card-stats-previous-card = Previous Card ({ $context })
|
||||
|
@ -28,6 +28,7 @@ def _legacy_card_stats(
|
||||
) -> str:
|
||||
"A quick hack to preserve compatibility with the old HTML string API."
|
||||
random_id = f"cardinfo-{base62(random.randint(0, 2 ** 64 - 1))}"
|
||||
varName = random_id.replace("-", "")
|
||||
return f"""
|
||||
<div id="{random_id}"></div>
|
||||
<script src="js/vendor/bootstrap.bundle.min.js"></script>
|
||||
@ -38,7 +39,8 @@ def _legacy_card_stats(
|
||||
if ({1 if _legacy_nightmode else 0}) {{
|
||||
document.documentElement.className = "night-mode";
|
||||
}}
|
||||
anki.cardInfo(document.getElementById('{random_id}'), {card_id}, {include_revlog});
|
||||
const {varName} = anki.cardInfo(document.getElementById('{random_id}'));
|
||||
{varName}.then((c) => c.$set({{ cardId: {card_id}, includeRevlog: {str(include_revlog).lower()} }}));
|
||||
</script>
|
||||
"""
|
||||
|
||||
|
@ -58,7 +58,7 @@ from aqt.utils import (
|
||||
)
|
||||
|
||||
from ..changenotetype import change_notetype_dialog
|
||||
from .card_info import CardInfoDialog
|
||||
from .card_info import BrowserCardInfo
|
||||
from .find_and_replace import FindAndReplaceDialog
|
||||
from .previewer import BrowserPreviewer as PreviewDialog
|
||||
from .previewer import Previewer
|
||||
@ -110,6 +110,7 @@ class Browser(QMainWindow):
|
||||
self.lastFilter = ""
|
||||
self.focusTo: int | None = None
|
||||
self._previewer: Previewer | None = None
|
||||
self._card_info = BrowserCardInfo(self.mw)
|
||||
self._closeEventHasCleanedUp = False
|
||||
self.form = aqt.forms.browser.Ui_Dialog()
|
||||
self.form.setupUi(self)
|
||||
@ -155,6 +156,7 @@ class Browser(QMainWindow):
|
||||
if changes.browser_table and changes.card:
|
||||
self.card = self.table.get_single_selected_card()
|
||||
self.current_card = self.table.get_current_card()
|
||||
self._update_card_info()
|
||||
self._update_current_actions()
|
||||
|
||||
# changes.card is required for updating flag icon
|
||||
@ -236,6 +238,7 @@ class Browser(QMainWindow):
|
||||
|
||||
def _closeWindow(self) -> None:
|
||||
self._cleanup_preview()
|
||||
self._card_info.close()
|
||||
self.editor.cleanup()
|
||||
self.table.cleanup()
|
||||
self.sidebar.cleanup()
|
||||
@ -447,6 +450,7 @@ class Browser(QMainWindow):
|
||||
return
|
||||
self.current_card = self.table.get_current_card()
|
||||
self._update_current_actions()
|
||||
self._update_card_info()
|
||||
|
||||
def _update_row_actions(self) -> None:
|
||||
has_rows = bool(self.table.len())
|
||||
@ -545,10 +549,10 @@ class Browser(QMainWindow):
|
||||
######################################################################
|
||||
|
||||
def showCardInfo(self) -> None:
|
||||
if not self.current_card:
|
||||
return
|
||||
self._card_info.toggle()
|
||||
|
||||
CardInfoDialog(parent=self, mw=self.mw, card=self.current_card)
|
||||
def _update_card_info(self) -> None:
|
||||
self._card_info.set_card(self.current_card)
|
||||
|
||||
# Menu helpers
|
||||
######################################################################
|
||||
|
@ -3,8 +3,12 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Callable
|
||||
|
||||
import aqt
|
||||
from anki.cards import Card, CardId
|
||||
from anki.lang import without_unicode_isolation
|
||||
from aqt.qt import *
|
||||
from aqt.utils import (
|
||||
addCloseShortcut,
|
||||
@ -12,6 +16,8 @@ from aqt.utils import (
|
||||
qconnect,
|
||||
restoreGeom,
|
||||
saveGeom,
|
||||
setWindowIcon,
|
||||
tr,
|
||||
)
|
||||
from aqt.webview import AnkiWebView
|
||||
|
||||
@ -21,18 +27,30 @@ class CardInfoDialog(QDialog):
|
||||
GEOMETRY_KEY = "revlog"
|
||||
silentlyClose = True
|
||||
|
||||
def __init__(self, parent: QWidget, mw: aqt.AnkiQt, card: Card) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
parent: QWidget | None,
|
||||
mw: aqt.AnkiQt,
|
||||
card: Card | None,
|
||||
on_close: Callable | None = None,
|
||||
geometry_key: str | None = None,
|
||||
window_title: str | None = None,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
self.mw = mw
|
||||
self._setup_ui(card.id)
|
||||
self._on_close = on_close
|
||||
self.GEOMETRY_KEY = geometry_key or self.GEOMETRY_KEY
|
||||
if window_title:
|
||||
self.setWindowTitle(window_title)
|
||||
self._setup_ui(card.id if card else None)
|
||||
self.show()
|
||||
|
||||
def _setup_ui(self, card_id: CardId) -> None:
|
||||
self.setWindowModality(Qt.WindowModality.ApplicationModal)
|
||||
def _setup_ui(self, card_id: CardId | None) -> None:
|
||||
self.mw.garbage_collect_on_dialog_finish(self)
|
||||
disable_help_button(self)
|
||||
restoreGeom(self, self.GEOMETRY_KEY)
|
||||
addCloseShortcut(self)
|
||||
setWindowIcon(self)
|
||||
|
||||
self.web = AnkiWebView(title=self.TITLE)
|
||||
self.web.setVisible(False)
|
||||
@ -47,10 +65,87 @@ class CardInfoDialog(QDialog):
|
||||
self.setLayout(layout)
|
||||
|
||||
self.web.eval(
|
||||
f"anki.cardInfo(document.getElementById('main'), {card_id}, true);"
|
||||
"const cardInfo = anki.cardInfo(document.getElementById('main'));"
|
||||
)
|
||||
self.update_card(card_id)
|
||||
|
||||
def update_card(self, card_id: CardId | None) -> None:
|
||||
self.web.eval(
|
||||
f"cardInfo.then((c) => c.$set({{ cardId: {json.dumps(card_id)} }}));"
|
||||
)
|
||||
|
||||
def reject(self) -> None:
|
||||
if self._on_close:
|
||||
self._on_close()
|
||||
self.web = None
|
||||
saveGeom(self, self.GEOMETRY_KEY)
|
||||
return QDialog.reject(self)
|
||||
|
||||
|
||||
class CardInfoManager:
|
||||
"""Wrapper class to conveniently toggle, update and close a card info dialog."""
|
||||
|
||||
def __init__(self, mw: aqt.AnkiQt, geometry_key: str, window_title: str):
|
||||
self.mw = mw
|
||||
self.geometry_key = geometry_key
|
||||
self.window_title = window_title
|
||||
self._card: Card | None = None
|
||||
self._dialog: CardInfoDialog | None = None
|
||||
|
||||
def toggle(self) -> None:
|
||||
if self._dialog:
|
||||
self._dialog.reject()
|
||||
else:
|
||||
self._dialog = CardInfoDialog(
|
||||
None,
|
||||
self.mw,
|
||||
self._card,
|
||||
self._on_close,
|
||||
self.geometry_key,
|
||||
self.window_title,
|
||||
)
|
||||
|
||||
def set_card(self, card: Card | None) -> None:
|
||||
self._card = card
|
||||
if self._dialog:
|
||||
self._dialog.update_card(card.id if card else None)
|
||||
|
||||
def close(self) -> None:
|
||||
if self._dialog:
|
||||
self.toggle()
|
||||
|
||||
def _on_close(self) -> None:
|
||||
self._dialog = None
|
||||
|
||||
|
||||
class BrowserCardInfo(CardInfoManager):
|
||||
def __init__(self, mw: aqt.AnkiQt):
|
||||
super().__init__(
|
||||
mw,
|
||||
"revlog",
|
||||
without_unicode_isolation(
|
||||
tr.card_stats_current_card(context=tr.qt_misc_browse())
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class ReviewerCardInfo(CardInfoManager):
|
||||
def __init__(self, mw: aqt.AnkiQt):
|
||||
super().__init__(
|
||||
mw,
|
||||
"reviewerCardInfo",
|
||||
without_unicode_isolation(
|
||||
tr.card_stats_current_card(context=tr.decks_study())
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class PreviousReviewerCardInfo(CardInfoManager):
|
||||
def __init__(self, mw: aqt.AnkiQt):
|
||||
super().__init__(
|
||||
mw,
|
||||
"previousReviewerCardInfo",
|
||||
without_unicode_isolation(
|
||||
tr.card_stats_previous_card(context=tr.decks_study())
|
||||
),
|
||||
)
|
||||
|
@ -17,9 +17,7 @@ from aqt.qt import (
|
||||
QCheckBox,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QIcon,
|
||||
QKeySequence,
|
||||
QPixmap,
|
||||
QShortcut,
|
||||
Qt,
|
||||
QTimer,
|
||||
@ -30,7 +28,7 @@ from aqt.qt import (
|
||||
from aqt.reviewer import replay_audio
|
||||
from aqt.sound import av_player, play_clicked_audio
|
||||
from aqt.theme import theme_manager
|
||||
from aqt.utils import disable_help_button, restoreGeom, saveGeom, tr
|
||||
from aqt.utils import disable_help_button, restoreGeom, saveGeom, setWindowIcon, tr
|
||||
from aqt.webview import AnkiWebView
|
||||
|
||||
LastStateAndMod = tuple[str, int, int]
|
||||
@ -52,10 +50,8 @@ class Previewer(QDialog):
|
||||
self._parent = parent
|
||||
self._close_callback = on_close
|
||||
self.mw = mw
|
||||
icon = QIcon()
|
||||
icon.addPixmap(QPixmap("icons:anki.png"), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
disable_help_button(self)
|
||||
self.setWindowIcon(icon)
|
||||
setWindowIcon(self)
|
||||
|
||||
def card(self) -> Card | None:
|
||||
raise NotImplementedError
|
||||
|
@ -21,7 +21,7 @@ from anki.scheduler.v3 import Scheduler as V3Scheduler
|
||||
from anki.tags import MARKED_TAG
|
||||
from anki.utils import stripHTML
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.browser.card_info import CardInfoDialog
|
||||
from aqt.browser.card_info import PreviousReviewerCardInfo, ReviewerCardInfo
|
||||
from aqt.deckoptions import confirm_deck_then_display_options
|
||||
from aqt.operations.card import set_card_flag
|
||||
from aqt.operations.note import remove_notes
|
||||
@ -126,6 +126,8 @@ class Reviewer:
|
||||
self._v3: V3CardInfo | None = None
|
||||
self._state_mutation_key = str(random.randint(0, 2 ** 64 - 1))
|
||||
self.bottom = BottomBar(mw, mw.bottomWeb)
|
||||
self._card_info = ReviewerCardInfo(self.mw)
|
||||
self._previous_card_info = PreviousReviewerCardInfo(self.mw)
|
||||
hooks.card_did_leech.append(self.onLeech)
|
||||
|
||||
def show(self) -> None:
|
||||
@ -197,6 +199,9 @@ class Reviewer:
|
||||
else:
|
||||
self._get_next_v3_card()
|
||||
|
||||
self._previous_card_info.set_card(self.previous_card)
|
||||
self._card_info.set_card(self.card)
|
||||
|
||||
if not self.card:
|
||||
self.mw.moveToState("overview")
|
||||
return
|
||||
@ -958,12 +963,10 @@ time = %(time)d;
|
||||
confirm_deck_then_display_options(self.card)
|
||||
|
||||
def on_previous_card_info(self) -> None:
|
||||
if self.previous_card:
|
||||
CardInfoDialog(parent=self.mw, mw=self.mw, card=self.previous_card)
|
||||
self._previous_card_info.toggle()
|
||||
|
||||
def on_card_info(self) -> None:
|
||||
if self.card:
|
||||
CardInfoDialog(parent=self.mw, mw=self.mw, card=self.card)
|
||||
self._card_info.toggle()
|
||||
|
||||
def set_flag_on_current_card(self, desired_flag: int) -> None:
|
||||
def redraw_flag(out: OpChangesWithCount) -> None:
|
||||
|
@ -406,6 +406,12 @@ def disable_help_button(widget: QWidget) -> None:
|
||||
)
|
||||
|
||||
|
||||
def setWindowIcon(widget: QWidget) -> None:
|
||||
icon = QIcon()
|
||||
icon.addPixmap(QPixmap("icons:anki.png"), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
widget.setWindowIcon(icon)
|
||||
|
||||
|
||||
# File handling
|
||||
######################################################################
|
||||
|
||||
|
@ -3,108 +3,53 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import * as tr2 from "../lib/ftl";
|
||||
import { Stats, unwrapOptionalNumber } from "../lib/proto";
|
||||
import { Timestamp, timeSpan, DAY } from "../lib/time";
|
||||
import * as tr from "../lib/ftl";
|
||||
import type { Stats } from "../lib/proto";
|
||||
import { getCardStats } from "./lib";
|
||||
import CardStats from "./CardStats.svelte";
|
||||
import Revlog from "./Revlog.svelte";
|
||||
|
||||
export let stats: Stats.CardStatsResponse;
|
||||
export let cardId: number | null = null;
|
||||
export let includeRevlog: boolean = true;
|
||||
|
||||
function dateString(timestamp: number): string {
|
||||
return new Timestamp(timestamp).dateString();
|
||||
}
|
||||
let stats: Stats.CardStatsResponse | null = null;
|
||||
|
||||
interface StatsRow {
|
||||
label: string;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
const statsRows: StatsRow[] = [];
|
||||
|
||||
statsRows.push({ label: tr2.cardStatsAdded(), value: dateString(stats.added) });
|
||||
|
||||
const firstReview = unwrapOptionalNumber(stats.firstReview);
|
||||
if (firstReview !== undefined) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsFirstReview(),
|
||||
value: dateString(firstReview),
|
||||
$: if (cardId === null) {
|
||||
stats = null;
|
||||
} else {
|
||||
const requestedCardId = cardId;
|
||||
getCardStats(requestedCardId).then((s) => {
|
||||
/* Skip if another update has been triggered in the meantime. */
|
||||
if (requestedCardId === cardId) {
|
||||
stats = s;
|
||||
}
|
||||
});
|
||||
}
|
||||
const latestReview = unwrapOptionalNumber(stats.latestReview);
|
||||
if (latestReview !== undefined) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsLatestReview(),
|
||||
value: dateString(latestReview),
|
||||
});
|
||||
}
|
||||
|
||||
const dueDate = unwrapOptionalNumber(stats.dueDate);
|
||||
if (dueDate !== undefined) {
|
||||
statsRows.push({ label: tr2.statisticsDueDate(), value: dateString(dueDate) });
|
||||
}
|
||||
const duePosition = unwrapOptionalNumber(stats.duePosition);
|
||||
if (duePosition !== undefined) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsNewCardPosition(),
|
||||
value: dateString(duePosition),
|
||||
});
|
||||
}
|
||||
|
||||
if (stats.interval) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsInterval(),
|
||||
value: timeSpan(stats.interval * DAY),
|
||||
});
|
||||
}
|
||||
if (stats.ease) {
|
||||
statsRows.push({ label: tr2.cardStatsEase(), value: `${stats.ease / 10}%` });
|
||||
}
|
||||
|
||||
statsRows.push({ label: tr2.cardStatsReviewCount(), value: stats.reviews });
|
||||
statsRows.push({ label: tr2.cardStatsLapseCount(), value: stats.lapses });
|
||||
|
||||
if (stats.totalSecs) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsAverageTime(),
|
||||
value: timeSpan(stats.averageSecs),
|
||||
});
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsTotalTime(),
|
||||
value: timeSpan(stats.totalSecs),
|
||||
});
|
||||
}
|
||||
|
||||
statsRows.push({ label: tr2.cardStatsCardTemplate(), value: stats.cardType });
|
||||
statsRows.push({ label: tr2.cardStatsNoteType(), value: stats.notetype });
|
||||
statsRows.push({ label: tr2.cardStatsDeckName(), value: stats.deck });
|
||||
|
||||
statsRows.push({ label: tr2.cardStatsCardId(), value: stats.cardId });
|
||||
statsRows.push({ label: tr2.cardStatsNoteId(), value: stats.noteId });
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<div>
|
||||
<table class="stats-table">
|
||||
{#each statsRows as row, _index}
|
||||
<tr>
|
||||
<th style="text-align:start">{row.label}</th>
|
||||
<td>{row.value}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
<Revlog {stats} />
|
||||
{#if stats !== null}
|
||||
<div class="container">
|
||||
<div>
|
||||
<CardStats {stats} />
|
||||
{#if includeRevlog}
|
||||
<Revlog {stats} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="placeholder">{tr.cardStatsNoCard()}</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.container {
|
||||
max-width: 40em;
|
||||
}
|
||||
|
||||
.stats-table {
|
||||
width: 100%;
|
||||
border-spacing: 1em 0;
|
||||
border-collapse: collapse;
|
||||
text-align: start;
|
||||
.placeholder {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
</style>
|
||||
|
113
ts/card-info/CardStats.svelte
Normal file
113
ts/card-info/CardStats.svelte
Normal file
@ -0,0 +1,113 @@
|
||||
<!--
|
||||
Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import * as tr2 from "../lib/ftl";
|
||||
import { Stats, unwrapOptionalNumber } from "../lib/proto";
|
||||
import { Timestamp, timeSpan, DAY } from "../lib/time";
|
||||
|
||||
export let stats: Stats.CardStatsResponse;
|
||||
|
||||
function dateString(timestamp: number): string {
|
||||
return new Timestamp(timestamp).dateString();
|
||||
}
|
||||
|
||||
interface StatsRow {
|
||||
label: string;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
function rowsFromStats(stats: Stats.CardStatsResponse): StatsRow[] {
|
||||
const statsRows: StatsRow[] = [];
|
||||
|
||||
statsRows.push({ label: tr2.cardStatsAdded(), value: dateString(stats.added) });
|
||||
|
||||
const firstReview = unwrapOptionalNumber(stats.firstReview);
|
||||
if (firstReview !== undefined) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsFirstReview(),
|
||||
value: dateString(firstReview),
|
||||
});
|
||||
}
|
||||
const latestReview = unwrapOptionalNumber(stats.latestReview);
|
||||
if (latestReview !== undefined) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsLatestReview(),
|
||||
value: dateString(latestReview),
|
||||
});
|
||||
}
|
||||
|
||||
const dueDate = unwrapOptionalNumber(stats.dueDate);
|
||||
if (dueDate !== undefined) {
|
||||
statsRows.push({
|
||||
label: tr2.statisticsDueDate(),
|
||||
value: dateString(dueDate),
|
||||
});
|
||||
}
|
||||
const duePosition = unwrapOptionalNumber(stats.duePosition);
|
||||
if (duePosition !== undefined) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsNewCardPosition(),
|
||||
value: dateString(duePosition),
|
||||
});
|
||||
}
|
||||
|
||||
if (stats.interval) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsInterval(),
|
||||
value: timeSpan(stats.interval * DAY),
|
||||
});
|
||||
}
|
||||
if (stats.ease) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsEase(),
|
||||
value: `${stats.ease / 10}%`,
|
||||
});
|
||||
}
|
||||
|
||||
statsRows.push({ label: tr2.cardStatsReviewCount(), value: stats.reviews });
|
||||
statsRows.push({ label: tr2.cardStatsLapseCount(), value: stats.lapses });
|
||||
|
||||
if (stats.totalSecs) {
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsAverageTime(),
|
||||
value: timeSpan(stats.averageSecs),
|
||||
});
|
||||
statsRows.push({
|
||||
label: tr2.cardStatsTotalTime(),
|
||||
value: timeSpan(stats.totalSecs),
|
||||
});
|
||||
}
|
||||
|
||||
statsRows.push({ label: tr2.cardStatsCardTemplate(), value: stats.cardType });
|
||||
statsRows.push({ label: tr2.cardStatsNoteType(), value: stats.notetype });
|
||||
statsRows.push({ label: tr2.cardStatsDeckName(), value: stats.deck });
|
||||
|
||||
statsRows.push({ label: tr2.cardStatsCardId(), value: stats.cardId });
|
||||
statsRows.push({ label: tr2.cardStatsNoteId(), value: stats.noteId });
|
||||
|
||||
return statsRows;
|
||||
}
|
||||
|
||||
let statsRows: StatsRow[];
|
||||
$: statsRows = rowsFromStats(stats);
|
||||
</script>
|
||||
|
||||
<table class="stats-table">
|
||||
{#each statsRows as row, _index}
|
||||
<tr>
|
||||
<th style="text-align:start">{row.label}</th>
|
||||
<td>{row.value}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
|
||||
<style>
|
||||
.stats-table {
|
||||
width: 100%;
|
||||
border-spacing: 1em 0;
|
||||
border-collapse: collapse;
|
||||
text-align: start;
|
||||
}
|
||||
</style>
|
@ -72,9 +72,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
};
|
||||
}
|
||||
|
||||
const revlogRows: RevlogRow[] = stats.revlog.map((entry) =>
|
||||
revlogRowFromEntry(entry)
|
||||
);
|
||||
let revlogRows: RevlogRow[];
|
||||
$: revlogRows = stats.revlog.map((entry) => revlogRowFromEntry(entry));
|
||||
</script>
|
||||
|
||||
{#if stats.revlog.length}
|
||||
|
@ -1,33 +1,15 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import { getCardStats } from "./lib";
|
||||
import { setupI18n, ModuleName } from "../lib/i18n";
|
||||
import { checkNightMode } from "../lib/nightmode";
|
||||
|
||||
import CardInfo from "./CardInfo.svelte";
|
||||
|
||||
export async function cardInfo(
|
||||
target: HTMLDivElement,
|
||||
cardId: number,
|
||||
includeRevlog: boolean
|
||||
): Promise<CardInfo> {
|
||||
export async function cardInfo(target: HTMLDivElement): Promise<CardInfo> {
|
||||
checkNightMode();
|
||||
const [stats] = await Promise.all([
|
||||
getCardStats(cardId),
|
||||
setupI18n({
|
||||
modules: [
|
||||
ModuleName.CARD_STATS,
|
||||
ModuleName.SCHEDULING,
|
||||
ModuleName.STATISTICS,
|
||||
],
|
||||
}),
|
||||
]);
|
||||
if (!includeRevlog) {
|
||||
stats.revlog = [];
|
||||
}
|
||||
return new CardInfo({
|
||||
target,
|
||||
props: { stats },
|
||||
await setupI18n({
|
||||
modules: [ModuleName.CARD_STATS, ModuleName.SCHEDULING, ModuleName.STATISTICS],
|
||||
});
|
||||
return new CardInfo({ target });
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user