= {
+ welcome: { type: 'channel' },
+ general: { type: 'channel' },
+ random: { type: 'channel' },
+ 'vitalik.eth': { type: 'chat' },
+ 'pvl.eth': { type: 'chat' },
+ 'Climate Change': { type: 'group-chat' },
+}
+
+export const Navbar = (props: Props) => {
+ const { enableMembers } = props
+
+ const { state, dispatch } = useAppState()
+ const { params } = useMatch(':id')! // eslint-disable-line @typescript-eslint/no-non-null-assertion
+
+ const chat = chats[params.id!]
+
+ const renderIdentity = () => {
+ if (chat.type == 'channel') {
+ return (
+
+
+
+ #general
+
+ 2 pinned messages | General discussions about CryptoKitties.
+
+
+
+ )
+ }
+
+ if (chat.type == 'group-chat') {
+ return (
+
+
+
+ Climate Change
+
+ 3 pinned messages | 5 members
+
+
+
+ )
+ }
+
+ return (
+
+
+
+ pvl.eth
+
+ 0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377
+
+
+
+ )
+ }
+
+ const renderMenuItems = () => {
+ if (chat.type === 'channel') {
+ return (
+ <>
+ }>
+ For 15 min
+ For 1 hour
+ For 8 hours
+ For 24 hours
+ Until I turn it back on
+
+ }>
+ Mark as Read
+
+ >
+ )
+ }
+ return (
+ <>
+ {chat.type === 'chat' && (
+ }>
+ View Profile
+
+ )}
+ {chat.type === 'group-chat' && (
+ }>Edit Group
+ )}
+
+ {chat.type === 'group-chat' && (
+ }>
+ Customize Chat
+
+ )}
+ }>
+ For 15 min
+ For 1 hour
+ For 8 hours
+ For 24 hours
+ Until I turn it back on
+
+ }>Mark as Read
+ }>
+ Last 24 hours
+ Last 2 days
+ Last 3 days
+ Last 7 days
+
+
+ {chat.type === 'chat' && (
+ } danger>
+ Delete Chat
+
+ )}
+ {chat.type === 'group-chat' && (
+ } danger>
+ Leave Chat
+
+ )}
+ >
+ )
+ }
+
+ return (
+
+ {renderIdentity()}
+
+
+ {enableMembers && (
+ dispatch({ type: 'TOGGLE_MEMBERS' })}
+ >
+
+
+ )}
+
+
+
+
+
+ {renderMenuItems()}
+
+
+
+
+
+
+
+
+
+ )
+}
+
+const NavbarWrapper = styled('div', {
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ padding: '10px 16px',
+})
diff --git a/packages/status-react/src/contexts/chat-context.tsx b/packages/status-react/src/contexts/chat-context.tsx
new file mode 100644
index 0000000..99d057b
--- /dev/null
+++ b/packages/status-react/src/contexts/chat-context.tsx
@@ -0,0 +1,62 @@
+import React, { createContext, useContext, useMemo, useReducer } from 'react'
+
+import type { Dispatch, Reducer } from 'react'
+
+type Context = {
+ state: State
+ dispatch: Dispatch
+}
+
+const ChatContext = createContext(undefined)
+
+// TODO: Take from generated protobuf
+export interface Message {
+ type: 'text' | 'image' | 'image-text'
+ text?: string
+}
+
+interface State {
+ message?: Message
+}
+
+type Action =
+ | { type: 'SET_REPLY'; message?: Message }
+ | { type: 'CANCEL_REPLY' }
+
+const reducer: Reducer = (state, action) => {
+ switch (action.type) {
+ case 'SET_REPLY': {
+ return { ...state, message: action.message }
+ }
+ case 'CANCEL_REPLY': {
+ return { ...state, message: undefined }
+ }
+ }
+}
+
+const initialState: State = {
+ message: undefined,
+}
+
+interface Props {
+ children: React.ReactNode
+}
+
+export const ChatProvider = (props: Props) => {
+ const { children } = props
+
+ const [state, dispatch] = useReducer(reducer, initialState)
+ const value = useMemo(() => ({ state, dispatch }), [state])
+
+ return {children}
+}
+
+export const useChatState = () => {
+ const context = useContext(ChatContext)
+
+ if (!context) {
+ throw new Error('useChatState must be used within a ChatProvider')
+ }
+
+ return context
+}