2022-04-17 18:44:34 +00:00
import React , { useContext , useEffect , useState } from 'react' ;
import {
BrowserRouter ,
Location ,
Outlet ,
Route ,
Routes ,
useLocation ,
useNavigate
} from 'react-router-dom' ;
import { Sidebar } from './components/file/Sidebar' ;
import { SettingsScreen } from './screens/Settings' ;
import { ExplorerScreen } from './screens/Explorer' ;
import { useCoreEvents } from './hooks/useCoreEvents' ;
import { ErrorBoundary , FallbackProps } from 'react-error-boundary' ;
import { OverviewScreen } from './screens/Overview' ;
2022-04-24 16:50:22 +00:00
import { DebugScreen } from './screens/Debug' ;
2022-04-17 18:44:34 +00:00
import { Modal } from './components/layout/Modal' ;
import GeneralSettings from './screens/settings/GeneralSettings' ;
import SlideUp from './components/transitions/SlideUp' ;
import SecuritySettings from './screens/settings/SecuritySettings' ;
import LocationSettings from './screens/settings/LocationSettings' ;
import { RedirectPage } from './screens/Redirect' ;
import { QueryClient , QueryClientProvider } from 'react-query' ;
2022-04-18 23:06:33 +00:00
import { BaseTransport , ClientProvider , setTransport } from '@sd/client' ;
2022-04-20 05:55:44 +00:00
import { Button } from '@sd/ui' ;
2022-04-17 18:44:34 +00:00
import { CoreEvent } from '@sd/core' ;
2022-04-19 03:35:19 +00:00
import clsx from 'clsx' ;
2022-04-23 17:49:24 +00:00
import './style.scss' ;
2022-04-24 16:50:22 +00:00
import { ContentScreen } from './screens/Content' ;
2022-04-26 23:44:08 +00:00
import LibrarySettings from './screens/settings/LibrarySettings' ;
2022-04-17 18:44:34 +00:00
const queryClient = new QueryClient ( ) ;
export const AppPropsContext = React . createContext < AppProps | null > ( null ) ;
2022-04-18 23:06:33 +00:00
export type Platform = 'browser' | 'macOS' | 'windows' | 'linux' ;
2022-04-17 18:44:34 +00:00
export interface AppProps {
2022-04-18 23:06:33 +00:00
transport : BaseTransport ;
platform : Platform ;
2022-04-17 18:44:34 +00:00
convertFileSrc : ( url : string ) = > string ;
2022-04-19 00:34:39 +00:00
openDialog : ( options : { directory? : boolean } ) = > Promise < string | string [ ] > ;
2022-04-17 18:44:34 +00:00
onClose ? : ( ) = > void ;
onMinimize ? : ( ) = > void ;
onFullscreen ? : ( ) = > void ;
}
function AppLayout() {
const appPropsContext = useContext ( AppPropsContext ) ;
const [ isWindowRounded , setIsWindowRounded ] = useState ( false ) ;
2022-04-19 03:35:19 +00:00
const [ hasWindowBorder , setHasWindowBorder ] = useState ( true ) ;
2022-04-17 18:44:34 +00:00
useEffect ( ( ) = > {
if ( appPropsContext ? . platform === 'macOS' ) {
setIsWindowRounded ( true ) ;
}
2022-04-19 03:35:19 +00:00
if ( appPropsContext ? . platform === 'browser' ) {
setHasWindowBorder ( false ) ;
}
2022-04-17 18:44:34 +00:00
} , [ ] ) ;
return (
< div
2022-04-19 03:35:19 +00:00
className = { clsx (
'flex flex-row h-screen overflow-hidden text-gray-900 bg-white select-none dark:text-white dark:bg-gray-650' ,
isWindowRounded && 'rounded-xl' ,
hasWindowBorder && 'border border-gray-200 dark:border-gray-500'
) }
2022-04-17 18:44:34 +00:00
>
< Sidebar / >
< div className = "flex flex-col w-full min-h-full" >
{ /* <TopBar /> */ }
< div className = "relative flex w-full" >
< Outlet / >
< / div >
< / div >
< / div >
) ;
}
function SettingsRoutes ( { modal = false } ) {
return (
< SlideUp >
< Routes >
< Route
path = { modal ? '/settings' : '/' }
element = { modal ? < Modal children = { < SettingsScreen / > } / > : < SettingsScreen / > }
>
< Route index element = { < GeneralSettings / > } / >
< Route path = "general" element = { < GeneralSettings / > } / >
< Route path = "security" element = { < SecuritySettings / > } / >
< Route path = "appearance" element = { < > < / > } / >
< Route path = "locations" element = { < LocationSettings / > } / >
2022-04-26 23:44:08 +00:00
< Route path = "library" element = { < LibrarySettings / > } / >
2022-04-17 18:44:34 +00:00
< Route path = "media" element = { < > < / > } / >
< Route path = "keys" element = { < > < / > } / >
< Route path = "tags" element = { < > < / > } / >
2022-04-26 18:34:36 +00:00
< Route path = "sync" element = { < > < / > } / >
< Route path = "contacts" element = { < > < / > } / >
2022-04-17 18:44:34 +00:00
< / Route >
< / Routes >
< / SlideUp >
) ;
}
function Router() {
let location = useLocation ( ) ;
let state = location . state as { backgroundLocation? : Location } ;
useEffect ( ( ) = > {
console . log ( { url : location.pathname } ) ;
} , [ state ] ) ;
return (
< >
< Routes location = { state ? . backgroundLocation || location } >
< Route path = "/" element = { < AppLayout / > } >
< Route index element = { < RedirectPage to = "/overview" / > } / >
< Route path = "overview" element = { < OverviewScreen / > } / >
2022-04-24 16:50:22 +00:00
< Route path = "content" element = { < ContentScreen / > } / >
< Route path = "debug" element = { < DebugScreen / > } / >
2022-04-17 18:44:34 +00:00
< Route path = "settings/*" element = { < SettingsRoutes / > } / >
< Route path = "explorer/:id" element = { < ExplorerScreen / > } / >
< Route path = "*" element = { < NotFound / > } / >
< / Route >
< / Routes >
{ state ? . backgroundLocation && < SettingsRoutes modal / > }
< / >
) ;
}
function ErrorFallback ( { error , resetErrorBoundary } : FallbackProps ) {
return (
< div
data - tauri - drag - region
role = "alert"
className = "flex flex-col items-center justify-center w-screen h-screen p-4 border border-gray-200 rounded-lg dark:border-gray-650 bg-gray-50 dark:bg-gray-650 dark:text-white"
>
< p className = "m-3 text-sm font-bold text-gray-400" > APP CRASHED < / p >
< h1 className = "text-2xl font-bold" > We ' re past the event horizon . . . < / h1 >
< pre className = "m-2" > Error : { error . message } < / pre >
< div className = "flex flex-row space-x-2" >
< Button variant = "primary" className = "mt-2" onClick = { resetErrorBoundary } >
Reload
< / Button >
< Button className = "mt-2" onClick = { resetErrorBoundary } >
Send report
< / Button >
< / div >
< / div >
) ;
}
function NotFound() {
const navigate = useNavigate ( ) ;
return (
< div
data - tauri - drag - region
role = "alert"
className = "flex flex-col items-center justify-center w-full h-full p-4 rounded-lg dark:text-white"
>
< p className = "m-3 mt-20 text-sm font-semibold text-gray-500 uppercase" > Error : 404 < / p >
< h1 className = "text-4xl font-bold" > You chose nothingness . < / h1 >
< div className = "flex flex-row space-x-2" >
< Button variant = "primary" className = "mt-4" onClick = { ( ) = > navigate ( - 1 ) } >
Go Back
< / Button >
< / div >
< / div >
) ;
}
function AppContainer() {
useCoreEvents ( ) ;
return (
< BrowserRouter >
< Router / >
< / BrowserRouter >
) ;
}
2022-04-21 08:54:07 +00:00
export function bindCoreEvent() { }
2022-04-17 18:44:34 +00:00
export default function App ( props : AppProps ) {
// @ts-ignore: TODO: This is a hack and a better solution should probably be found. This exists so that the queryClient can be accessed within the subpackage '@sd/client'. Refer to <ClientProvider /> for where this is used.
if ( window . ReactQueryClient === undefined ) {
// @ts-ignore
window . ReactQueryClient = queryClient ;
}
2022-04-23 17:49:24 +00:00
setTransport ( props . transport ) ;
2022-04-18 23:06:33 +00:00
console . log ( 'App props' , props ) ;
2022-04-17 18:44:34 +00:00
return (
< >
{ /* @ts-ignore */ }
< ErrorBoundary FallbackComponent = { ErrorFallback } onReset = { ( ) = > { } } >
{ /* @ts-ignore */ }
< QueryClientProvider client = { queryClient } contextSharing = { false } >
< AppPropsContext.Provider value = { props } >
< ClientProvider >
< AppContainer / >
< / ClientProvider >
< / AppPropsContext.Provider >
< / QueryClientProvider >
< / ErrorBoundary >
< / >
) ;
}