feat: add fallback

This commit is contained in:
0xzio
2025-05-14 21:26:55 +08:00
parent 56d3e3c372
commit a87c35972d
7 changed files with 121 additions and 31 deletions

View File

@@ -40,6 +40,8 @@
"@floating-ui/react": "^0.25.4",
"@glideapps/glide-data-grid": "^6.0.3",
"@hookform/resolvers": "^3.10.0",
"@ionic/react": "^8.5.7",
"@ionic/react-router": "^8.5.7",
"@lingui/core": "5.3.1",
"@lingui/macro": "^5.3.1",
"@lingui/react": "5.3.1",
@@ -73,12 +75,12 @@
"@radix-ui/react-toolbar": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.8",
"@tanstack/react-query": "^5.74.3",
"@tauri-apps/plugin-http": "^2.2.0",
"@tauri-apps/plugin-fs": "2.2.1",
"@tauri-apps/api": "2.5.0",
"@tauri-apps/plugin-dialog": "2.2.1",
"@tauri-apps/plugin-fs": "2.2.1",
"@tauri-apps/plugin-http": "^2.2.0",
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-process": "^2.2.1",
"@tauri-apps/plugin-dialog": "2.2.1",
"@tauri-apps/plugin-updater": "^2.7.1",
"@trpc/client": "11.1.2",
"@trpc/next": "11.1.2",
@@ -135,8 +137,6 @@
"@uiw/react-color": "^2.4.5",
"@uploadthing/react": "7.1.0",
"@vercel/functions": "^2.0.0",
"@ionic/react": "^8.5.7",
"@ionic/react-router": "^8.5.7",
"ai": "^4.1.24",
"array-move": "^4.0.0",
"axios": "^1.7.9",
@@ -228,6 +228,7 @@
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^19.0.0",
"react-error-boundary": "^6.0.0",
"react-fast-compare": "^3.2.2",
"react-grid-layout": "^1.5.1",
"react-hook-form": "^7.54.2",

View File

@@ -0,0 +1,12 @@
import { ReloadAppBtn } from './ReloadAppBtn'
export const Fallback = () => {
return (
<div className='h-[80vh] flex flex-col items-center justify-center gap-1' >
<div className='text-lg text-foreground/60'>
Something went wrong
</div>
<ReloadAppBtn />
</div>
)
}

View File

@@ -0,0 +1,9 @@
import { Button } from '@penx/uikit/ui/button'
export const ReloadAppBtn = () => {
async function reloadApp() {
window.location.reload()
}
return <Button onClick={() => reloadApp()}>Reload App</Button>
}

View File

@@ -1,41 +1,35 @@
'use client'
import { ReactNode, useEffect, useRef } from 'react'
import { nextTick } from 'process'
import { Shape, ShapeStream } from '@electric-sql/client'
import { useQuery } from '@tanstack/react-query'
import { editorDefaultValue } from '@penx/constants'
import { useCreations } from '@penx/hooks/useCreations'
import { useSiteTags } from '@penx/hooks/useSiteTags'
import { useSession } from '@penx/session'
import { Button } from '@penx/uikit/button'
import { ErrorBoundary } from 'react-error-boundary'
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from '@penx/uikit/sidebar'
import { uniqueId } from '@penx/unique-id'
import { Fallback } from '../../Fallback/Fallback'
import { AppSidebar } from '../Sidebar/app-sidebar'
import { PanelList } from './PanelList'
export function PanelLayout({ children }: { children: ReactNode }) {
// useSiteTags()
return (
<SidebarProvider className="">
<AppSidebar className="z-3" />
<SidebarInset className="z-2 relative">
<PanelList />
</SidebarInset>
<ErrorBoundary fallback={<Fallback></Fallback>}>
<SidebarProvider className="">
<AppSidebar className="z-3" />
<SidebarInset className="z-2 relative">
<PanelList />
</SidebarInset>
<div
className="z-1 fixed left-[10%] top-[0px] h-[80vh] w-[100vw] opacity-30 dark:opacity-0"
style={{
filter: 'blur(150px) saturate(150%)',
transform: 'translateZ(0)',
backgroundImage:
'radial-gradient(at 27% 37%, #3a8bfd 0, transparent 50%), radial-gradient(at 97% 21%, #9772fe 0, transparent 50%), radial-gradient(at 52% 99%, #fd3a4e 0, transparent 50%), radial-gradient(at 10% 29%, #5afc7d 0, transparent 50%), radial-gradient(at 97% 96%, #e4c795 0, transparent 50%), radial-gradient(at 33% 50%, #8ca8e8 0, transparent 50%), radial-gradient(at 79% 53%, #eea5ba 0, transparent 50%)',
}}
></div>
</SidebarProvider>
<div
className="z-1 fixed left-[10%] top-[0px] h-[80vh] w-[100vw] opacity-30 dark:opacity-0"
style={{
filter: 'blur(150px) saturate(150%)',
transform: 'translateZ(0)',
backgroundImage:
'radial-gradient(at 27% 37%, #3a8bfd 0, transparent 50%), radial-gradient(at 97% 21%, #9772fe 0, transparent 50%), radial-gradient(at 52% 99%, #fd3a4e 0, transparent 50%), radial-gradient(at 10% 29%, #5afc7d 0, transparent 50%), radial-gradient(at 97% 96%, #e4c795 0, transparent 50%), radial-gradient(at 33% 50%, #8ca8e8 0, transparent 50%), radial-gradient(at 79% 53%, #eea5ba 0, transparent 50%)',
}}
></div>
</SidebarProvider>
</ErrorBoundary>
)
}

View File

@@ -0,0 +1,51 @@
'use client'
import React, { ReactNode } from 'react'
import { XIcon } from 'lucide-react'
import { AnimatePresence, motion } from 'motion/react'
import { Widget } from '@penx/types'
import { Button } from '@penx/uikit/button'
import { IsAllProvider } from './IsAllContext'
import { WidgetRender } from './WidgetRender'
interface Props {
name: ReactNode
visible: boolean
setVisible: any
widget: Widget
}
export function AllCreationCard({ name, visible, setVisible, widget }: Props) {
return (
<AnimatePresence initial={false}>
{visible && (
<motion.div
initial={{ left: -240 }}
animate={{ left: 8 }}
exit={{ left: -240 }}
className="bg-background fixed bottom-2 left-[8px] top-2 z-50 flex w-[240px] flex-col rounded-md shadow-lg"
>
<div className="flex items-center justify-between gap-1 px-3 py-2">
<div className="select-none text-sm font-semibold">{name}</div>
<Button
variant="ghost"
size="icon"
className="size-6 rounded-md"
onClick={() => {
setVisible(false)
}}
>
<XIcon size={16} className="text-foreground/60"></XIcon>
</Button>
</div>
<div className="flex-1 overflow-auto">
<IsAllProvider isAll>
<WidgetRender widget={widget} />
</IsAllProvider>
</div>
</motion.div>
)}
</AnimatePresence>
)
}

View File

@@ -18,6 +18,7 @@ import { WidgetIcon } from '@penx/widgets/WidgetIcon'
import { WidgetName } from '@penx/widgets/WidgetName'
import { QuickInput } from '../QuickInput'
import { AddCreationButton } from './AddCreationButton'
import { AllCreationCard } from './AllCreationCard'
import { IsAllProvider } from './IsAllContext'
import { TitleContextMenu } from './TitleContextMenu'
import { ToggleButton } from './ToggleButton'
@@ -95,7 +96,7 @@ export const WidgetItem = forwardRef<HTMLDivElement, Props>(
return
}
store.panels.openWidgetPanel(widget)
// store.panels.openWidgetPanel(widget)
setVisible(!visible)
}}
>
@@ -163,6 +164,15 @@ export const WidgetItem = forwardRef<HTMLDivElement, Props>(
</AnimatePresence>
</div>
{!isMobileApp && (
<AllCreationCard
name={<WidgetName widget={widget} molds={molds} />}
visible={visible}
setVisible={setVisible}
widget={widget}
/>
)}
{isMobileApp && (
<Drawer.Root open={visible} onOpenChange={setVisible}>
<Drawer.Portal>

13
pnpm-lock.yaml generated
View File

@@ -653,6 +653,9 @@ importers:
react-dom:
specifier: ^19.0.0
version: 19.0.0(react@19.0.0)
react-error-boundary:
specifier: ^6.0.0
version: 6.0.0(react@19.0.0)
react-fast-compare:
specifier: ^3.2.2
version: 3.2.2
@@ -12114,6 +12117,11 @@ packages:
resolution: {integrity: sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg==}
engines: {node: '>= 6'}
react-error-boundary@6.0.0:
resolution: {integrity: sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==}
peerDependencies:
react: '>=16.13.1'
react-fast-compare@3.2.2:
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
@@ -25545,6 +25553,11 @@ snapshots:
dependencies:
prop-types: 15.8.1
react-error-boundary@6.0.0(react@19.0.0):
dependencies:
'@babel/runtime': 7.27.1
react: 19.0.0
react-fast-compare@3.2.2: {}
react-from-dom@0.7.5(react@19.0.0):