Skip to content

Commit

Permalink
reconfigure router
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelcolvin committed Nov 27, 2023
1 parent 1694df8 commit dc1def6
Show file tree
Hide file tree
Showing 17 changed files with 207 additions and 87 deletions.
2 changes: 1 addition & 1 deletion packages/fastui/src/components/MarkdownLazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import remarkGfm from 'remark-gfm'
import type { MarkdownProps } from './Markdown'

import { useClassName } from '../hooks/className'
import { useFireEvent, AnyEvent } from '../hooks/events'
import { useFireEvent, AnyEvent } from '../events'
import { useCustomRender } from '../hooks/config'

import { CodeProps, CodeComp } from './Code'
Expand Down
40 changes: 30 additions & 10 deletions packages/fastui/src/components/ServerLoad.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,62 @@
import { FC, useContext, useEffect, useState } from 'react'

import { ErrorContext } from '../hooks/error'
import { ReloadContext } from '../hooks/dev'
import { useRequest } from '../tools'
import { DefaultLoading } from '../DefaultLoading'
import { ConfigContext } from '../hooks/config'
import { PageEvent, useEventListenerToggle } from '../events'

import { AnyCompList, FastProps } from './index'

export interface ServerLoadProps {
type: 'ServerLoad'
url: string
path: string
components?: FastProps[]
loadTrigger?: PageEvent
}
export const ServerLoadComp: FC<ServerLoadProps> = ({ path, components, loadTrigger }) => {
if (components) {
return <ServerLoadDefer path={path} components={components} loadTrigger={loadTrigger} />
} else {
return <ServerLoadDirect path={path} />
}
}

const ServerLoadDefer: FC<{ path: string; components: FastProps[]; loadTrigger?: PageEvent }> = ({
components,
path,
loadTrigger,
}) => {
const [loadFromServer] = useEventListenerToggle(loadTrigger)

if (loadFromServer) {
return <ServerLoadDirect path={path} />
} else {
return <AnyCompList propsList={components} />
}
}

export const ServerLoadComp: FC<ServerLoadProps> = ({ url }) => {
export const ServerLoadDirect: FC<{ path: string; devReload?: number }> = ({ path, devReload }) => {
const [componentProps, setComponentProps] = useState<FastProps[] | null>(null)

const { error, setError } = useContext(ErrorContext)
const reloadValue = useContext(ReloadContext)
const { error } = useContext(ErrorContext)
const { rootUrl, pathSendMode, Loading } = useContext(ConfigContext)
const request = useRequest()

useEffect(() => {
let fetchUrl = rootUrl
if (pathSendMode === 'query') {
fetchUrl += `?path=${encodeURIComponent(url)}`
fetchUrl += `?path=${encodeURIComponent(path)}`
} else {
fetchUrl += url
fetchUrl += path
}

const promise = request({ url: fetchUrl })

promise.then(([, data]) => setComponentProps(data as FastProps[]))

return () => {
promise.then(() => null)
}
}, [rootUrl, pathSendMode, url, setError, reloadValue, request])
}, [rootUrl, pathSendMode, path, request, devReload])

if (componentProps === null) {
if (error) {
Expand Down
2 changes: 1 addition & 1 deletion packages/fastui/src/components/button.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FC } from 'react'

import { ClassName, useClassName } from '../hooks/className'
import { useFireEvent, AnyEvent } from '../hooks/events'
import { useFireEvent, AnyEvent } from '../events'

export interface ButtonProps {
type: 'Button'
Expand Down
2 changes: 1 addition & 1 deletion packages/fastui/src/components/form.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FC, FormEvent, useState } from 'react'

import { ClassName, useClassName } from '../hooks/className'
import { useFireEvent, AnyEvent } from '../hooks/events'
import { useFireEvent, AnyEvent } from '../events'
import { useRequest } from '../tools'

import { FastProps, AnyCompList } from './index'
Expand Down
2 changes: 1 addition & 1 deletion packages/fastui/src/components/link.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FC, MouseEventHandler, ReactNode } from 'react'

import { ClassName, useClassName } from '../hooks/className'
import { useFireEvent, AnyEvent } from '../hooks/events'
import { useFireEvent, AnyEvent } from '../events'

import { FastProps, AnyCompList } from './index'

Expand Down
2 changes: 1 addition & 1 deletion packages/fastui/src/components/modal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FC, useEffect } from 'react'

import { ClassName } from '../hooks/className'
import { PageEvent, useEventListenerToggle } from '../hooks/events'
import { PageEvent, useEventListenerToggle } from '../events'

import { FastProps } from './index'

Expand Down
2 changes: 1 addition & 1 deletion packages/fastui/src/components/navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ClassName, useClassName } from '../hooks/className'
import { AnyEvent } from '../hooks/events'
import { AnyEvent } from '../events'

import { LinkProps, LinkComp, LinkRender } from './link'

Expand Down
2 changes: 1 addition & 1 deletion packages/fastui/src/components/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { JsonData } from './Json'

import { DisplayChoices, asTitle } from '../display'
import { ClassName, useClassName } from '../hooks/className'
import { AnyEvent } from '../hooks/events'
import { AnyEvent } from '../events'

import { DisplayComp } from './display'
import { LinkRender } from './link'
Expand Down
24 changes: 21 additions & 3 deletions packages/fastui/src/controller.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
import { useContext } from 'react'
import { useContext, useEffect, useState } from 'react'

import { LocationContext } from './hooks/locationContext'
import { ServerLoadComp } from './components/ServerLoad'
import { ServerLoadDirect } from './components/ServerLoad'
import { loadEvent, LoadEventDetail } from './events'

export function FastUIController() {
const { fullPath } = useContext(LocationContext)
const [path, setPath] = useState(fullPath)
const [reloadValue, setReloadValue] = useState(0)

return <ServerLoadComp type="ServerLoad" url={fullPath} />
useEffect(() => {
function onEvent(e: Event) {
const { path, reloadValue } = (e as CustomEvent<LoadEventDetail>).detail

setPath(path ?? fullPath)
setReloadValue(reloadValue ?? 0)
}

document.addEventListener(loadEvent, onEvent)

return () => {
document.removeEventListener(loadEvent, onEvent)
}
}, [fullPath])

return <ServerLoadDirect path={path} devReload={reloadValue} />
}
49 changes: 29 additions & 20 deletions packages/fastui/src/hooks/dev.tsx → packages/fastui/src/dev.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
import { createContext, FC, ReactNode, useContext, useEffect, useState } from 'react'
import { FC, useContext, useEffect } from 'react'

import { ErrorContext } from './error'
import { sleep } from './tools'
import { ErrorContext } from './hooks/error'
import { fireLoadEvent } from './events'

export const ReloadContext = createContext<number>(0)
let devConnected = false

export const DevReloadProvider: FC<{ children: ReactNode; enabled?: boolean }> = ({ children, enabled }) => {
const [value, setValue] = useState<number>(0)
const { setError } = useContext(ErrorContext)
export const DevReload: FC<{ enabled?: boolean }> = ({ enabled }) => {
if (typeof enabled === 'undefined') {
enabled = process.env.NODE_ENV === 'development'
}

if (enabled) {
return <DevReloadActive />
} else {
return <></>
}
}

const DevReloadActive = () => {
const { setError } = useContext(ErrorContext)

useEffect(() => {
let listening = true
let lastValue = 0

async function listen() {
let count = 0
let failCount = 0
Expand All @@ -32,37 +43,35 @@ export const DevReloadProvider: FC<{ children: ReactNode; enabled?: boolean }> =
}
// await like this means we wait for the entire response to be received
const text = await response.text()
const value = parseInt(text.replace(/\./g, '')) || 0
if (response.status === 404) {
console.log('dev reload endpoint not found, disabling dev reload')
return count
} else if (response.ok) {
failCount = 0
// wait long enough for the server to be back online
await sleep(300)
console.debug('dev reloading')
setValue(value)
setError(null)
const value = parseInt(text.replace(/\./g, '')) || 0
if (value !== lastValue) {
lastValue = value
// wait long enough for the server to be back online
await sleep(300)
console.debug('dev reloading')
fireLoadEvent({ reloadValue: value })
setError(null)
}
} else {
failCount++
await sleep(2000)
}
}
}

if (enabled && !devConnected) {
if (!devConnected) {
devConnected = true
listen().then((count) => count > 0 && console.debug('dev reload disconnected.'))
return () => {
listening = false
devConnected = false
}
}
}, [enabled, setError])

return <ReloadContext.Provider value={value}>{children}</ReloadContext.Provider>
}

async function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms))
}, [setError])
return <></>
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useContext, useState, useEffect, useCallback } from 'react'

import { LocationContext } from './locationContext'
import { LocationContext } from './hooks/locationContext'

export interface PageEvent {
type: 'page'
name: string
pushPath?: string
}

export interface GoToEvent {
Expand Down Expand Up @@ -33,6 +34,9 @@ export function useFireEvent(): { fireEvent: (event?: AnyEvent) => void } {
const { type } = event
switch (type) {
case 'page':
if (event.pushPath) {
location.gotoCosmetic(event.pushPath)
}
document.dispatchEvent(new CustomEvent(pageEventType(event)))
break
case 'go-to':
Expand All @@ -47,6 +51,17 @@ export function useFireEvent(): { fireEvent: (event?: AnyEvent) => void } {
return { fireEvent }
}

export const loadEvent = 'fastui:load'

export interface LoadEventDetail {
path?: string
reloadValue?: number
}

export function fireLoadEvent(detail: LoadEventDetail) {
document.dispatchEvent(new CustomEvent(loadEvent, { detail }))
}

export function useEventListenerToggle(event?: PageEvent, initialState = false): [boolean, () => void] {
const [state, setState] = useState(initialState)

Expand Down
Loading

0 comments on commit dc1def6

Please sign in to comment.