From f6c540a3ad29c4ef70e01bf135dd2d478fdd0562 Mon Sep 17 00:00:00 2001 From: thislight Date: Thu, 10 Oct 2024 20:32:54 +0800 Subject: [PATCH] TrendTimelinePanel: improved error handling --- src/UnexpectedError.tsx | 85 +++++++++++++++++----------- src/masto/timelines.ts | 18 +++--- src/timelines/TrendTimelinePanel.tsx | 19 ++----- 3 files changed, 69 insertions(+), 53 deletions(-) diff --git a/src/UnexpectedError.tsx b/src/UnexpectedError.tsx index 38e3c70..aa7f468 100644 --- a/src/UnexpectedError.tsx +++ b/src/UnexpectedError.tsx @@ -1,40 +1,59 @@ -import { Button } from '@suid/material'; -import {Component, createResource} from 'solid-js' -import { css } from 'solid-styled'; +import { Button } from "@suid/material"; +import { Component, createResource } from "solid-js"; +import { css } from "solid-styled"; -const UnexpectedError: Component<{error?: any}> = (props) => { +const UnexpectedError: Component<{ error?: any }> = (props) => { + const [errorMsg] = createResource( + () => props.error, + async (err) => { + if (err instanceof Error) { + const mod = await import("stacktrace-js"); + try { + const stacktrace = await mod.fromError(err); + const strackMsg = stacktrace + .map( + (entry) => + `${entry.functionName ?? ""}@${entry.fileName}:(${entry.lineNumber}:${entry.columnNumber})`, + ) + .join("\n"); + return `${err.name}: ${err.message}\n${strackMsg}`; + } catch (reason) { + return `\n${reason}`; + } + } - const [errorMsg] = createResource(() => props.error, async (err) => { - if (err instanceof Error) { - const mod = await import('stacktrace-js') - const stacktrace = await mod.fromError(err) - const strackMsg = stacktrace.map(entry => `${entry.functionName ?? ""}@${entry.fileName}:(${entry.lineNumber}:${entry.columnNumber})`).join('\n') - return `${err.name}: ${err.message}\n${strackMsg}` - } - - return err.toString() - }) + return err.toString(); + }, + ); css` - main { - padding: calc(var(--safe-area-inset-top) + 20px) calc(var(--safe-area-inset-right) + 20px) calc(var(--safe-area-inset-bottom) + 20px) calc(var(--safe-area-inset-left) + 20px); - } - ` + main { + padding: calc(var(--safe-area-inset-top) + 20px) + calc(var(--safe-area-inset-right) + 20px) + calc(var(--safe-area-inset-bottom) + 20px) + calc(var(--safe-area-inset-left) + 20px); + } + `; - return
-

Oh, it is our fault.

-

There is an unexpected error in our app, and it's not your fault.

-

You can reload to see if this guy is gone. If you meet this guy repeatly, please report to us.

-
- -
-
- {errorMsg.loading ? 'Generating ' : " "}Technical Infomation (Bring to us if you report the problem) -
-        {errorMsg()}
-      
-
-
-} + return ( +
+

Oh, it is our fault.

+

There is an unexpected error in our app, and it's not your fault.

+

+ You can reload to see if this guy is gone. If you meet this guy + repeatly, please report to us. +

+
+ +
+
+ + {errorMsg.loading ? "Generating " : " "}Technical Infomation + +
{errorMsg()}
+
+
+ ); +}; export default UnexpectedError; diff --git a/src/masto/timelines.ts b/src/masto/timelines.ts index 4e307f7..e147cbc 100644 --- a/src/masto/timelines.ts +++ b/src/masto/timelines.ts @@ -1,5 +1,5 @@ import { type mastodon } from "masto"; -import { Accessor, createEffect, createResource } from "solid-js"; +import { Accessor, catchError, createEffect, createResource } from "solid-js"; import { createStore } from "solid-js/store"; type TimelineFetchTips = { @@ -114,7 +114,7 @@ export function createTimelineSnapshot( timeline: Accessor, limit: Accessor, ) { - const [shot, {refetch}] = createResource( + const [shot, { refetch }] = createResource( () => [timeline(), limit()] as const, async ([tl, limit]) => { const ls = await tl.list({ limit }).next(); @@ -125,7 +125,7 @@ export function createTimelineSnapshot( const [snapshot, setSnapshot] = createStore([] as mastodon.v1.Status[][]); createEffect(() => { - const nls = shot(); + const nls = catchError(shot, (e) => console.error(e)); if (!nls) return; const ols = Array.from(snapshot); // The algorithm below assumes the snapshot is not changing @@ -154,10 +154,14 @@ export function createTimelineSnapshot( } }); - return [snapshot, shot, { - refetch, - mutate: setSnapshot - }] as const; + return [ + snapshot, + shot, + { + refetch, + mutate: setSnapshot, + }, + ] as const; } export function createTimeline(timeline: Accessor) { diff --git a/src/timelines/TrendTimelinePanel.tsx b/src/timelines/TrendTimelinePanel.tsx index ddb97bc..a2370e8 100644 --- a/src/timelines/TrendTimelinePanel.tsx +++ b/src/timelines/TrendTimelinePanel.tsx @@ -3,7 +3,6 @@ import { For, onCleanup, createSignal, - Show, untrack, Match, Switch as JsSwitch, @@ -11,7 +10,7 @@ import { createSelector, } from "solid-js"; import { type mastodon } from "masto"; -import { Button, LinearProgress } from "@suid/material"; +import { Button } from "@suid/material"; import { createTimelineSnapshot } from "../masto/timelines.js"; import { vibrate } from "../platform/hardware.js"; import PullDownToRefresh from "./PullDownToRefresh.jsx"; @@ -40,7 +39,7 @@ const TrendTimelinePanel: Component<{ const tlEndObserver = new IntersectionObserver(() => { if (untrack(() => props.prefetch) && !snapshot.loading) - refetchTimeline({ direction: "old" }); + refetchTimeline(); }); onCleanup(() => tlEndObserver.disconnect()); @@ -143,26 +142,19 @@ const TrendTimelinePanel: Component<{
tlEndObserver.observe(e)}>
- -
- -
-
+

{`Oops: ${snapshot.error}`}

+