mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 15:32:23 -04:00
Generalize ts/graphs/preferences to ts/sveltelib/preferences
This commit is contained in:
parent
b696635afc
commit
13decbe608
10 changed files with 124 additions and 103 deletions
|
@ -4,6 +4,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "anki/backend_proto";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
|
@ -17,11 +18,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import type { HistogramData } from "./histogram-graph";
|
||||
import { gatherData, buildHistogram } from "./added";
|
||||
import type { GraphData } from "./added";
|
||||
import type { PreferenceStore } from "./preferences";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut | null = null;
|
||||
import * as tr from "anki/i18n";
|
||||
export let preferences: PreferenceStore;
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
|
||||
let histogramData = null as HistogramData | null;
|
||||
let tableData: TableDatum[] = [];
|
||||
|
|
|
@ -4,6 +4,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "anki/backend_proto";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
|
@ -15,11 +16,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import { defaultGraphBounds, RevlogRange } from "./graph-helpers";
|
||||
import type { SearchEventMap } from "./graph-helpers";
|
||||
import { gatherData, renderCalendar } from "./calendar";
|
||||
import type { PreferenceStore } from "./preferences";
|
||||
import type { GraphData } from "./calendar";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut | null = null;
|
||||
export let preferences: PreferenceStore | null = null;
|
||||
export let sourceData: pb.BackendProto.GraphsOut;
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
export let revlogRange: RevlogRange;
|
||||
import * as tr from "anki/i18n";
|
||||
export let nightMode: boolean;
|
||||
|
|
|
@ -5,6 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
<script lang="typescript">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import type pb from "anki/backend_proto";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
import InputBox from "./InputBox.svelte";
|
||||
|
@ -13,7 +14,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import type { SearchEventMap } from "./graph-helpers";
|
||||
import { gatherData, renderCards } from "./card-counts";
|
||||
import type { GraphData, TableDatum } from "./card-counts";
|
||||
import type { PreferenceStore } from "./preferences";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut;
|
||||
import * as tr2 from "anki/i18n";
|
||||
|
|
|
@ -4,6 +4,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
-->
|
||||
<script lang="typescript">
|
||||
import type pb from "anki/backend_proto";
|
||||
import * as tr from "anki/i18n";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
|
@ -14,11 +16,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import type { HistogramData } from "./histogram-graph";
|
||||
import { gatherData, prepareData } from "./ease";
|
||||
import type { TableDatum, SearchEventMap } from "./graph-helpers";
|
||||
import type { PreferenceStore } from "./preferences";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut | null = null;
|
||||
import * as tr from "anki/i18n";
|
||||
export let preferences: PreferenceStore;
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
|
||||
const dispatch = createEventDispatcher<SearchEventMap>();
|
||||
|
||||
|
|
|
@ -12,17 +12,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import HistogramGraph from "./HistogramGraph.svelte";
|
||||
import GraphRangeRadios from "./GraphRangeRadios.svelte";
|
||||
import TableData from "./TableData.svelte";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
|
||||
import type { HistogramData } from "./histogram-graph";
|
||||
import { GraphRange, RevlogRange } from "./graph-helpers";
|
||||
import type { TableDatum, SearchEventMap } from "./graph-helpers";
|
||||
import { gatherData, buildHistogram } from "./future-due";
|
||||
import type { GraphData } from "./future-due";
|
||||
import type { PreferenceStore } from "./preferences";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut | null = null;
|
||||
import * as tr from "anki/i18n";
|
||||
export let preferences: PreferenceStore;
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
|
||||
const dispatch = createEventDispatcher<SearchEventMap>();
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import { timeSpan, MONTH } from "anki/time";
|
||||
|
||||
import type pb from "anki/backend_proto";
|
||||
import type { PreferenceStore } from "sveltelib/preferences";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import Graph from "./Graph.svelte";
|
||||
|
@ -21,11 +22,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
} from "./intervals";
|
||||
import type { IntervalGraphData } from "./intervals";
|
||||
import type { TableDatum, SearchEventMap } from "./graph-helpers";
|
||||
import type { PreferenceStore } from "./preferences";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut | null = null;
|
||||
import * as tr from "anki/i18n";
|
||||
export let preferences: PreferenceStore;
|
||||
export let preferences: PreferenceStore<pb.BackendProto.GraphPreferences>;
|
||||
|
||||
const dispatch = createEventDispatcher<SearchEventMap>();
|
||||
|
||||
|
|
|
@ -5,11 +5,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
<script lang="typescript">
|
||||
import type { Writable } from "svelte/store";
|
||||
|
||||
import pb from "anki/backend_proto";
|
||||
|
||||
import useAsync from "sveltelib/async";
|
||||
import useAsyncReactive from "sveltelib/asyncReactive";
|
||||
import { getPreferences } from "sveltelib/preferences";
|
||||
|
||||
import { getGraphData, daysToRevlogRange } from "./graph-helpers";
|
||||
import { getPreferences } from "./preferences";
|
||||
import {
|
||||
getGraphData,
|
||||
getGraphPreferences,
|
||||
setGraphPreferences,
|
||||
daysToRevlogRange,
|
||||
} from "./graph-helpers";
|
||||
|
||||
export let search: Writable<string>;
|
||||
export let days: Writable<number>;
|
||||
|
@ -24,7 +31,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
loading: prefsLoading,
|
||||
error: prefsError,
|
||||
value: prefsValue,
|
||||
} = useAsync(() => getPreferences());
|
||||
} = useAsync(() =>
|
||||
getPreferences(
|
||||
getGraphPreferences,
|
||||
setGraphPreferences,
|
||||
pb.BackendProto.GraphPreferences.toObject.bind(
|
||||
pb.BackendProto.GraphPreferences
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$: revlogRange = daysToRevlogRange($days);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import pb from "anki/backend_proto";
|
||||
import type { Selection } from "d3";
|
||||
import type { PreferencePayload } from "./preferences";
|
||||
import type { PreferencePayload } from "sveltelib/preferences";
|
||||
import { postRequest } from "anki/postrequest";
|
||||
|
||||
export async function getGraphData(
|
||||
|
@ -26,13 +26,13 @@ export async function getGraphPreferences(): Promise<pb.BackendProto.GraphPrefer
|
|||
);
|
||||
}
|
||||
|
||||
export async function setGraphPreferences(prefs: PreferencePayload): Promise<void> {
|
||||
return (async (): Promise<void> => {
|
||||
await postRequest(
|
||||
"/_anki/setGraphPreferences",
|
||||
pb.BackendProto.GraphPreferences.encode(prefs).finish()
|
||||
);
|
||||
})();
|
||||
export async function setGraphPreferences(
|
||||
prefs: PreferencePayload<pb.BackendProto.GraphPreferences>
|
||||
): Promise<void> {
|
||||
await postRequest(
|
||||
"/_anki/setGraphPreferences",
|
||||
pb.BackendProto.GraphPreferences.encode(prefs).finish()
|
||||
);
|
||||
}
|
||||
|
||||
// amount of data to fetch from backend
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
// languageServerHost taken from MIT sources - see below.
|
||||
|
||||
import pb from "anki/backend_proto";
|
||||
import { getGraphPreferences, setGraphPreferences } from "./graph-helpers";
|
||||
import { Writable, writable, get } from "svelte/store";
|
||||
|
||||
export interface CustomStore<T> extends Writable<T> {
|
||||
subscribe: (getter: (value: T) => void) => () => void;
|
||||
set: (value: T) => void;
|
||||
}
|
||||
|
||||
export type PreferenceStore = {
|
||||
[K in keyof Omit<pb.BackendProto.GraphPreferences, "toJSON">]: CustomStore<
|
||||
pb.BackendProto.GraphPreferences[K]
|
||||
>;
|
||||
};
|
||||
|
||||
export type PreferencePayload = {
|
||||
[K in keyof Omit<
|
||||
pb.BackendProto.GraphPreferences,
|
||||
"toJSON"
|
||||
>]: pb.BackendProto.GraphPreferences[K];
|
||||
};
|
||||
|
||||
function createPreference<T>(
|
||||
initialValue: T,
|
||||
savePreferences: () => void
|
||||
): CustomStore<T> {
|
||||
const { subscribe, set, update } = writable(initialValue);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set: (value: T): void => {
|
||||
set(value);
|
||||
savePreferences();
|
||||
},
|
||||
update: (updater: (value: T) => T): void => {
|
||||
update(updater);
|
||||
savePreferences();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function preparePreferences(
|
||||
GraphPreferences: pb.BackendProto.GraphPreferences
|
||||
): PreferenceStore {
|
||||
const preferences: Partial<PreferenceStore> = {};
|
||||
|
||||
function constructPreferences(): PreferencePayload {
|
||||
const payload: Partial<PreferencePayload> = {};
|
||||
|
||||
for (const key in preferences as PreferenceStore) {
|
||||
payload[key] = get(preferences[key]);
|
||||
}
|
||||
|
||||
return payload as PreferencePayload;
|
||||
}
|
||||
|
||||
function savePreferences(): void {
|
||||
setGraphPreferences(constructPreferences());
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(
|
||||
pb.BackendProto.GraphPreferences.toObject(GraphPreferences, {
|
||||
defaults: true,
|
||||
})
|
||||
)) {
|
||||
preferences[key] = createPreference(value, savePreferences);
|
||||
}
|
||||
|
||||
return preferences as PreferenceStore;
|
||||
}
|
||||
|
||||
export async function getPreferences(): Promise<PreferenceStore> {
|
||||
const initialPreferences = await getGraphPreferences();
|
||||
return preparePreferences(initialPreferences);
|
||||
}
|
85
ts/sveltelib/preferences.ts
Normal file
85
ts/sveltelib/preferences.ts
Normal file
|
@ -0,0 +1,85 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
// languageServerHost taken from MIT sources - see below.
|
||||
|
||||
import { Writable, writable, get } from "svelte/store";
|
||||
|
||||
// import pb from "anki/backend_proto";
|
||||
// export async function getGraphPreferences(): Promise<pb.BackendProto.GraphPreferences> {
|
||||
// export async function setGraphPreferences(prefs: PreferencePayload): Promise<void> {
|
||||
// pb.BackendProto.GraphPreferences.toObject(Preferences, {
|
||||
|
||||
export interface CustomStore<T> extends Writable<T> {
|
||||
subscribe: (getter: (value: T) => void) => () => void;
|
||||
set: (value: T) => void;
|
||||
}
|
||||
|
||||
export type PreferenceStore<T> = {
|
||||
[K in keyof Omit<T, "toJSON">]: CustomStore<T[K]>;
|
||||
};
|
||||
|
||||
export type PreferencePayload<T> = {
|
||||
[K in keyof Omit<T, "toJSON">]: T[K];
|
||||
};
|
||||
|
||||
export type PreferenceRaw<T> = {
|
||||
[K in keyof T]: T[K];
|
||||
};
|
||||
|
||||
function createPreference<T>(
|
||||
initialValue: T,
|
||||
savePreferences: () => void
|
||||
): CustomStore<T> {
|
||||
const { subscribe, set, update } = writable(initialValue);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set: (value: T): void => {
|
||||
set(value);
|
||||
savePreferences();
|
||||
},
|
||||
update: (updater: (value: T) => T): void => {
|
||||
update(updater);
|
||||
savePreferences();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function preparePreferences<T>(
|
||||
Preferences: T,
|
||||
setter: (payload: PreferencePayload<T>) => Promise<void>,
|
||||
toObject: (preferences: T, options: { defaults: boolean }) => PreferenceRaw<T>
|
||||
): PreferenceStore<T> {
|
||||
const preferences: Partial<PreferenceStore<T>> = {};
|
||||
|
||||
function constructPreferences(): PreferencePayload<T> {
|
||||
const payload: Partial<PreferencePayload<T>> = {};
|
||||
|
||||
for (const key in preferences as PreferenceStore<T>) {
|
||||
payload[key] = get(preferences[key]);
|
||||
}
|
||||
|
||||
return payload as PreferencePayload<T>;
|
||||
}
|
||||
|
||||
function savePreferences(): void {
|
||||
setter(constructPreferences());
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(
|
||||
toObject(Preferences, { defaults: true })
|
||||
)) {
|
||||
preferences[key] = createPreference(value, savePreferences);
|
||||
}
|
||||
|
||||
return preferences as PreferenceStore<T>;
|
||||
}
|
||||
|
||||
export async function getPreferences<T>(
|
||||
getter: () => Promise<T>,
|
||||
setter: (payload: PreferencePayload<T>) => Promise<void>,
|
||||
toObject: (preferences: T, options: { defaults: boolean }) => PreferenceRaw<T>
|
||||
): Promise<PreferenceStore<T>> {
|
||||
const initialPreferences = await getter();
|
||||
return preparePreferences(initialPreferences, setter, toObject);
|
||||
}
|
Loading…
Reference in a new issue