From 0e5bedc51c6a21e00be587893a3afdacec542610 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Fri, 2 Oct 2020 09:45:09 +0300 Subject: [PATCH] Add a global message queue that shows a snackbar. --- src/MainRouter.tsx | 81 +++++++++++++++++++++++++++++------------- src/store/actions.ts | 15 ++++++++ src/store/construct.ts | 6 ++-- src/store/reducers.ts | 17 +++++++++ 4 files changed, 92 insertions(+), 27 deletions(-) diff --git a/src/MainRouter.tsx b/src/MainRouter.tsx index b57be8a..ccaca72 100644 --- a/src/MainRouter.tsx +++ b/src/MainRouter.tsx @@ -10,35 +10,66 @@ import { routeResolver } from "./App"; import SignupPage from "./SignupPage"; import LoginPage from "./LoginPage"; import WizardPage from "./WizardPage"; +import { Snackbar } from "@material-ui/core"; +import Alert from "@material-ui/lab/Alert"; +import { useSelector, useDispatch } from "react-redux"; +import { StoreState } from "./store"; +import { popMessage } from "./store/actions"; export default function MainRouter() { return ( - - - - - - - - - - - - - - + <> + + + + + + + + + + + + + + + + + ); +} + +function GlobalMessages() { + const dispatch = useDispatch(); + const message = useSelector((state: StoreState) => state.messages.first(undefined)); + + function handleClose() { + dispatch(popMessage()); + } + + return ( + + + {message?.message} + + ); } diff --git a/src/store/actions.ts b/src/store/actions.ts index f4d0cbf..f674049 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -6,6 +6,7 @@ import { createAction as origCreateAction, ActionMeta } from "redux-actions"; import * as Etebase from "etebase"; import { SettingsType } from "./"; +import { Message } from "./reducers"; type FunctionAny = (...args: any[]) => any; @@ -166,6 +167,20 @@ export const clearErros = createAction( } ); +export const pushMessage = createAction( + "PUSH_MESSAGE", + (message: Message) => { + return message; + } +); + +export const popMessage = createAction( + "POP_MESSAGE", + () => { + return true; + } +); + // FIXME: Move the rest to their own file export const setSettings = createAction( "SET_SETTINGS", diff --git a/src/store/construct.ts b/src/store/construct.ts index ccd3dc6..50e8ed8 100644 --- a/src/store/construct.ts +++ b/src/store/construct.ts @@ -11,9 +11,9 @@ import * as Etebase from "etebase"; import { List, Map as ImmutableMap } from "immutable"; import { SettingsType, - fetchCount, credentials, settingsReducer, encryptionKeyReducer, errorsReducer, + fetchCount, credentials, settingsReducer, encryptionKeyReducer, errorsReducer, messagesReducer, syncGeneral, syncCollections, collections, items, - SyncGeneralData, SyncCollectionsData, CacheCollectionsData, CacheItemsData, CredentialsData, + SyncGeneralData, SyncCollectionsData, CacheCollectionsData, CacheItemsData, CredentialsData, Message, } from "./reducers"; export interface StoreState { @@ -30,6 +30,7 @@ export interface StoreState { items: CacheItemsData; }; errors: List; + messages: List; } const settingsMigrations = { @@ -135,6 +136,7 @@ const reducers = combineReducers({ items, })), errors: errorsReducer, + messages: messagesReducer, }); export default reducers; diff --git a/src/store/reducers.ts b/src/store/reducers.ts index a062e3a..2376905 100644 --- a/src/store/reducers.ts +++ b/src/store/reducers.ts @@ -30,6 +30,11 @@ export type SyncGeneralData = { lastSyncDate: Date; }; +export type Message = { + message: string; + severity: "error" | "warning" | "info" | "success"; +}; + export interface CredentialsData { storedSession?: string; } @@ -219,6 +224,18 @@ export const errorsReducer = handleActions( List([]) ); +export const messagesReducer = handleActions( + { + [actions.pushMessage.toString()]: (state: List, action: Action) => { + return state.push(action.payload); + }, + [actions.popMessage.toString()]: (state: List, _action: Action) => { + return state.remove(0); + }, + }, + List([]) +); + // FIXME Move all the below (potentially the fetchCount ones too) to their own file export interface SettingsType {