add unified provider
This commit is contained in:
parent
c0dc3b4497
commit
7486cb72ad
|
@ -6,6 +6,7 @@ export * from './icon-button'
|
|||
export * from './image'
|
||||
export * from './input'
|
||||
export * from './messages'
|
||||
export * from './provider'
|
||||
export * from './sidebar'
|
||||
export * from './sidebar-members'
|
||||
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