From 7486cb72ad83764132450f13156f37118dd02c25 Mon Sep 17 00:00:00 2001 From: Pavel Prichodko <14926950+prichodko@users.noreply.github.com> Date: Tue, 28 Feb 2023 14:56:21 +0100 Subject: [PATCH] add unified provider --- packages/components/src/index.tsx | 1 + .../components/src/provider/app-context.tsx | 67 +++++++++++++++++ .../components/src/provider/chat-context.tsx | 74 +++++++++++++++++++ packages/components/src/provider/index.tsx | 3 + packages/components/src/provider/provider.tsx | 23 ++++++ .../components/src/provider/theme-context.tsx | 24 ++++++ 6 files changed, 192 insertions(+) create mode 100644 packages/components/src/provider/app-context.tsx create mode 100644 packages/components/src/provider/chat-context.tsx create mode 100644 packages/components/src/provider/index.tsx create mode 100644 packages/components/src/provider/provider.tsx create mode 100644 packages/components/src/provider/theme-context.tsx diff --git a/packages/components/src/index.tsx b/packages/components/src/index.tsx index e7d1daa1..8296bf9d 100644 --- a/packages/components/src/index.tsx +++ b/packages/components/src/index.tsx @@ -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' diff --git a/packages/components/src/provider/app-context.tsx b/packages/components/src/provider/app-context.tsx new file mode 100644 index 00000000..48f58aa8 --- /dev/null +++ b/packages/components/src/provider/app-context.tsx @@ -0,0 +1,67 @@ +import { createContext, useContext, useReducer } from 'react' + +/* + * CONTEXT + */ +const DispatchContext = createContext | undefined>( + undefined +) +const StateContext = createContext(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 ( + + {children} + + ) +} + +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 } diff --git a/packages/components/src/provider/chat-context.tsx b/packages/components/src/provider/chat-context.tsx new file mode 100644 index 00000000..59e6a6f3 --- /dev/null +++ b/packages/components/src/provider/chat-context.tsx @@ -0,0 +1,74 @@ +import { createContext, useContext, useReducer } from 'react' + +/* + * CONTEXT + */ +const DispatchContext = createContext | undefined>( + undefined +) +const StateContext = createContext(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 ( + + {children} + + ) +} + +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 } diff --git a/packages/components/src/provider/index.tsx b/packages/components/src/provider/index.tsx new file mode 100644 index 00000000..e481efc8 --- /dev/null +++ b/packages/components/src/provider/index.tsx @@ -0,0 +1,3 @@ +export { useAppDispatch, useAppState } from './app-context' +export { useChatDispatch, useChatState } from './chat-context' +export { Provider } from './provider' diff --git a/packages/components/src/provider/provider.tsx b/packages/components/src/provider/provider.tsx new file mode 100644 index 00000000..d9da81bc --- /dev/null +++ b/packages/components/src/provider/provider.tsx @@ -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 ( + + + {children} + + + ) +} + +export { Provider } diff --git a/packages/components/src/provider/theme-context.tsx b/packages/components/src/provider/theme-context.tsx new file mode 100644 index 00000000..92c6ff60 --- /dev/null +++ b/packages/components/src/provider/theme-context.tsx @@ -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 + + {children} + + ) +} + +export { ThemeProvider } +export type ThemeProviderProps = Omit +export type { Theme }