192 lines
9.1 KiB
TypeScript
192 lines
9.1 KiB
TypeScript
import React, { createContext, ReactElement, useContext, useMemo, useReducer } from 'react';
|
|
|
|
import { IEmoji } from '../../definitions';
|
|
import { IAutocompleteBase, TMicOrSend } from './interfaces';
|
|
import { animateNextTransition } from '../../lib/methods/helpers';
|
|
|
|
type TMessageComposerContextApi = {
|
|
setHeight: (keyboardHeight: number, trackingViewHeight: number) => void;
|
|
openEmojiKeyboard(): void;
|
|
closeEmojiKeyboard(): void;
|
|
openSearchEmojiKeyboard(): void;
|
|
closeSearchEmojiKeyboard(): void;
|
|
setFocused(focused: boolean): void;
|
|
setMicOrSend(micOrSend: TMicOrSend): void;
|
|
setMarkdownToolbar(showMarkdownToolbar: boolean): void;
|
|
setAlsoSendThreadToChannel(alsoSendThreadToChannel: boolean): void;
|
|
setRecordingAudio(recordingAudio: boolean): void;
|
|
setAutocompleteParams(params: IAutocompleteBase): void;
|
|
};
|
|
|
|
const FocusedContext = createContext<State['focused']>({} as State['focused']);
|
|
const MicOrSendContext = createContext<State['micOrSend']>({} as State['micOrSend']);
|
|
const ShowMarkdownToolbarContext = createContext<State['showMarkdownToolbar']>({} as State['showMarkdownToolbar']);
|
|
const ShowEmojiKeyboardContext = createContext<State['showEmojiKeyboard']>({} as State['showEmojiKeyboard']);
|
|
const ShowEmojiSearchbarContext = createContext<State['showEmojiSearchbar']>({} as State['showEmojiSearchbar']);
|
|
const KeyboardHeightContext = createContext<State['keyboardHeight']>({} as State['keyboardHeight']);
|
|
const TrackingViewHeightContext = createContext<State['trackingViewHeight']>({} as State['trackingViewHeight']);
|
|
const AlsoSendThreadToChannelContext = createContext<State['alsoSendThreadToChannel']>({} as State['alsoSendThreadToChannel']);
|
|
const RecordingAudioContext = createContext<State['recordingAudio']>({} as State['recordingAudio']);
|
|
const AutocompleteParamsContext = createContext<State['autocompleteParams']>({} as State['autocompleteParams']);
|
|
const MessageComposerContextApi = createContext<TMessageComposerContextApi>({} as TMessageComposerContextApi);
|
|
|
|
export const useMessageComposerApi = (): TMessageComposerContextApi => useContext(MessageComposerContextApi);
|
|
export const useFocused = (): State['focused'] => useContext(FocusedContext);
|
|
export const useMicOrSend = (): State['micOrSend'] => useContext(MicOrSendContext);
|
|
export const useShowMarkdownToolbar = (): State['showMarkdownToolbar'] => useContext(ShowMarkdownToolbarContext);
|
|
export const useShowEmojiKeyboard = (): State['showEmojiKeyboard'] => useContext(ShowEmojiKeyboardContext);
|
|
export const useShowEmojiSearchbar = (): State['showEmojiSearchbar'] => useContext(ShowEmojiSearchbarContext);
|
|
export const useKeyboardHeight = (): State['keyboardHeight'] => useContext(KeyboardHeightContext);
|
|
export const useTrackingViewHeight = (): State['trackingViewHeight'] => useContext(TrackingViewHeightContext);
|
|
export const useAlsoSendThreadToChannel = (): State['alsoSendThreadToChannel'] => useContext(AlsoSendThreadToChannelContext);
|
|
export const useRecordingAudio = (): State['recordingAudio'] => useContext(RecordingAudioContext);
|
|
export const useAutocompleteParams = (): State['autocompleteParams'] => useContext(AutocompleteParamsContext);
|
|
|
|
// TODO: rename
|
|
type TMessageInnerContext = {
|
|
sendMessage(): void;
|
|
onEmojiSelected(emoji: IEmoji): void;
|
|
// TODO: action should be required
|
|
closeEmojiKeyboardAndAction(action?: Function, params?: any): void;
|
|
};
|
|
|
|
// TODO: rename
|
|
export const MessageInnerContext = createContext<TMessageInnerContext>({
|
|
sendMessage: () => {},
|
|
onEmojiSelected: () => {},
|
|
closeEmojiKeyboardAndAction: () => {}
|
|
});
|
|
|
|
type State = {
|
|
showEmojiKeyboard: boolean;
|
|
showEmojiSearchbar: boolean;
|
|
focused: boolean;
|
|
trackingViewHeight: number;
|
|
keyboardHeight: number;
|
|
micOrSend: TMicOrSend;
|
|
showMarkdownToolbar: boolean;
|
|
alsoSendThreadToChannel: boolean;
|
|
recordingAudio: boolean;
|
|
autocompleteParams: IAutocompleteBase;
|
|
};
|
|
|
|
type Actions =
|
|
| { type: 'updateEmojiKeyboard'; showEmojiKeyboard: boolean }
|
|
| { type: 'updateEmojiSearchbar'; showEmojiSearchbar: boolean }
|
|
| { type: 'updateFocused'; focused: boolean }
|
|
| { type: 'updateHeight'; trackingViewHeight: number; keyboardHeight: number }
|
|
| { type: 'openEmojiKeyboard' }
|
|
| { type: 'closeEmojiKeyboard' }
|
|
| { type: 'openSearchEmojiKeyboard' }
|
|
| { type: 'closeSearchEmojiKeyboard' }
|
|
| { type: 'setMicOrSend'; micOrSend: TMicOrSend }
|
|
| { type: 'setMarkdownToolbar'; showMarkdownToolbar: boolean }
|
|
| { type: 'setAlsoSendThreadToChannel'; alsoSendThreadToChannel: boolean }
|
|
| { type: 'setRecordingAudio'; recordingAudio: boolean }
|
|
| { type: 'setAutocompleteParams'; params: IAutocompleteBase };
|
|
|
|
const reducer = (state: State, action: Actions): State => {
|
|
switch (action.type) {
|
|
case 'updateEmojiKeyboard':
|
|
return { ...state, showEmojiKeyboard: action.showEmojiKeyboard };
|
|
case 'updateEmojiSearchbar':
|
|
return { ...state, showEmojiSearchbar: action.showEmojiSearchbar };
|
|
case 'updateFocused':
|
|
animateNextTransition();
|
|
return { ...state, focused: action.focused };
|
|
case 'updateHeight':
|
|
return { ...state, trackingViewHeight: action.trackingViewHeight, keyboardHeight: action.keyboardHeight };
|
|
case 'openEmojiKeyboard':
|
|
return { ...state, showEmojiKeyboard: true, showEmojiSearchbar: false };
|
|
case 'openSearchEmojiKeyboard':
|
|
return { ...state, showEmojiKeyboard: false, showEmojiSearchbar: true };
|
|
case 'closeEmojiKeyboard':
|
|
return { ...state, showEmojiKeyboard: false, showEmojiSearchbar: false };
|
|
case 'closeSearchEmojiKeyboard':
|
|
return { ...state, showEmojiSearchbar: false };
|
|
case 'setMicOrSend':
|
|
return { ...state, micOrSend: action.micOrSend };
|
|
case 'setMarkdownToolbar':
|
|
animateNextTransition();
|
|
return { ...state, showMarkdownToolbar: action.showMarkdownToolbar };
|
|
case 'setAlsoSendThreadToChannel':
|
|
return { ...state, alsoSendThreadToChannel: action.alsoSendThreadToChannel };
|
|
case 'setRecordingAudio':
|
|
animateNextTransition();
|
|
return { ...state, recordingAudio: action.recordingAudio };
|
|
case 'setAutocompleteParams':
|
|
return { ...state, autocompleteParams: action.params };
|
|
}
|
|
};
|
|
|
|
export const MessageComposerProvider = ({ children }: { children: ReactElement }): ReactElement => {
|
|
const [state, dispatch] = useReducer(reducer, { keyboardHeight: 0, autocompleteParams: { text: '', type: null } } as State);
|
|
|
|
const api = useMemo(() => {
|
|
const setFocused: TMessageComposerContextApi['setFocused'] = focused => dispatch({ type: 'updateFocused', focused });
|
|
|
|
const setHeight: TMessageComposerContextApi['setHeight'] = (keyboardHeight, trackingViewHeight) =>
|
|
dispatch({ type: 'updateHeight', keyboardHeight, trackingViewHeight });
|
|
|
|
const openEmojiKeyboard = () => dispatch({ type: 'openEmojiKeyboard' });
|
|
|
|
const closeEmojiKeyboard = () => dispatch({ type: 'closeEmojiKeyboard' });
|
|
|
|
const openSearchEmojiKeyboard = () => dispatch({ type: 'openSearchEmojiKeyboard' });
|
|
|
|
const closeSearchEmojiKeyboard = () => dispatch({ type: 'closeSearchEmojiKeyboard' });
|
|
|
|
const setMicOrSend: TMessageComposerContextApi['setMicOrSend'] = micOrSend => dispatch({ type: 'setMicOrSend', micOrSend });
|
|
|
|
const setMarkdownToolbar: TMessageComposerContextApi['setMarkdownToolbar'] = showMarkdownToolbar =>
|
|
dispatch({ type: 'setMarkdownToolbar', showMarkdownToolbar });
|
|
|
|
const setAlsoSendThreadToChannel: TMessageComposerContextApi['setAlsoSendThreadToChannel'] = alsoSendThreadToChannel =>
|
|
dispatch({ type: 'setAlsoSendThreadToChannel', alsoSendThreadToChannel });
|
|
|
|
const setRecordingAudio: TMessageComposerContextApi['setRecordingAudio'] = recordingAudio =>
|
|
dispatch({ type: 'setRecordingAudio', recordingAudio });
|
|
|
|
const setAutocompleteParams: TMessageComposerContextApi['setAutocompleteParams'] = params =>
|
|
dispatch({ type: 'setAutocompleteParams', params });
|
|
|
|
return {
|
|
setFocused,
|
|
setHeight,
|
|
openEmojiKeyboard,
|
|
closeEmojiKeyboard,
|
|
openSearchEmojiKeyboard,
|
|
closeSearchEmojiKeyboard,
|
|
setMicOrSend,
|
|
setMarkdownToolbar,
|
|
setAlsoSendThreadToChannel,
|
|
setRecordingAudio,
|
|
setAutocompleteParams
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<MessageComposerContextApi.Provider value={api}>
|
|
<ShowEmojiKeyboardContext.Provider value={state.showEmojiKeyboard}>
|
|
<ShowEmojiSearchbarContext.Provider value={state.showEmojiSearchbar}>
|
|
<FocusedContext.Provider value={state.focused}>
|
|
<KeyboardHeightContext.Provider value={state.keyboardHeight}>
|
|
<TrackingViewHeightContext.Provider value={state.trackingViewHeight}>
|
|
<ShowMarkdownToolbarContext.Provider value={state.showMarkdownToolbar}>
|
|
<AlsoSendThreadToChannelContext.Provider value={state.alsoSendThreadToChannel}>
|
|
<RecordingAudioContext.Provider value={state.recordingAudio}>
|
|
<AutocompleteParamsContext.Provider value={state.autocompleteParams}>
|
|
<MicOrSendContext.Provider value={state.micOrSend}>{children}</MicOrSendContext.Provider>
|
|
</AutocompleteParamsContext.Provider>
|
|
</RecordingAudioContext.Provider>
|
|
</AlsoSendThreadToChannelContext.Provider>
|
|
</ShowMarkdownToolbarContext.Provider>
|
|
</TrackingViewHeightContext.Provider>
|
|
</KeyboardHeightContext.Provider>
|
|
</FocusedContext.Provider>
|
|
</ShowEmojiSearchbarContext.Provider>
|
|
</ShowEmojiKeyboardContext.Provider>
|
|
</MessageComposerContextApi.Provider>
|
|
);
|
|
};
|