add unified provider
This commit is contained in:
parent
2d2938c057
commit
3625fa355a
|
@ -6,6 +6,7 @@ export * from './icon-button'
|
||||||
export * from './image'
|
export * from './image'
|
||||||
export * from './input'
|
export * from './input'
|
||||||
export * from './messages'
|
export * from './messages'
|
||||||
|
export * from './provider'
|
||||||
export * from './sidebar'
|
export * from './sidebar'
|
||||||
export * from './sidebar-members'
|
export * from './sidebar-members'
|
||||||
export * from './topbar'
|
export * from './topbar'
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { createContext, useContext, useReducer } from 'react'
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CONTEXT
|
||||||
|
*/
|
||||||
|
const DispatchContext = createContext<React.Dispatch<Action> | undefined>(
|
||||||
|
undefined
|
||||||
|
)
|
||||||
|
const StateContext = createContext<State | undefined>(undefined)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* REDUCER
|
||||||
|
*/
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
channelId?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Action = { type: 'set-channel'; channelId: string }
|
||||||
|
|
||||||
|
const reducer = (_state: State, action: Action): State => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'set-channel': {
|
||||||
|
return { channelId: action.channelId }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppProvider = (props: Props) => {
|
||||||
|
const { children } = props
|
||||||
|
|
||||||
|
const [state, dispatch] = useReducer(reducer, { channelId: 'welcome' })
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DispatchContext.Provider value={dispatch}>
|
||||||
|
<StateContext.Provider value={state}>{children}</StateContext.Provider>
|
||||||
|
</DispatchContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const useAppState = (): State => {
|
||||||
|
const context = useContext(StateContext)
|
||||||
|
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error('useMessagesState must be used within a MessagesProvider')
|
||||||
|
}
|
||||||
|
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
const useAppDispatch = () => {
|
||||||
|
const context = useContext(DispatchContext)
|
||||||
|
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error(
|
||||||
|
'useMessagesDispatch must be used within a MessagesProvider'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
export { AppProvider, useAppDispatch, useAppState }
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { createContext, useContext, useReducer } from 'react'
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CONTEXT
|
||||||
|
*/
|
||||||
|
const DispatchContext = createContext<React.Dispatch<Action> | undefined>(
|
||||||
|
undefined
|
||||||
|
)
|
||||||
|
const StateContext = createContext<State | null>(null)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* REDUCER
|
||||||
|
*/
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
type: 'edit' | 'reply'
|
||||||
|
messageId: string
|
||||||
|
} | null
|
||||||
|
|
||||||
|
type Action =
|
||||||
|
| { type: 'edit'; messageId: string }
|
||||||
|
| { type: 'reply'; messageId: string }
|
||||||
|
| { type: 'cancel' }
|
||||||
|
|
||||||
|
const reducer = (_state: State, action: Action): State => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'edit':
|
||||||
|
return { type: 'edit', messageId: action.messageId }
|
||||||
|
case 'reply':
|
||||||
|
return { type: 'reply', messageId: action.messageId }
|
||||||
|
case 'cancel':
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChatProvider = (props: Props) => {
|
||||||
|
const { children } = props
|
||||||
|
|
||||||
|
const [state, dispatch] = useReducer(reducer, null)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DispatchContext.Provider value={dispatch}>
|
||||||
|
<StateContext.Provider value={state}>{children}</StateContext.Provider>
|
||||||
|
</DispatchContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const useChatState = (): State => {
|
||||||
|
const context = useContext(StateContext)
|
||||||
|
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error('useMessagesState must be used within a MessagesProvider')
|
||||||
|
}
|
||||||
|
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
const useChatDispatch = () => {
|
||||||
|
const context = useContext(DispatchContext)
|
||||||
|
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error(
|
||||||
|
'useMessagesDispatch must be used within a MessagesProvider'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ChatProvider, useChatDispatch, useChatState }
|
|
@ -0,0 +1,3 @@
|
||||||
|
export { useAppDispatch, useAppState } from './app-context'
|
||||||
|
export { useChatDispatch, useChatState } from './chat-context'
|
||||||
|
export { Provider } from './provider'
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { AppProvider } from './app-context'
|
||||||
|
import { ChatProvider } from './chat-context'
|
||||||
|
import { ThemeProvider } from './theme-context'
|
||||||
|
|
||||||
|
import type { ThemeProviderProps } from './theme-context'
|
||||||
|
|
||||||
|
type Props = ThemeProviderProps & {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const Provider = (props: Props) => {
|
||||||
|
const { children } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider defaultTheme={props.defaultTheme}>
|
||||||
|
<AppProvider>
|
||||||
|
<ChatProvider>{children}</ChatProvider>
|
||||||
|
</AppProvider>
|
||||||
|
</ThemeProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Provider }
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { TamaguiProvider } from '@tamagui/core'
|
||||||
|
|
||||||
|
import { config } from '../tamagui.config'
|
||||||
|
|
||||||
|
type Theme = 'light' | 'dark'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: React.ReactNode
|
||||||
|
defaultTheme?: Theme
|
||||||
|
}
|
||||||
|
|
||||||
|
const ThemeProvider = (props: Props) => {
|
||||||
|
const { children, defaultTheme = 'light' } = props
|
||||||
|
return (
|
||||||
|
// TODO: store theme in localStorage
|
||||||
|
<TamaguiProvider config={config} defaultTheme={defaultTheme}>
|
||||||
|
{children}
|
||||||
|
</TamaguiProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ThemeProvider }
|
||||||
|
export type ThemeProviderProps = Omit<Props, 'children'>
|
||||||
|
export type { Theme }
|
Loading…
Reference in New Issue