From 7ddf7e578951a35a5ee1f4d5c19587b9ec8391f5 Mon Sep 17 00:00:00 2001 From: Daniel Metcalfe Date: Sun, 11 Aug 2024 21:18:44 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Allow=20signing=20back=20in=20af?= =?UTF-8?q?ter=20client-side=20exception?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This at least allow users to recover from some bugs until they're fixed --- app/[...all]/page.tsx | 4 +- components/{AppShell.tsx => App.tsx} | 23 +-- components/ErrorBoundary.tsx | 42 +++++ components/common/Header.tsx | 156 ++++++++++++++++++ components/{app => demo}/ControlPanel.tsx | 0 components/{app => demo}/Journey/index.tsx | 0 .../{app => demo}/PerformanceSidebar.tsx | 0 components/{app => demo}/RoleSidebar.tsx | 0 .../{app => demo}/chart-dynamic-gradient.png | Bin .../{app => demo}/crown-dynamic-gradient.png | Bin components/{app => demo}/index.tsx | 12 +- .../setting-dynamic-gradient.png | Bin .../{app => demo}/star-front-gradient.png | Bin .../{app => demo}/zoom-dynamic-gradient.png | Bin components/pages/Constellation.tsx | 7 +- components/pages/Home.tsx | 147 +---------------- pages/app-demo.tsx | 2 +- 17 files changed, 226 insertions(+), 167 deletions(-) rename components/{AppShell.tsx => App.tsx} (70%) create mode 100644 components/ErrorBoundary.tsx create mode 100644 components/common/Header.tsx rename components/{app => demo}/ControlPanel.tsx (100%) rename components/{app => demo}/Journey/index.tsx (100%) rename components/{app => demo}/PerformanceSidebar.tsx (100%) rename components/{app => demo}/RoleSidebar.tsx (100%) rename components/{app => demo}/chart-dynamic-gradient.png (100%) rename components/{app => demo}/crown-dynamic-gradient.png (100%) rename components/{app => demo}/index.tsx (82%) rename components/{app => demo}/setting-dynamic-gradient.png (100%) rename components/{app => demo}/star-front-gradient.png (100%) rename components/{app => demo}/zoom-dynamic-gradient.png (100%) diff --git a/app/[...all]/page.tsx b/app/[...all]/page.tsx index 005977f..051d760 100644 --- a/app/[...all]/page.tsx +++ b/app/[...all]/page.tsx @@ -1,7 +1,7 @@ import dynamic from 'next/dynamic' // TODO: Find out if this is necessary to be compatible with Ionic & Capacitor -const App = dynamic(() => import('../../components/AppShell'), { +const LazyApp = dynamic(() => import('../../components/App'), { ssr: false, }) @@ -10,5 +10,5 @@ export async function generateStaticParams() { } export default function Page() { - return + return } diff --git a/components/AppShell.tsx b/components/App.tsx similarity index 70% rename from components/AppShell.tsx rename to components/App.tsx index f8b46b6..cc81d06 100644 --- a/components/AppShell.tsx +++ b/components/App.tsx @@ -5,6 +5,7 @@ import { IonReactRouter } from '@ionic/react-router' import { Route } from 'react-router-dom' import Home from './pages/Home' import Constellation from './pages/Constellation' +import ErrorBoundary from './ErrorBoundary' setupIonicReact({}) @@ -18,23 +19,25 @@ window } catch {} }) -const AppShell = () => { +const App = () => { return ( - } - /> - } - /> + + } + /> + } + /> + ) } -export default AppShell +export default App diff --git a/components/ErrorBoundary.tsx b/components/ErrorBoundary.tsx new file mode 100644 index 0000000..3642812 --- /dev/null +++ b/components/ErrorBoundary.tsx @@ -0,0 +1,42 @@ +import { Component, ErrorInfo, ReactNode } from 'react' +import { Header } from './common/Header' + +interface Props { + children?: ReactNode +} + +interface State { + hasError: boolean +} + +class ErrorBoundary extends Component { + public state: State = { + hasError: false, + } + + public static getDerivedStateFromError(_: Error): State { + return { hasError: true } + } + + public componentDidCatch(error: Error, errorInfo: ErrorInfo) { + console.error('Uncaught error:', error, errorInfo) + } + + public render() { + if (this.state.hasError) { + return ( +
+
+

+ Sorry there was an error. If you've unsynced, re-syncing might + fix the issue. +

+
+ ) + } + + return this.props.children + } +} + +export default ErrorBoundary diff --git a/components/common/Header.tsx b/components/common/Header.tsx new file mode 100644 index 0000000..4fd067d --- /dev/null +++ b/components/common/Header.tsx @@ -0,0 +1,156 @@ +import { useObservable } from 'dexie-react-hooks' +import { db } from '../db' +import { + IonButton, + IonButtons, + IonContent, + IonHeader, + IonIcon, + IonImg, + IonInput, + IonItem, + IonList, + IonPopover, + IonTitle, + IonToolbar, +} from '@ionic/react' +import { + cloudDoneSharp, + cloudDownloadSharp, + cloudOfflineSharp, + cloudUploadSharp, + thunderstormSharp, +} from 'ionicons/icons' + +export const Header = ({ title }: { title: string }) => { + const user = useObservable(db.cloud.currentUser) + const syncState = useObservable(db.cloud.syncState) + const isLoggedIn = user?.isLoggedIn + + return ( + + + + {title} + + {isLoggedIn ? ( + <> + + + + + {syncState?.error ? ( +

Sync error: ${syncState.error.message}

+ ) : ( + + + + + + + + + + + + + + + + + + + + + + )} +
+
+
+ { + db.cloud.logout() + }} + > + Unsync + + + ) : ( + <> + + + + + Not synced. Your data is stored locally only. + + + + { + db.cloud.login() + }} + > + Sync + + + )} +
+
+
+ ) +} diff --git a/components/app/ControlPanel.tsx b/components/demo/ControlPanel.tsx similarity index 100% rename from components/app/ControlPanel.tsx rename to components/demo/ControlPanel.tsx diff --git a/components/app/Journey/index.tsx b/components/demo/Journey/index.tsx similarity index 100% rename from components/app/Journey/index.tsx rename to components/demo/Journey/index.tsx diff --git a/components/app/PerformanceSidebar.tsx b/components/demo/PerformanceSidebar.tsx similarity index 100% rename from components/app/PerformanceSidebar.tsx rename to components/demo/PerformanceSidebar.tsx diff --git a/components/app/RoleSidebar.tsx b/components/demo/RoleSidebar.tsx similarity index 100% rename from components/app/RoleSidebar.tsx rename to components/demo/RoleSidebar.tsx diff --git a/components/app/chart-dynamic-gradient.png b/components/demo/chart-dynamic-gradient.png similarity index 100% rename from components/app/chart-dynamic-gradient.png rename to components/demo/chart-dynamic-gradient.png diff --git a/components/app/crown-dynamic-gradient.png b/components/demo/crown-dynamic-gradient.png similarity index 100% rename from components/app/crown-dynamic-gradient.png rename to components/demo/crown-dynamic-gradient.png diff --git a/components/app/index.tsx b/components/demo/index.tsx similarity index 82% rename from components/app/index.tsx rename to components/demo/index.tsx index 9e83b70..da6a41c 100644 --- a/components/app/index.tsx +++ b/components/demo/index.tsx @@ -1,8 +1,8 @@ import { useEffect, useState } from 'react' -import ControlPanel from '../app/ControlPanel' -import Journey from '../app/Journey' -import PerformanceSidebar from '../app/PerformanceSidebar' -import RoleSidebar from '../app/RoleSidebar' +import ControlPanel from './ControlPanel' +import Journey from './Journey' +import PerformanceSidebar from './PerformanceSidebar' +import RoleSidebar from './RoleSidebar' import Planets from '../common/Planets' import Events from '../todos/Events' import useTodos from '../todos/useTodos' @@ -45,10 +45,10 @@ export default function App() { expanded={eventsExpanded} /> -
+
-
+
diff --git a/components/app/setting-dynamic-gradient.png b/components/demo/setting-dynamic-gradient.png similarity index 100% rename from components/app/setting-dynamic-gradient.png rename to components/demo/setting-dynamic-gradient.png diff --git a/components/app/star-front-gradient.png b/components/demo/star-front-gradient.png similarity index 100% rename from components/app/star-front-gradient.png rename to components/demo/star-front-gradient.png diff --git a/components/app/zoom-dynamic-gradient.png b/components/demo/zoom-dynamic-gradient.png similarity index 100% rename from components/app/zoom-dynamic-gradient.png rename to components/demo/zoom-dynamic-gradient.png diff --git a/components/pages/Constellation.tsx b/components/pages/Constellation.tsx index 6989300..2dab02a 100644 --- a/components/pages/Constellation.tsx +++ b/components/pages/Constellation.tsx @@ -21,6 +21,7 @@ import { db } from '../db' import { useCreateStarRoleModal } from '../starRoles/create/useCreateStarRoleModal' import { getIonIcon } from '../starRoles/icons' import { useStarRoleActionSheet } from '../starRoles/StarRoleActionSheet' +import { Header } from '../common/Header' export default function Constellation() { const starRoles = useLiveQuery(() => db.starRoles.toArray()) @@ -42,11 +43,7 @@ export default function Constellation() { return ( - - - Constellation - - +
{isLoading ? (
diff --git a/components/pages/Home.tsx b/components/pages/Home.tsx index 528840e..eece466 100644 --- a/components/pages/Home.tsx +++ b/components/pages/Home.tsx @@ -13,7 +13,6 @@ import { IonGrid, IonHeader, IonIcon, - IonImg, IonInfiniteScroll, IonInfiniteScrollContent, IonInput, @@ -23,7 +22,6 @@ import { IonMenu, IonMenuButton, IonPage, - IonPopover, IonReorder, IonReorderGroup, IonRow, @@ -36,18 +34,13 @@ import { IonToggle, IonToolbar, } from '@ionic/react' -import { useLiveQuery, useObservable } from 'dexie-react-hooks' +import { useLiveQuery } from 'dexie-react-hooks' import { add, checkmarkDoneCircleSharp, - cloudDoneSharp, - cloudDownloadSharp, - cloudOfflineSharp, - cloudUploadSharp, documentText, filterSharp, rocketSharp, - thunderstormSharp, } from 'ionicons/icons' import _ from 'lodash' import { @@ -61,11 +54,12 @@ import { import { db, Todo } from '../db' import NoteProviders from '../notes/providers' import useSettings from '../settings/useSettings' +import { getIonIcon } from '../starRoles/icons' import { SelectedTodoProvider } from '../todos/SelectedTodo' import { useTodoActionSheet } from '../todos/TodoActionSheet' import { useCreateTodoModal } from '../todos/create/useCreateTodoModal' import useView, { ViewProvider } from '../view' -import { getIonIcon } from '../starRoles/icons' +import { Header } from '../common/Header' const Home = () => { const [logLimit, setLogLimit] = useState(7) @@ -106,7 +100,7 @@ const Home = () => { -
+
{ export default Home -export const Header = () => { - const user = useObservable(db.cloud.currentUser) - const syncState = useObservable(db.cloud.syncState) - const isLoggedIn = user?.isLoggedIn - - return ( - - - - Starfocus - - {isLoggedIn ? ( - <> - - - - - {syncState?.error ? ( -

Sync error: ${syncState.error.message}

- ) : ( - - - - - - - - - - - - - - - - - - - - - - )} -
-
-
- { - db.cloud.logout() - }} - > - Unsync - - - ) : ( - <> - - - - - Not synced. Your data is stored locally only. - - - - { - db.cloud.login() - }} - > - Sync - - - )} -
-
-
- ) -} - export const SyncState = () => {} export const MiscMenu = () => { diff --git a/pages/app-demo.tsx b/pages/app-demo.tsx index 7fb5223..de9bb14 100644 --- a/pages/app-demo.tsx +++ b/pages/app-demo.tsx @@ -1,4 +1,4 @@ -import App from '../components/app' +import App from 'next/app' export default function AppDemo() { // useEffect(setupAnimations, [])