From d9a9ac991f01e507ce53089d829add0ec82bd292 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Fri, 31 Jul 2020 13:00:27 +1000 Subject: [PATCH] interface: add storage and hydration of settings --- pkg/interface/src/App.js | 1 + pkg/interface/src/api/launch.ts | 2 +- pkg/interface/src/api/local.ts | 36 +++++++++++++++++++++- pkg/interface/src/reducers/local.ts | 40 +++++++++++++++++++++++-- pkg/interface/src/store/base.ts | 4 +++ pkg/interface/src/store/store.ts | 11 +++++++ pkg/interface/src/store/type.ts | 5 +++- pkg/interface/src/types/local-update.ts | 30 ++++++++++++++++++- 8 files changed, 123 insertions(+), 6 deletions(-) diff --git a/pkg/interface/src/App.js b/pkg/interface/src/App.js index 94dc9d0764..c2e0e0f8f9 100644 --- a/pkg/interface/src/App.js +++ b/pkg/interface/src/App.js @@ -70,6 +70,7 @@ class App extends React.Component { this.api.local.setDark(this.themeWatcher.matches); this.themeWatcher.addListener(this.updateTheme); this.api.local.getBaseHash(); + this.store.rehydrate(); } componentWillUnmount() { diff --git a/pkg/interface/src/api/launch.ts b/pkg/interface/src/api/launch.ts index 1e6fa4a33a..0eeca42e8f 100644 --- a/pkg/interface/src/api/launch.ts +++ b/pkg/interface/src/api/launch.ts @@ -12,7 +12,7 @@ export default class LaunchApi extends BaseApi { this.launchAction({ remove: name }); } - changeOrder(orderedTiles = []) { + changeOrder(orderedTiles: string[] = []) { this.launchAction({ 'change-order': orderedTiles }); } diff --git a/pkg/interface/src/api/local.ts b/pkg/interface/src/api/local.ts index 8610284c23..d5a11c28da 100644 --- a/pkg/interface/src/api/local.ts +++ b/pkg/interface/src/api/local.ts @@ -1,6 +1,6 @@ import BaseApi from "./base"; import { StoreState } from "../store/type"; -import { SelectedGroup } from "../types/local-update"; +import { SelectedGroup, BackgroundConfig } from "../types/local-update"; export default class LocalApi extends BaseApi { getBaseHash() { @@ -39,4 +39,38 @@ export default class LocalApi extends BaseApi { }); } + setBackground(backgroundConfig: BackgroundConfig) { + this.store.handleEvent({ + data: { + local: { + backgroundConfig + } + } + }); + } + + hideAvatars(hideAvatars: boolean) { + this.store.handleEvent({ + data: { + local: { + hideAvatars + } + } + }); + } + + hideNicknames(hideNicknames: boolean) { + this.store.handleEvent({ + data: { + local: { + hideNicknames + } + } + }); + } + + dehydrate() { + this.store.dehydrate(); + } + } diff --git a/pkg/interface/src/reducers/local.ts b/pkg/interface/src/reducers/local.ts index ec11a23669..f434daf28c 100644 --- a/pkg/interface/src/reducers/local.ts +++ b/pkg/interface/src/reducers/local.ts @@ -1,11 +1,26 @@ import _ from 'lodash'; import { StoreState } from '../store/type'; import { Cage } from '../types/cage'; -import { LocalUpdate } from '../types/local-update'; +import { LocalUpdate, BackgroundConfig } from '../types/local-update'; -type LocalState = Pick; +type LocalState = Pick; export default class LocalReducer { + rehydrate(state: S) { + try { + const json = JSON.parse(localStorage.getItem('localReducer') || ''); + _.forIn(json, (value, key) => { + state[key] = value; + }); + } catch (e) { + console.warn('Failed to rehydrate localStorage state', e); + } + } + + dehydrate(state: S) { + const json = _.pick(state, ['hideNicknames' , 'hideAvatars' , 'background']); + localStorage.setItem('localReducer', JSON.stringify(json)); + } reduce(json: Cage, state: S) { const data = json['local']; if (data) { @@ -13,6 +28,9 @@ export default class LocalReducer { this.setSelected(data, state); this.setDark(data, state); this.baseHash(data, state); + this.backgroundConfig(data, state) + this.hideAvatars(data, state) + this.hideNicknames(data, state) } } baseHash(obj: LocalUpdate, state: S) { @@ -38,4 +56,22 @@ export default class LocalReducer { state.dark = obj.setDark; } } + + backgroundConfig(obj: LocalUpdate, state: S) { + if('backgroundConfig' in obj) { + state.background = obj.backgroundConfig; + } + } + + hideAvatars(obj: LocalUpdate, state: S) { + if('hideAvatars' in obj) { + state.hideAvatars = obj.hideAvatars; + } + } + + hideNicknames(obj: LocalUpdate, state: S) { + if( 'hideNicknames' in obj) { + state.hideNicknames = obj.hideNicknames; + } + } } diff --git a/pkg/interface/src/store/base.ts b/pkg/interface/src/store/base.ts index da026c33ed..9a48ebd80e 100644 --- a/pkg/interface/src/store/base.ts +++ b/pkg/interface/src/store/base.ts @@ -5,6 +5,10 @@ export default class BaseStore { this.state = this.initialState(); } + dehydrate() {} + + rehydrate() {} + initialState() { return {} as S; } diff --git a/pkg/interface/src/store/store.ts b/pkg/interface/src/store/store.ts index 76cdad3c2d..2847b24c1d 100644 --- a/pkg/interface/src/store/store.ts +++ b/pkg/interface/src/store/store.ts @@ -34,6 +34,14 @@ export default class GlobalStore extends BaseStore { launchReducer = new LaunchReducer(); connReducer = new ConnectionReducer(); + rehydrate() { + this.localReducer.rehydrate(this.state); + } + + dehydrate() { + this.localReducer.dehydrate(this.state); + } + initialState(): StoreState { return { @@ -42,6 +50,9 @@ export default class GlobalStore extends BaseStore { connection: 'connected', sidebarShown: true, baseHash: null, + background: undefined, + hideAvatars: false, + hideNicknames: false, invites: {}, associations: { chat: {}, diff --git a/pkg/interface/src/store/type.ts b/pkg/interface/src/store/type.ts index 875f80318a..739c19369c 100644 --- a/pkg/interface/src/store/type.ts +++ b/pkg/interface/src/store/type.ts @@ -2,7 +2,7 @@ import { Inbox, Envelope } from '../types/chat-update'; import { ChatHookUpdate } from '../types/chat-hook-update'; import { Path } from '../types/noun'; import { Invites } from '../types/invite-update'; -import { SelectedGroup } from '../types/local-update'; +import { SelectedGroup, BackgroundConfig } from '../types/local-update'; import { Associations } from '../types/metadata-update'; import { Rolodex } from '../types/contact-update'; import { Notebooks } from '../types/publish-update'; @@ -20,6 +20,9 @@ export interface StoreState { dark: boolean; connection: ConnectionStatus; baseHash: string | null; + background: BackgroundConfig; + hideAvatars: boolean; + hideNicknames: boolean; // invite state invites: Invites; // metadata state diff --git a/pkg/interface/src/types/local-update.ts b/pkg/interface/src/types/local-update.ts index 326d845400..e76c670928 100644 --- a/pkg/interface/src/types/local-update.ts +++ b/pkg/interface/src/types/local-update.ts @@ -4,7 +4,10 @@ export type LocalUpdate = LocalUpdateSidebarToggle | LocalUpdateSelectedGroups | LocalUpdateSetDark -| LocalUpdateBaseHash; +| LocalUpdateBaseHash +| LocalUpdateBackgroundConfig +| LocalUpdateHideAvatars +| LocalUpdateHideNicknames; interface LocalUpdateSidebarToggle { sidebarToggle: boolean; @@ -22,4 +25,29 @@ interface LocalUpdateBaseHash { baseHash: string; } +interface LocalUpdateBackgroundConfig { + backgroundConfig: BackgroundConfig; +} + +interface LocalUpdateHideAvatars { + hideAvatars: boolean; +} + +interface LocalUpdateHideNicknames { + hideNicknames: boolean; +} + +export type BackgroundConfig = BackgroundConfigUrl | BackgroundConfigColor | undefined; + +interface BackgroundConfigUrl { + type: 'url'; + url: string; +} + +interface BackgroundConfigColor { + type: 'color'; + color: string; +} + + export type SelectedGroup = [Path, string];