From f82a02bd2e35ffdb1833d20469f58a1afcb4d72a Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 21 Mar 2021 19:43:59 +0100 Subject: [PATCH 01/24] Add Svelte async hook --- ts/graphs/async.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 ts/graphs/async.ts diff --git a/ts/graphs/async.ts b/ts/graphs/async.ts new file mode 100644 index 000000000..073ba42a9 --- /dev/null +++ b/ts/graphs/async.ts @@ -0,0 +1,28 @@ +import { Readable, readable, derived } from "svelte/store"; + +interface AsyncData { + value: Readable, + error: Readable, + pending: Readable, + successful: Readable, +} + + +function useAsync(asyncFunction: () => Promise): AsyncData { + const promise = asyncFunction(); + + const value = readable(null, (set: (value: T) => void) => { + promise.then((value: T) => set(value)) + }) + + const error = readable(null, (set: (value: E) => void) => { + promise.catch((value: E) => set(value)) + }) + + const pending = derived([value, error], (_, set) => set(true), true) + const successful = derived([value], (_, set) => set(true), false) + + return { value, error, pending, successful } +} + +export default useAsync From a9c16a3cd84b5f02f2ab109f120d0b2887e930c9 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 21 Mar 2021 20:16:40 +0100 Subject: [PATCH 02/24] Add (probably non-working) asyncRefresh --- ts/graphs/async.ts | 12 ++++++------ ts/graphs/asyncRefresh.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 ts/graphs/asyncRefresh.ts diff --git a/ts/graphs/async.ts b/ts/graphs/async.ts index 073ba42a9..e03185dbf 100644 --- a/ts/graphs/async.ts +++ b/ts/graphs/async.ts @@ -1,14 +1,14 @@ import { Readable, readable, derived } from "svelte/store"; -interface AsyncData { +export interface AsyncData { value: Readable, error: Readable, pending: Readable, - successful: Readable, + success: Readable, } -function useAsync(asyncFunction: () => Promise): AsyncData { +function useAsync(asyncFunction: () => Promise): AsyncData { const promise = asyncFunction(); const value = readable(null, (set: (value: T) => void) => { @@ -19,10 +19,10 @@ function useAsync(asyncFunction: () => Promise): AsyncData set(value)) }) - const pending = derived([value, error], (_, set) => set(true), true) - const successful = derived([value], (_, set) => set(true), false) + const pending = derived([value, error], (_, set) => set(false), true) + const success= derived([value], (_, set) => set(true), false) - return { value, error, pending, successful } + return { value, error, pending, success } } export default useAsync diff --git a/ts/graphs/asyncRefresh.ts b/ts/graphs/asyncRefresh.ts new file mode 100644 index 000000000..3d813cbab --- /dev/null +++ b/ts/graphs/asyncRefresh.ts @@ -0,0 +1,30 @@ +import { Readable, derived, get } from "svelte/store"; +import useAsync, { AsyncData } from "./async"; + +interface AsyncRefreshData { + value: Readable, + error: Readable, + pending: Readable, + success: Readable, + loading: Readable, +} + + +function useAsyncRefresh(asyncFunction: () => Promise, dependencies: [Readable, ...Readable[]]): AsyncRefreshData { + const current = derived( + dependencies, + (_, set: (value: AsyncData) => void) => set(useAsync(asyncFunction)), + useAsync(asyncFunction), + ) + + const value = derived(current, ($current, set: (value: T | null) => void) => set(get($current.value)), null) + const error = derived(current, ($current, set: (error: E | null) => void) => set(get($current.error)), null) + + const pending = derived(current, (_, set) => set(false), true) + const success = derived(current, ($current, set: (success: boolean) => void) => set(get($current.success)), false) + const loading = derived(current, ($current, set: (pending: boolean) => void) => set(get($current.pending)), true) + + return { value, error, pending, success, loading } +} + +export default useAsyncRefresh From 75a8b7d318a14c739cc6d694109ce14e4f2b8554 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 21 Mar 2021 21:07:35 +0100 Subject: [PATCH 03/24] Improve implementation of asyncRefresh --- ts/graphs/async.ts | 28 ++++++++------- ts/graphs/asyncRefresh.ts | 71 ++++++++++++++++++++++++++++----------- ts/tsconfig.json | 2 +- 3 files changed, 67 insertions(+), 34 deletions(-) diff --git a/ts/graphs/async.ts b/ts/graphs/async.ts index e03185dbf..5ce71974f 100644 --- a/ts/graphs/async.ts +++ b/ts/graphs/async.ts @@ -1,28 +1,30 @@ import { Readable, readable, derived } from "svelte/store"; export interface AsyncData { - value: Readable, - error: Readable, - pending: Readable, - success: Readable, + value: Readable; + error: Readable; + pending: Readable; + success: Readable; } - function useAsync(asyncFunction: () => Promise): AsyncData { const promise = asyncFunction(); const value = readable(null, (set: (value: T) => void) => { - promise.then((value: T) => set(value)) - }) + promise.then((value: T) => set(value)); + }); const error = readable(null, (set: (value: E) => void) => { - promise.catch((value: E) => set(value)) - }) + promise.catch((value: E) => set(value)); + }); - const pending = derived([value, error], (_, set) => set(false), true) - const success= derived([value], (_, set) => set(true), false) + const pending = readable(true, (set: (value: boolean) => void) => { + promise.finally(() => set(false)); + }); - return { value, error, pending, success } + const success = derived([value], (_, set) => set(true), false); + + return { value, error, pending, success }; } -export default useAsync +export default useAsync; diff --git a/ts/graphs/asyncRefresh.ts b/ts/graphs/asyncRefresh.ts index 3d813cbab..660eacfd1 100644 --- a/ts/graphs/asyncRefresh.ts +++ b/ts/graphs/asyncRefresh.ts @@ -1,30 +1,61 @@ -import { Readable, derived, get } from "svelte/store"; -import useAsync, { AsyncData } from "./async"; +import { Readable, readable, derived } from "svelte/store"; interface AsyncRefreshData { - value: Readable, - error: Readable, - pending: Readable, - success: Readable, - loading: Readable, + value: Readable; + error: Readable; + pending: Readable; + success: Readable; + loading: Readable; } +function useAsyncRefresh( + asyncFunction: () => Promise, + dependencies: [Readable, ...Readable[]] +): AsyncRefreshData { + const initial = asyncFunction(); + const promise = derived(dependencies, (_, set) => set(asyncFunction()), initial); -function useAsyncRefresh(asyncFunction: () => Promise, dependencies: [Readable, ...Readable[]]): AsyncRefreshData { - const current = derived( - dependencies, - (_, set: (value: AsyncData) => void) => set(useAsync(asyncFunction)), - useAsync(asyncFunction), - ) + const value = derived( + promise, + ($promise, set: (value: T | null) => void) => { + $promise.then((value: T) => set(value)); + return () => set(null); + }, + null + ); - const value = derived(current, ($current, set: (value: T | null) => void) => set(get($current.value)), null) - const error = derived(current, ($current, set: (error: E | null) => void) => set(get($current.error)), null) + const error = derived( + promise, + ($promise, set: (error: E | null) => void) => { + $promise.catch((error: E) => set(error)); + return () => set(null); + }, + null + ); - const pending = derived(current, (_, set) => set(false), true) - const success = derived(current, ($current, set: (success: boolean) => void) => set(get($current.success)), false) - const loading = derived(current, ($current, set: (pending: boolean) => void) => set(get($current.pending)), true) + const pending = readable(true, (set: (value: boolean) => void) => { + initial.finally(() => set(false)); + }); - return { value, error, pending, success, loading } + const loading = derived( + [value, error], + (_, set) => { + set(false); + return () => set(true); + }, + true + ); + + const success = derived( + [value], + (_, set) => { + set(true); + return () => set(false); + }, + false + ); + + return { value, error, pending, loading, success }; } -export default useAsyncRefresh +export default useAsyncRefresh; diff --git a/ts/tsconfig.json b/ts/tsconfig.json index 883e2130b..52befdcf3 100644 --- a/ts/tsconfig.json +++ b/ts/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "target": "es6", "module": "es6", - "lib": ["es2017", "es2019.array", "dom", "dom.iterable"], + "lib": ["es2017", "es2019.array", "es2018.promise", "dom", "dom.iterable"], "baseUrl": ".", "paths": { "anki/*": ["../bazel-bin/ts/lib/*"] From e11b31c29dfb0f0c7a3da66f42056a954f55dbf5 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 21 Mar 2021 21:38:23 +0100 Subject: [PATCH 04/24] Rename asyncRefresh to asyncReactive --- ts/graphs/async.ts | 2 +- ts/graphs/{asyncRefresh.ts => asyncReactive.ts} | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) rename ts/graphs/{asyncRefresh.ts => asyncReactive.ts} (86%) diff --git a/ts/graphs/async.ts b/ts/graphs/async.ts index 5ce71974f..8037a7e24 100644 --- a/ts/graphs/async.ts +++ b/ts/graphs/async.ts @@ -1,6 +1,6 @@ import { Readable, readable, derived } from "svelte/store"; -export interface AsyncData { +interface AsyncData { value: Readable; error: Readable; pending: Readable; diff --git a/ts/graphs/asyncRefresh.ts b/ts/graphs/asyncReactive.ts similarity index 86% rename from ts/graphs/asyncRefresh.ts rename to ts/graphs/asyncReactive.ts index 660eacfd1..5016c7227 100644 --- a/ts/graphs/asyncRefresh.ts +++ b/ts/graphs/asyncReactive.ts @@ -1,6 +1,6 @@ import { Readable, readable, derived } from "svelte/store"; -interface AsyncRefreshData { +interface AsyncReativeData { value: Readable; error: Readable; pending: Readable; @@ -8,10 +8,10 @@ interface AsyncRefreshData { loading: Readable; } -function useAsyncRefresh( +function useAsyncReactive( asyncFunction: () => Promise, dependencies: [Readable, ...Readable[]] -): AsyncRefreshData { +): AsyncReativeData { const initial = asyncFunction(); const promise = derived(dependencies, (_, set) => set(asyncFunction()), initial); @@ -19,7 +19,6 @@ function useAsyncRefresh( promise, ($promise, set: (value: T | null) => void) => { $promise.then((value: T) => set(value)); - return () => set(null); }, null ); @@ -28,7 +27,6 @@ function useAsyncRefresh( promise, ($promise, set: (error: E | null) => void) => { $promise.catch((error: E) => set(error)); - return () => set(null); }, null ); @@ -58,4 +56,4 @@ function useAsyncRefresh( return { value, error, pending, loading, success }; } -export default useAsyncRefresh; +export default useAsyncReactive; From 36e14cd525c9fc1b931b37ec66065e762497360b Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 21 Mar 2021 22:06:25 +0100 Subject: [PATCH 05/24] Add WithGraphData --- ts/graphs/WithGraphData.svelte | 31 +++++++++++++++++++++++++++++++ ts/graphs/asyncReactive.ts | 1 + 2 files changed, 32 insertions(+) create mode 100644 ts/graphs/WithGraphData.svelte diff --git a/ts/graphs/WithGraphData.svelte b/ts/graphs/WithGraphData.svelte new file mode 100644 index 000000000..7c3af297a --- /dev/null +++ b/ts/graphs/WithGraphData.svelte @@ -0,0 +1,31 @@ + + + + diff --git a/ts/graphs/asyncReactive.ts b/ts/graphs/asyncReactive.ts index 5016c7227..d53c14895 100644 --- a/ts/graphs/asyncReactive.ts +++ b/ts/graphs/asyncReactive.ts @@ -27,6 +27,7 @@ function useAsyncReactive( promise, ($promise, set: (error: E | null) => void) => { $promise.catch((error: E) => set(error)); + return () => set(null); }, null ); From c107090906b85c311036c72924a668b56e2f93b2 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 21 Mar 2021 22:09:34 +0100 Subject: [PATCH 06/24] Move Graph-specific html from GraphsPage to Graph.svelte --- ts/graphs/Graph.svelte | 5 ++++- ts/graphs/GraphsPage.svelte | 25 ++++++++++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/ts/graphs/Graph.svelte b/ts/graphs/Graph.svelte index 8ee040fd4..9b4ed79c8 100644 --- a/ts/graphs/Graph.svelte +++ b/ts/graphs/Graph.svelte @@ -42,6 +42,9 @@ * marked the ticks as odd */ display: none; } + + &:focus { + outline: 0; } } @@ -57,7 +60,7 @@ } -
+

{title}

{#if subtitle} diff --git a/ts/graphs/GraphsPage.svelte b/ts/graphs/GraphsPage.svelte index 2c52979e6..e60c8b67f 100644 --- a/ts/graphs/GraphsPage.svelte +++ b/ts/graphs/GraphsPage.svelte @@ -60,9 +60,6 @@ } } - .no-focus-outline:focus { - outline: 0; - }
@@ -77,17 +74,15 @@ {/if} {#if sourceData} -
- {#each graphs as graph} - - {/each} -
+ {#each graphs as graph} + + {/each} {/if}
From 3f37153558b1294803c2022539ed60a130a53ee1 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 21 Mar 2021 22:35:53 +0100 Subject: [PATCH 07/24] Compiles with WithGraphData --- ts/graphs/GraphsPage.svelte | 83 ++++++++++++---------------------- ts/graphs/RangeBox.svelte | 44 ++++++------------ ts/graphs/WithGraphData.svelte | 22 +++++---- 3 files changed, 54 insertions(+), 95 deletions(-) diff --git a/ts/graphs/GraphsPage.svelte b/ts/graphs/GraphsPage.svelte index e60c8b67f..92f536c57 100644 --- a/ts/graphs/GraphsPage.svelte +++ b/ts/graphs/GraphsPage.svelte @@ -9,6 +9,8 @@ import { getPreferences } from "./preferences"; import { bridgeCommand } from "anki/bridgecommand"; + import WithGraphData from "./WithGraphData.svelte"; + export let i18n: I18n; export let nightMode: boolean; export let graphs: SvelteComponent[]; @@ -17,39 +19,8 @@ export let days: number; export let controller: SvelteComponent | null; - let active = false; - let sourceData: pb.BackendProto.GraphsOut | null = null; - let preferences: PreferenceStore | null = null; - let revlogRange: RevlogRange; - - const preferencesPromise = getPreferences(); - - const refreshWith = async (searchNew: string, days: number) => { - search = searchNew; - - active = true; - try { - [sourceData, preferences] = await Promise.all([ - getGraphData(search, days), - preferencesPromise, - ]); - revlogRange = daysToRevlogRange(days); - } catch (e) { - sourceData = null; - alert(e); - } - active = false; - }; - - const refresh = (event: CustomEvent) => { - refreshWith(event.detail.search, event.detail.days); - }; - - refreshWith(search, days); - - const browserSearch = (event: CustomEvent) => { - const query = `${search} ${event.detail.query}`; - bridgeCommand(`browserSearch:${query}`); + const browserSearch = (search: string, query: string) => { + bridgeCommand(`browserSearch:${search} ${query}`); }; @@ -59,30 +30,32 @@ font-size: 12px; } } -
- {#if controller} - - {/if} + + {#if controller} + + {/if} - {#if sourceData} - {#each graphs as graph} - - {/each} - {/if} + {#if !pending} + {#each graphs as graph} + browserSearch(search, event.detail.query)} /> + {/each} + {/if} +
diff --git a/ts/graphs/RangeBox.svelte b/ts/graphs/RangeBox.svelte index 553cca1c0..75d015a4b 100644 --- a/ts/graphs/RangeBox.svelte +++ b/ts/graphs/RangeBox.svelte @@ -1,5 +1,6 @@ - + {search} + {days} + {revlogRange} + pending={$sourceData.pending || $preferences.pending} + loading={$sourceData.loading || $preferences.loading} + sourceData={$sourceData.value} + preferences={$preferences.value} /> From 672eb203211eed1b3ffd1c428ef14f5293d7b5da Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 21 Mar 2021 23:45:59 +0100 Subject: [PATCH 08/24] Get it to work, if you change the input - there's still an issue on initial load --- ts/graphs/GraphsPage.svelte | 10 ++++------ ts/graphs/RangeBox.svelte | 13 +++++++------ ts/graphs/WithGraphData.svelte | 21 +++++++++++++++------ ts/graphs/asyncReactive.ts | 4 ++-- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/ts/graphs/GraphsPage.svelte b/ts/graphs/GraphsPage.svelte index 92f536c57..c0f76cf02 100644 --- a/ts/graphs/GraphsPage.svelte +++ b/ts/graphs/GraphsPage.svelte @@ -3,10 +3,6 @@ import type { SvelteComponent } from "svelte/internal"; import type { I18n } from "anki/i18n"; - import type { PreferenceStore } from "./preferences"; - import type pb from "anki/backend_proto"; - import { getGraphData, RevlogRange, daysToRevlogRange } from "./graph-helpers"; - import { getPreferences } from "./preferences"; import { bridgeCommand } from "anki/bridgecommand"; import WithGraphData from "./WithGraphData.svelte"; @@ -36,16 +32,18 @@ {#if controller} - + {/if} - {#if !pending} + {#if !pending && sourceData && preferences} {#each graphs as graph} ; export let search: Writable; - let revlogRange = daysToRevlogRange(days); - let searchRange: SearchRange = - search === "deck:current" + let revlogRange = daysToRevlogRange($days); + let searchRange = $search === "deck:current" ? SearchRange.Deck - : search === "" + : $search === "" ? SearchRange.Collection : SearchRange.Custom; - let displayedSearch = search; + let displayedSearch = $search; $: { switch (searchRange as SearchRange) { case SearchRange.Deck: displayedSearch = "deck:current"; + console.log('search', search) search.set(displayedSearch); break; case SearchRange.Collection: - search = displayedSearch = ""; + displayedSearch = ""; + console.log('search', search) search.set(displayedSearch); break; } diff --git a/ts/graphs/WithGraphData.svelte b/ts/graphs/WithGraphData.svelte index 560c1b585..e5e94d542 100644 --- a/ts/graphs/WithGraphData.svelte +++ b/ts/graphs/WithGraphData.svelte @@ -14,11 +14,20 @@ const search = writable(initialSearch); const days = writable(initialDays); - const sourceData = useAsyncReactive(() => getGraphData($search, $days), [ + const { + pending: graphPending, + loading: graphLoading, + value: graphValue, + } = useAsyncReactive(() => getGraphData($search, $days), [ search, days, ]); - const preferences = useAsync(() => getPreferences()); + + const { + pending: prefsPending, + loading: prefsLoading, + value: prefsValue, + } = useAsync(() => getPreferences()); $: revlogRange = daysToRevlogRange($days); @@ -27,7 +36,7 @@ {search} {days} {revlogRange} - pending={$sourceData.pending || $preferences.pending} - loading={$sourceData.loading || $preferences.loading} - sourceData={$sourceData.value} - preferences={$preferences.value} /> + pending={$graphPending || $prefsPending} + loading={$graphLoading || $prefsLoading} + sourceData={$graphValue} + preferences={$prefsValue} /> diff --git a/ts/graphs/asyncReactive.ts b/ts/graphs/asyncReactive.ts index d53c14895..bb91f1fc7 100644 --- a/ts/graphs/asyncReactive.ts +++ b/ts/graphs/asyncReactive.ts @@ -38,7 +38,7 @@ function useAsyncReactive( const loading = derived( [value, error], - (_, set) => { + (_, set: (value: boolean) => void) => { set(false); return () => set(true); }, @@ -47,7 +47,7 @@ function useAsyncReactive( const success = derived( [value], - (_, set) => { + (_, set: (value: boolean) => void) => { set(true); return () => set(false); }, From dd2e180f9b41f8d02f5f2c736f10265843e954c5 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Mon, 22 Mar 2021 00:04:24 +0100 Subject: [PATCH 09/24] Rename search and days to initialSearch and intitialDays in GraphsPage --- ts/graphs/GraphsPage.svelte | 16 ++++++++-------- ts/graphs/RangeBox.svelte | 2 -- ts/graphs/WithGraphData.svelte | 1 + ts/graphs/asyncReactive.ts | 2 +- ts/graphs/index.ts | 4 ++-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/ts/graphs/GraphsPage.svelte b/ts/graphs/GraphsPage.svelte index c0f76cf02..c76236bb1 100644 --- a/ts/graphs/GraphsPage.svelte +++ b/ts/graphs/GraphsPage.svelte @@ -11,8 +11,8 @@ export let nightMode: boolean; export let graphs: SvelteComponent[]; - export let search: string; - export let days: number; + export let initialSearch: string; + export let initialDays: number; export let controller: SvelteComponent | null; const browserSearch = (search: string, query: string) => { @@ -30,20 +30,20 @@
{#if controller} - + {/if} - {#if !pending && sourceData && preferences} + {#if !pending} {#each graphs as graph} + import { onMount } from "svelte"; import { writable } from "svelte/store"; import useAsync from "./async"; import useAsyncReactive from "./asyncReactive"; diff --git a/ts/graphs/asyncReactive.ts b/ts/graphs/asyncReactive.ts index bb91f1fc7..57d7b500f 100644 --- a/ts/graphs/asyncReactive.ts +++ b/ts/graphs/asyncReactive.ts @@ -4,8 +4,8 @@ interface AsyncReativeData { value: Readable; error: Readable; pending: Readable; - success: Readable; loading: Readable; + success: Readable; } function useAsyncReactive( diff --git a/ts/graphs/index.ts b/ts/graphs/index.ts index 4e261cfd6..68e877e66 100644 --- a/ts/graphs/index.ts +++ b/ts/graphs/index.ts @@ -40,8 +40,8 @@ export function graphs( i18n, graphs, nightMode, - search, - days, + initialSearch: search, + initialDays: days, controller, }, }); From 3363c574c996d6d173290086b1624fd475d289aa Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Mon, 22 Mar 2021 00:13:52 +0100 Subject: [PATCH 10/24] Use $-assignments instead of store.set --- ts/graphs/RangeBox.svelte | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ts/graphs/RangeBox.svelte b/ts/graphs/RangeBox.svelte index b2449ec45..157420444 100644 --- a/ts/graphs/RangeBox.svelte +++ b/ts/graphs/RangeBox.svelte @@ -31,12 +31,10 @@ $: { switch (searchRange as SearchRange) { case SearchRange.Deck: - displayedSearch = "deck:current"; - search.set(displayedSearch); + $search = displayedSearch = "deck:current"; break; case SearchRange.Collection: - displayedSearch = ""; - search.set(displayedSearch); + $search = displayedSearch = ""; break; } } @@ -44,10 +42,10 @@ $: { switch (revlogRange as RevlogRange) { case RevlogRange.Year: - days.set(365); + $days = 365; break; case RevlogRange.All: - days.set(0); + $days = 0; break; } } @@ -55,7 +53,7 @@ const searchKeyUp = (event: KeyboardEvent) => { // fetch data on enter if (event.key === "Enter") { - search.set(displayedSearch); + $search = displayedSearch; } }; From b3851172ba38af7de18987ca190ba7ead973d1e3 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Mon, 22 Mar 2021 00:21:40 +0100 Subject: [PATCH 11/24] Use preferencesPromise, as refreshing is handled over stores --- ts/graphs/WithGraphData.svelte | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ts/graphs/WithGraphData.svelte b/ts/graphs/WithGraphData.svelte index e28d59e33..72e6e0a81 100644 --- a/ts/graphs/WithGraphData.svelte +++ b/ts/graphs/WithGraphData.svelte @@ -10,8 +10,6 @@ export let initialSearch: string; export let initialDays: number; - const preferencesPromise = getPreferences(); - const search = writable(initialSearch); const days = writable(initialDays); @@ -24,11 +22,12 @@ days, ]); + const preferencesPromise = getPreferences(); const { pending: prefsPending, loading: prefsLoading, value: prefsValue, - } = useAsync(() => getPreferences()); + } = useAsync(() => preferencesPromise); $: revlogRange = daysToRevlogRange($days); From 6d546b0bca673c9a2bb4a1979324ee328bd92ba7 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Mon, 22 Mar 2021 00:40:19 +0100 Subject: [PATCH 12/24] Remove pending, and resort to checking for value - once value is set, it won't be unset --- ts/graphs/GraphsPage.svelte | 5 ++--- ts/graphs/WithGraphData.svelte | 17 ++++++++++++++--- ts/graphs/async.ts | 6 +++--- ts/graphs/asyncReactive.ts | 11 +++-------- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/ts/graphs/GraphsPage.svelte b/ts/graphs/GraphsPage.svelte index c76236bb1..90f8a2c1f 100644 --- a/ts/graphs/GraphsPage.svelte +++ b/ts/graphs/GraphsPage.svelte @@ -15,7 +15,7 @@ export let initialDays: number; export let controller: SvelteComponent | null; - const browserSearch = (search: string, query: string) => { + const browserSearch = (search: string, query: string): void => { bridgeCommand(`browserSearch:${search} ${query}`); }; @@ -34,7 +34,6 @@ {initialDays} let:search let:days - let:pending let:loading let:sourceData let:preferences @@ -43,7 +42,7 @@ {/if} - {#if !pending} + {#if sourceData && preferences && revlogRange} {#each graphs as graph} getGraphData($search, $days), [ search, @@ -24,19 +24,30 @@ const preferencesPromise = getPreferences(); const { - pending: prefsPending, loading: prefsLoading, + error: prefsError, value: prefsValue, } = useAsync(() => preferencesPromise); $: revlogRange = daysToRevlogRange($days); + + $: { + if ($graphError) { + alert($graphError) + } + } + + $: { + if ($prefsError) { + alert($prefsError) + } + } diff --git a/ts/graphs/async.ts b/ts/graphs/async.ts index 8037a7e24..387dcb3b5 100644 --- a/ts/graphs/async.ts +++ b/ts/graphs/async.ts @@ -3,7 +3,7 @@ import { Readable, readable, derived } from "svelte/store"; interface AsyncData { value: Readable; error: Readable; - pending: Readable; + loading: Readable; success: Readable; } @@ -18,13 +18,13 @@ function useAsync(asyncFunction: () => Promise): AsyncData set(value)); }); - const pending = readable(true, (set: (value: boolean) => void) => { + const loading = readable(true, (set: (value: boolean) => void) => { promise.finally(() => set(false)); }); const success = derived([value], (_, set) => set(true), false); - return { value, error, pending, success }; + return { value, error, loading, success }; } export default useAsync; diff --git a/ts/graphs/asyncReactive.ts b/ts/graphs/asyncReactive.ts index 57d7b500f..70dfcdfd9 100644 --- a/ts/graphs/asyncReactive.ts +++ b/ts/graphs/asyncReactive.ts @@ -1,9 +1,8 @@ -import { Readable, readable, derived } from "svelte/store"; +import { Readable, derived } from "svelte/store"; interface AsyncReativeData { value: Readable; error: Readable; - pending: Readable; loading: Readable; success: Readable; } @@ -17,7 +16,7 @@ function useAsyncReactive( const value = derived( promise, - ($promise, set: (value: T | null) => void) => { + ($promise, set: (value: T) => void) => { $promise.then((value: T) => set(value)); }, null @@ -32,10 +31,6 @@ function useAsyncReactive( null ); - const pending = readable(true, (set: (value: boolean) => void) => { - initial.finally(() => set(false)); - }); - const loading = derived( [value, error], (_, set: (value: boolean) => void) => { @@ -54,7 +49,7 @@ function useAsyncReactive( false ); - return { value, error, pending, loading, success }; + return { value, error, loading, success }; } export default useAsyncReactive; From 7dc74004aefb35d56a286fd9f7c65d41a174fe82 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Mon, 22 Mar 2021 01:07:15 +0100 Subject: [PATCH 13/24] Create BrowserSearch component, because we cannot read from stores within slotted content --- ts/graphs/BrowserSearch.svelte | 10 ++++++++++ ts/graphs/GraphsPage.svelte | 18 +++++++++++------- ts/graphs/asyncReactive.ts | 3 +-- 3 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 ts/graphs/BrowserSearch.svelte diff --git a/ts/graphs/BrowserSearch.svelte b/ts/graphs/BrowserSearch.svelte new file mode 100644 index 000000000..a093b42d7 --- /dev/null +++ b/ts/graphs/BrowserSearch.svelte @@ -0,0 +1,10 @@ + diff --git a/ts/graphs/GraphsPage.svelte b/ts/graphs/GraphsPage.svelte index 90f8a2c1f..5d165cac1 100644 --- a/ts/graphs/GraphsPage.svelte +++ b/ts/graphs/GraphsPage.svelte @@ -3,9 +3,9 @@ import type { SvelteComponent } from "svelte/internal"; import type { I18n } from "anki/i18n"; - import { bridgeCommand } from "anki/bridgecommand"; import WithGraphData from "./WithGraphData.svelte"; + import BrowserSearch from "./BrowserSearch.svelte"; export let i18n: I18n; export let nightMode: boolean; @@ -15,20 +15,22 @@ export let initialDays: number; export let controller: SvelteComponent | null; - const browserSearch = (search: string, query: string): void => { - bridgeCommand(`browserSearch:${search} ${query}`); + let query: string; + + const activateBrowserSearch = (event: CustomEvent): void => { + query = event.detail.query; }; -
+
browserSearch(search, event.detail.query)} /> + on:search={activateBrowserSearch} /> {/each} {/if} + +
diff --git a/ts/graphs/asyncReactive.ts b/ts/graphs/asyncReactive.ts index 70dfcdfd9..c5590d0c7 100644 --- a/ts/graphs/asyncReactive.ts +++ b/ts/graphs/asyncReactive.ts @@ -11,8 +11,7 @@ function useAsyncReactive( asyncFunction: () => Promise, dependencies: [Readable, ...Readable[]] ): AsyncReativeData { - const initial = asyncFunction(); - const promise = derived(dependencies, (_, set) => set(asyncFunction()), initial); + const promise = derived(dependencies, (_, set) => set(asyncFunction()), asyncFunction()); const value = derived( promise, From 9a864120b2da1b4f2e1f58c93553e500331b0aa7 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Mon, 22 Mar 2021 01:44:07 +0100 Subject: [PATCH 14/24] Fix syntax error introduced by rebase --- ts/graphs/Graph.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/ts/graphs/Graph.svelte b/ts/graphs/Graph.svelte index 9b4ed79c8..03c34128f 100644 --- a/ts/graphs/Graph.svelte +++ b/ts/graphs/Graph.svelte @@ -42,6 +42,7 @@ * marked the ticks as odd */ display: none; } + } &:focus { outline: 0; From 0bbe38ebde07656a2c0ff23d131fa5f0895820f1 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Mon, 22 Mar 2021 02:44:08 +0100 Subject: [PATCH 15/24] Create search and days writable in GraphsPage to allow browserSearch to work --- ts/graphs/BrowserSearch.svelte | 10 ---------- ts/graphs/GraphsPage.svelte | 22 ++++++++++------------ ts/graphs/RangeBox.svelte | 3 ++- ts/graphs/WithGraphData.svelte | 28 ++++++++-------------------- ts/graphs/asyncReactive.ts | 6 +++++- 5 files changed, 25 insertions(+), 44 deletions(-) delete mode 100644 ts/graphs/BrowserSearch.svelte diff --git a/ts/graphs/BrowserSearch.svelte b/ts/graphs/BrowserSearch.svelte deleted file mode 100644 index a093b42d7..000000000 --- a/ts/graphs/BrowserSearch.svelte +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/ts/graphs/GraphsPage.svelte b/ts/graphs/GraphsPage.svelte index 5d165cac1..6d2488ed4 100644 --- a/ts/graphs/GraphsPage.svelte +++ b/ts/graphs/GraphsPage.svelte @@ -2,10 +2,11 @@ import "../sass/core.css"; import type { SvelteComponent } from "svelte/internal"; + import { writable } from "svelte/store"; import type { I18n } from "anki/i18n"; + import { bridgeCommand } from "anki/bridgecommand"; import WithGraphData from "./WithGraphData.svelte"; - import BrowserSearch from "./BrowserSearch.svelte"; export let i18n: I18n; export let nightMode: boolean; @@ -15,11 +16,12 @@ export let initialDays: number; export let controller: SvelteComponent | null; - let query: string; + const search = writable(initialSearch); + const days = writable(initialDays); - const activateBrowserSearch = (event: CustomEvent): void => { - query = event.detail.query; - }; + function browserSearch(event: CustomEvent) { + bridgeCommand(`browserSearch: ${$search} ${event.detail.query}`); + }