From b2d9208a5816fbbea0473f7ef1d399e534c04be7 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 12 Jul 2023 12:09:44 -0500 Subject: [PATCH] clean up activity syncing --- src/components/Activity.tsx | 46 ++++++++++++++++++++++++++++--------- src/components/App.tsx | 24 ++++++++----------- src/routes/Activity.tsx | 16 +++++++------ src/state/megaStore.tsx | 14 +---------- src/utils/deepSignal.ts | 21 +++++++++++++++++ 5 files changed, 75 insertions(+), 46 deletions(-) create mode 100644 src/utils/deepSignal.ts diff --git a/src/components/Activity.tsx b/src/components/Activity.tsx index 685cdfd..00d1c56 100644 --- a/src/components/Activity.tsx +++ b/src/components/Activity.tsx @@ -3,9 +3,9 @@ import { For, Match, Show, - Suspense, Switch, createEffect, + createResource, createSignal } from "solid-js"; import { useMegaStore } from "~/state/megaStore"; @@ -13,7 +13,9 @@ import { useI18n } from "~/i18n/context"; import { Contact } from "@mutinywallet/mutiny-wasm"; import { ActivityItem, HackActivityType } from "./ActivityItem"; import { DetailsIdModal } from "./DetailsModal"; +import { A } from "solid-start"; import { LoadingShimmer } from "./BalanceBox"; +import { createDeepSignal } from "~/utils/deepSignal"; export const THREE_COLUMNS = "grid grid-cols-[auto,1fr,auto] gap-4 py-2 px-2 border-b border-neutral-800 last:border-b-0"; @@ -85,8 +87,10 @@ function UnifiedActivityItem(props: { ); } + + export function CombinedActivity(props: { limit?: number }) { - const [state, actions] = useMegaStore(); + const [state, _actions] = useMegaStore(); const i18n = useI18n(); const [detailsOpen, setDetailsOpen] = createSignal(false); @@ -107,14 +111,26 @@ export function CombinedActivity(props: { limit?: number }) { setDetailsOpen(true); } + async function fetchActivity() { + return await state.mutiny_wallet?.get_activity(); + } + + const [activity, { refetch }] = createResource(fetchActivity, { + storage: createDeepSignal + }); + createEffect(() => { - if (!state.wallet_loading && !state.is_syncing) { - actions.syncActivity(); + // Should re-run after every sync + if (!state.is_syncing) { + refetch(); } }); return ( - }> + } + > - +
{i18n.t("receive_some_sats_to_get_started")} @@ -132,9 +148,9 @@ export function CombinedActivity(props: { limit?: number }) {
props.limit} + when={props.limit && activity.latest.length > props.limit} > - + {(activityItem) => ( - = 0}> - + = 0}> + {(activityItem) => (
-
+ 0}> + + {i18n.t("view_all")} + + + ); } diff --git a/src/components/App.tsx b/src/components/App.tsx index 30c1760..a1ae636 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -6,7 +6,7 @@ import { A } from "solid-start"; import { OnboardWarning } from "~/components/OnboardWarning"; import { CombinedActivity } from "./Activity"; import { useMegaStore } from "~/state/megaStore"; -import { Match, Show, Switch } from "solid-js"; +import { Match, Show, Suspense, Switch } from "solid-js"; import { ExternalLink } from "./layout/ExternalLink"; import { BetaWarningModal } from "~/components/BetaWarningModal"; import settings from "~/assets/icons/settings.svg"; @@ -74,21 +74,15 @@ export default function App() {
- } - > - - + + } + > + + + - 0}> - - {i18n.t("view_all")} - -

Bugs? Feedback?{" "} diff --git a/src/routes/Activity.tsx b/src/routes/Activity.tsx index f36c6c6..37d318a 100644 --- a/src/routes/Activity.tsx +++ b/src/routes/Activity.tsx @@ -1,4 +1,4 @@ -import { For, Show, createResource } from "solid-js"; +import { For, Show, Suspense, createResource } from "solid-js"; import NavBar from "~/components/NavBar"; import { Button, @@ -107,12 +107,14 @@ export default function Activity() {

- } - > - - + + } + > + + + diff --git a/src/state/megaStore.tsx b/src/state/megaStore.tsx index 42526f8..63c4d6e 100644 --- a/src/state/megaStore.tsx +++ b/src/state/megaStore.tsx @@ -9,7 +9,7 @@ import { onMount, useContext } from "solid-js"; -import { createStore, reconcile } from "solid-js/store"; +import { createStore } from "solid-js/store"; import { MutinyWalletSettingStrings, doubleInitDefense, @@ -21,7 +21,6 @@ import { MutinyTagItem } from "~/utils/tags"; import { checkBrowserCompatibility } from "~/logic/browserCompatibility"; import eify from "~/utils/eify"; import { timeout } from "~/utils/timeout"; -import { ActivityItem } from "~/components/Activity"; import { ParsedParams } from "~/logic/waila"; const MegaStoreContext = createContext(); @@ -51,7 +50,6 @@ export type MegaStore = [ has_backed_up: boolean; dismissed_restore_prompt: boolean; wallet_loading: boolean; - activity: ActivityItem[]; setup_error?: Error; is_pwa: boolean; existing_tab_detected: boolean; @@ -73,7 +71,6 @@ export type MegaStore = [ dismissRestorePrompt(): void; setHasBackedUp(): void; listTags(): Promise; - syncActivity(): Promise; checkBrowserCompat(): Promise; checkForSubscription(justPaid?: boolean): Promise; } @@ -97,7 +94,6 @@ export const Provider: ParentComponent = (props) => { dismissed_restore_prompt: localStorage.getItem("dismissed_restore_prompt") === "true", wallet_loading: true, - activity: [] as ActivityItem[], setup_error: undefined as Error | undefined, is_pwa: window.matchMedia("(display-mode: standalone)").matches, existing_tab_detected: false, @@ -287,14 +283,6 @@ export const Provider: ParentComponent = (props) => { setState({ is_syncing: false }); } }, - async syncActivity(): Promise { - try { - const activity = await state.mutiny_wallet?.get_activity(); - setState("activity", reconcile(activity, { merge: true })); - } catch (e) { - console.error(e); - } - }, setScanResult(scan_result: ParsedParams) { setState({ scan_result }); }, diff --git a/src/utils/deepSignal.ts b/src/utils/deepSignal.ts new file mode 100644 index 0000000..2045b61 --- /dev/null +++ b/src/utils/deepSignal.ts @@ -0,0 +1,21 @@ +import { Signal } from "solid-js"; +import { createStore, reconcile, unwrap } from "solid-js/store"; + +// All these shenanigans are so we don't get a flicker after every refresh +// API may change in the future: https://docs.solidjs.com/references/api-reference/basic-reactivity/createResource +export function createDeepSignal(value: T): Signal { + const [store, setStore] = createStore({ + value + }); + return [ + // eslint-disable-next-line + () => store.value, + // eslint-disable-next-line + (v: T) => { + const unwrapped = unwrap(store.value); + typeof v === "function" && (v = v(unwrapped)); + setStore("value", reconcile(v, { merge: true })); + return store.value; + } + ] as Signal; +}