From 04e481f8e91f82c71d53c72e9aadb9c2dbc2a306 Mon Sep 17 00:00:00 2001 From: Tyler Brown Cifu Shuster Date: Tue, 2 Mar 2021 21:45:50 -0800 Subject: [PATCH] interface: addressed store feedback; cleaning up --- pkg/interface/src/logic/api/local.ts | 2 +- .../src/logic/lib/migrateSettings.ts | 4 -- .../src/logic/reducers/group-view.ts | 23 +++--- .../src/logic/reducers/launch-update.ts | 11 ++- pkg/interface/src/logic/reducers/local.ts | 33 --------- .../src/logic/reducers/settings-update.ts | 67 ++++++++++-------- pkg/interface/src/logic/state/invite.ts | 2 +- pkg/interface/src/logic/state/launch.ts | 2 + pkg/interface/src/logic/state/settings.ts | 54 ++++++++++++++ pkg/interface/src/logic/state/settings.tsx | 70 ------------------- pkg/interface/src/logic/store/base.ts | 4 -- pkg/interface/src/logic/store/store.ts | 52 +------------- pkg/interface/src/logic/store/type.ts | 43 ------------ pkg/interface/src/views/App.js | 5 +- pkg/interface/src/views/apps/launch/app.js | 11 +-- 15 files changed, 126 insertions(+), 257 deletions(-) delete mode 100644 pkg/interface/src/logic/reducers/local.ts create mode 100644 pkg/interface/src/logic/state/settings.ts delete mode 100644 pkg/interface/src/logic/state/settings.tsx diff --git a/pkg/interface/src/logic/api/local.ts b/pkg/interface/src/logic/api/local.ts index e5bad49a3f..305ac71f89 100644 --- a/pkg/interface/src/logic/api/local.ts +++ b/pkg/interface/src/logic/api/local.ts @@ -4,7 +4,7 @@ import { StoreState } from '../store/type'; export default class LocalApi extends BaseApi { getBaseHash() { this.scry('file-server', '/clay/base/hash').then((baseHash) => { - this.store.handleEvent({ data: { local: { baseHash } } }); + this.store.handleEvent({ data: { baseHash } }); }); } diff --git a/pkg/interface/src/logic/lib/migrateSettings.ts b/pkg/interface/src/logic/lib/migrateSettings.ts index bcfe44bfcb..ec841af18f 100644 --- a/pkg/interface/src/logic/lib/migrateSettings.ts +++ b/pkg/interface/src/logic/lib/migrateSettings.ts @@ -18,10 +18,6 @@ export function useMigrateSettings(api: GlobalApi) { const { display, remoteContentPolicy, calm } = useSettingsState(); return async () => { - if (!localStorage?.has("localReducer")) { - return; - } - let promises: Promise[] = []; if (local.hideAvatars !== calm.hideAvatars) { diff --git a/pkg/interface/src/logic/reducers/group-view.ts b/pkg/interface/src/logic/reducers/group-view.ts index 17cc4e6429..76234b8b49 100644 --- a/pkg/interface/src/logic/reducers/group-view.ts +++ b/pkg/interface/src/logic/reducers/group-view.ts @@ -1,13 +1,16 @@ -import { resourceAsPath } from '~/logic/lib/util'; +import { GroupUpdate } from '@urbit/api/groups'; +import { reduceState, resourceAsPath } from '~/logic/lib/util'; +import useGroupState, { GroupState } from '../state/group'; -const initial = (json: any, state: any) => { +const initial = (json: any, state: GroupState): GroupState => { const data = json.initial; if(data) { state.pendingJoin = data; } + return state; }; -const progress = (json: any, state: any) => { +const progress = (json: any, state: GroupState): GroupState => { const data = json.progress; if(data) { const { progress, resource } = data; @@ -18,13 +21,15 @@ const progress = (json: any, state: any) => { }, 10000); } } + return state; }; -export const GroupViewReducer = (json: any, state: any) => { +export const GroupViewReducer = (json: any) => { const data = json['group-view-update']; - if(data) { - progress(data, state); - initial(data, state); + if (data) { + reduceState(useGroupState, data, [ + progress, + initial + ]); } -}; -// TODO zustand this file \ No newline at end of file +}; \ No newline at end of file diff --git a/pkg/interface/src/logic/reducers/launch-update.ts b/pkg/interface/src/logic/reducers/launch-update.ts index 7dc86df711..42a5b2da7e 100644 --- a/pkg/interface/src/logic/reducers/launch-update.ts +++ b/pkg/interface/src/logic/reducers/launch-update.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; -import { LaunchState, LaunchUpdate, WeatherState } from '~/types/launch-update'; +import { LaunchUpdate, WeatherState } from '~/types/launch-update'; import { Cage } from '~/types/cage'; -import useLaunchState from '../state/launch'; +import useLaunchState, { LaunchState } from '../state/launch'; import { compose } from 'lodash/fp'; import { reduceState } from '../lib/util'; @@ -31,6 +31,13 @@ export default class LaunchReducer { state.userLocation = locationData; }); } + + const baseHash = _.get(json, 'baseHash', false); + if (baseHash) { + useLaunchState.getState().set(state => { + state.baseHash = baseHash; + }) + } } } diff --git a/pkg/interface/src/logic/reducers/local.ts b/pkg/interface/src/logic/reducers/local.ts deleted file mode 100644 index c10455278d..0000000000 --- a/pkg/interface/src/logic/reducers/local.ts +++ /dev/null @@ -1,33 +0,0 @@ -import _ from 'lodash'; -import { StoreState } from '~/store/type'; -import { Cage } from '~/types/cage'; -import { LocalUpdate } from '~/types/local-update'; - -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) { - } - reduce(json: Cage, state: S) { - const data = json['local']; - if (data) { - this.baseHash(data, state); - } - } - baseHash(obj: LocalUpdate, state: S) { - if ('baseHash' in obj) { - state.baseHash = obj.baseHash; - } - } -} diff --git a/pkg/interface/src/logic/reducers/settings-update.ts b/pkg/interface/src/logic/reducers/settings-update.ts index 79bb810061..bc6ac9483d 100644 --- a/pkg/interface/src/logic/reducers/settings-update.ts +++ b/pkg/interface/src/logic/reducers/settings-update.ts @@ -1,46 +1,46 @@ import _ from 'lodash'; -import { SettingsUpdate } from '~/types/settings'; -import useSettingsState, { SettingsStateZus } from "~/logic/state/settings"; -import produce from 'immer'; +import useSettingsState, { SettingsState } from "~/logic/state/settings"; +import { SettingsUpdate } from '@urbit/api/dist/settings'; +import { reduceState } from '../lib/util'; -export default class SettingsStateZusettingsReducer{ +export default class SettingsReducer { reduce(json: any) { - const old = useSettingsState.getState(); - const newState = produce(old, state => { - let data = json["settings-event"]; - if (data) { - console.log(data); - this.putBucket(data, state); - this.delBucket(data, state); - this.putEntry(data, state); - this.delEntry(data, state); - } - data = json["settings-data"]; - if (data) { - console.log(data); - this.getAll(data, state); - this.getBucket(data, state); - this.getEntry(data, state); - } - }); - useSettingsState.setState(newState); + let data = json["settings-event"]; + if (data) { + reduceState(useSettingsState, data, [ + this.putBucket, + this.delBucket, + this.putEntry, + this.delEntry, + ]); + } + data = json["settings-data"]; + if (data) { + reduceState(useSettingsState, data, [ + this.getAll, + this.getBucket, + this.getEntry, + ]); + } } - putBucket(json: SettingsUpdate, state: SettingsStateZus) { + putBucket(json: SettingsUpdate, state: SettingsState): SettingsState { const data = _.get(json, 'put-bucket', false); if (data) { state[data["bucket-key"]] = data.bucket; } + return state; } - delBucket(json: SettingsUpdate, state: SettingsStateZus) { + delBucket(json: SettingsUpdate, state: SettingsState): SettingsState { const data = _.get(json, 'del-bucket', false); if (data) { - delete settings[data['bucket-key']]; + delete state[data['bucket-key']]; } + return state; } - putEntry(json: SettingsUpdate, state: SettingsStateZus) { + putEntry(json: SettingsUpdate, state: SettingsState): SettingsState { const data = _.get(json, 'put-entry', false); if (data) { if (!state[data["bucket-key"]]) { @@ -48,36 +48,41 @@ export default class SettingsStateZusettingsReducer{ } state[data["bucket-key"]][data["entry-key"]] = data.value; } + return state; } - delEntry(json: SettingsUpdate, state: SettingsStateZus) { + delEntry(json: SettingsUpdate, state: SettingsState): SettingsState { const data = _.get(json, 'del-entry', false); if (data) { delete state[data["bucket-key"]][data["entry-key"]]; } + return state; } - getAll(json: any, state: SettingsStateZus) { + getAll(json: any, state: SettingsState): SettingsState { const data = _.get(json, 'all'); if(data) { _.merge(state, data); } + return state; } - getBucket(json: any, state: SettingsStateZus) { + getBucket(json: any, state: SettingsState): SettingsState { const key = _.get(json, 'bucket-key', false); const bucket = _.get(json, 'bucket', false); if (key && bucket) { state[key] = bucket; } + return state; } - getEntry(json: any, state: SettingsStateZus) { + getEntry(json: any, state: SettingsState) { const bucketKey = _.get(json, 'bucket-key', false); const entryKey = _.get(json, 'entry-key', false); const entry = _.get(json, 'entry', false); if (bucketKey && entryKey && entry) { state[bucketKey][entryKey] = entry; } + return state; } } diff --git a/pkg/interface/src/logic/state/invite.ts b/pkg/interface/src/logic/state/invite.ts index b49c27f9b1..35df0cedd0 100644 --- a/pkg/interface/src/logic/state/invite.ts +++ b/pkg/interface/src/logic/state/invite.ts @@ -1,6 +1,6 @@ import { Invites } from '@urbit/api'; -import { BaseState, createState } from "./base"; +import { BaseState, createState } from '~/logic/state/base'; export interface InviteState extends BaseState { invites: Invites; diff --git a/pkg/interface/src/logic/state/launch.ts b/pkg/interface/src/logic/state/launch.ts index be8fe527c8..14f2113e58 100644 --- a/pkg/interface/src/logic/state/launch.ts +++ b/pkg/interface/src/logic/state/launch.ts @@ -11,6 +11,7 @@ export interface LaunchState extends BaseState { }, weather: WeatherState | null, userLocation: string | null; + baseHash: string | null; }; const useLaunchState = createState('Launch', { @@ -19,6 +20,7 @@ const useLaunchState = createState('Launch', { tiles: {}, weather: null, userLocation: null, + baseHash: null }); diff --git a/pkg/interface/src/logic/state/settings.ts b/pkg/interface/src/logic/state/settings.ts new file mode 100644 index 0000000000..eca60201c9 --- /dev/null +++ b/pkg/interface/src/logic/state/settings.ts @@ -0,0 +1,54 @@ +import f from 'lodash/fp'; +import { RemoteContentPolicy, LeapCategories, leapCategories } from "~/types/local-update"; +import { BaseState, createState } from '~/logic/state/base'; + + +export interface SettingsState extends BaseState { + display: { + backgroundType: 'none' | 'url' | 'color'; + background?: string; + dark: boolean; + }; + calm: { + hideNicknames: boolean; + hideAvatars: boolean; + hideUnreads: boolean; + hideGroups: boolean; + hideUtilities: boolean; + }; + remoteContentPolicy: RemoteContentPolicy; + leap: { + categories: LeapCategories[]; + } +}; + +export const selectSettingsState = +(keys: K[]) => f.pick(keys); + +export const selectCalmState = (s: SettingsState) => s.calm; + +const useSettingsState = createState('Settings', { + display: { + backgroundType: 'none', + background: undefined, + dark: false, + }, + calm: { + hideNicknames: false, + hideAvatars: false, + hideUnreads: false, + hideGroups: false, + hideUtilities: false + }, + remoteContentPolicy: { + imageShown: true, + oembedShown: true, + audioShown: true, + videoShown: true + }, + leap: { + categories: leapCategories, + }, +}); + +export default useSettingsState; diff --git a/pkg/interface/src/logic/state/settings.tsx b/pkg/interface/src/logic/state/settings.tsx deleted file mode 100644 index de1bb1da87..0000000000 --- a/pkg/interface/src/logic/state/settings.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React, { ReactNode } from "react"; -import f from 'lodash/fp'; -import create, { State } from 'zustand'; -import { persist } from 'zustand/middleware'; -import produce from 'immer'; -import { BackgroundConfig, RemoteContentPolicy, TutorialProgress, tutorialProgress, LeapCategories, leapCategories } from "~/types/local-update"; - - -export interface SettingsState { - display: { - backgroundType: 'none' | 'url' | 'color'; - background?: string; - dark: boolean; - }; - calm: { - hideNicknames: boolean; - hideAvatars: boolean; - hideUnreads: boolean; - hideGroups: boolean; - hideUtilities: boolean; - }; - remoteContentPolicy: RemoteContentPolicy; - leap: { - categories: LeapCategories[]; - } - set: (fn: (state: SettingsState) => void) => void -}; - -export type SettingsStateZus = SettingsState & State; - -export const selectSettingsState = -(keys: K[]) => f.pick(keys); - -export const selectCalmState = (s: SettingsState) => s.calm; - -const useSettingsState = create((set) => ({ - display: { - backgroundType: 'none', - background: undefined, - dark: false, - }, - calm: { - hideNicknames: false, - hideAvatars: false, - hideUnreads: false, - hideGroups: false, - hideUtilities: false - }, - remoteContentPolicy: { - imageShown: true, - oembedShown: true, - audioShown: true, - videoShown: true - }, - leap: { - categories: leapCategories, - }, - set: (fn: (state: SettingsState) => void) => set(produce(fn)) -})); - -function withSettingsState(Component: any, stateMemberKeys?: S[]) { - return React.forwardRef((props: Omit, ref) => { - const localState = stateMemberKeys - ? useSettingsState(selectSettingsState(stateMemberKeys)) - : useSettingsState(); - return - }); -} - -export { useSettingsState as default, withSettingsState }; diff --git a/pkg/interface/src/logic/store/base.ts b/pkg/interface/src/logic/store/base.ts index faeacca1e9..b2c894f34e 100644 --- a/pkg/interface/src/logic/store/base.ts +++ b/pkg/interface/src/logic/store/base.ts @@ -5,10 +5,6 @@ export default class BaseStore { this.state = this.initialState(); } - dehydrate() {} - - rehydrate() {} - initialState() { return {} as S; } diff --git a/pkg/interface/src/logic/store/store.ts b/pkg/interface/src/logic/store/store.ts index 6eff91e166..fbeb9ea94b 100644 --- a/pkg/interface/src/logic/store/store.ts +++ b/pkg/interface/src/logic/store/store.ts @@ -23,7 +23,6 @@ import { GroupViewReducer } from '../reducers/group-view'; export default class GlobalStore extends BaseStore { inviteReducer = new InviteReducer(); metadataReducer = new MetadataReducer(); - localReducer = new LocalReducer(); s3Reducer = new S3Reducer(); groupReducer = new GroupReducer(); launchReducer = new LaunchReducer(); @@ -42,56 +41,9 @@ export default class GlobalStore extends BaseStore { console.log(_.pick(this.state, stateKeys)); } - rehydrate() { - this.localReducer.rehydrate(this.state); - } - - dehydrate() { - this.localReducer.dehydrate(this.state); - } - initialState(): StoreState { return { connection: 'connected', - baseHash: null, - invites: {}, - associations: { - groups: {}, - graph: {} - }, - groups: {}, - groupKeys: new Set(), - graphs: {}, - graphKeys: new Set(), - launch: { - firstTime: false, - tileOrdering: [], - tiles: {} - }, - weather: {}, - userLocation: null, - s3: { - configuration: { - buckets: new Set(), - currentBucket: '' - }, - credentials: null - }, - notifications: new BigIntOrderedMap(), - archivedNotifications: new BigIntOrderedMap(), - notificationsGroupConfig: [], - notificationsGraphConfig: { - watchOnSelf: false, - mentions: false, - watching: [] - }, - unreads: { - graph: {}, - group: {} - }, - notificationsCount: 0, - settings: {}, - pendingJoin: {} }; } @@ -100,10 +52,8 @@ export default class GlobalStore extends BaseStore { const tag = Object.keys(data)[0]; const oldActions = this.pastActions[tag] || []; this.pastActions[tag] = [data[tag], ...oldActions.slice(0,14)]; - this.inviteReducer.reduce(data); this.metadataReducer.reduce(data); - this.localReducer.reduce(data, this.state); this.s3Reducer.reduce(data); this.groupReducer.reduce(data); this.launchReducer.reduce(data); @@ -112,6 +62,6 @@ export default class GlobalStore extends BaseStore { HarkReducer(data); ContactReducer(data); this.settingsReducer.reduce(data); - GroupViewReducer(data, this.state); + GroupViewReducer(data); } } diff --git a/pkg/interface/src/logic/store/type.ts b/pkg/interface/src/logic/store/type.ts index 97304be966..568cd20411 100644 --- a/pkg/interface/src/logic/store/type.ts +++ b/pkg/interface/src/logic/store/type.ts @@ -1,49 +1,6 @@ -import { Path } from '@urbit/api'; -import { Invites } from '@urbit/api/invite'; -import { Associations } from '@urbit/api/metadata'; -import { Rolodex } from '@urbit/api/contacts'; -import { Groups } from '@urbit/api/groups'; -import { S3State } from '~/types/s3-update'; -import { LaunchState, WeatherState } from '~/types/launch-update'; import { ConnectionStatus } from '~/types/connection'; -import { Graphs } from '@urbit/api/graph'; -import { - Notifications, - NotificationGraphConfig, - GroupNotificationsConfig, - Unreads, - JoinRequests, - Patp -} from '@urbit/api'; export interface StoreState { // local state connection: ConnectionStatus; - baseHash: string | null; - - // invite state - invites: Invites; - // metadata state - associations: Associations; - // groups state - groups: Groups; - groupKeys: Set; - s3: S3State; - graphs: Graphs; - graphKeys: Set; - - // App specific states - // launch state - launch: LaunchState; - weather: WeatherState | {} | null; - userLocation: string | null; - - archivedNotifications: Notifications; - notifications: Notifications; - notificationsGraphConfig: NotificationGraphConfig; - notificationsGroupConfig: GroupNotificationsConfig; - notificationsCount: number, - unreads: Unreads; - doNotDisturb: boolean; - pendingJoin: JoinRequests; } diff --git a/pkg/interface/src/views/App.js b/pkg/interface/src/views/App.js index 2ad7c0820d..30e2d45f7b 100644 --- a/pkg/interface/src/views/App.js +++ b/pkg/interface/src/views/App.js @@ -31,10 +31,10 @@ import withState from '~/logic/lib/withState'; import useLocalState from '~/logic/state/local'; import useContactState from '~/logic/state/contact'; import useGroupState from '~/logic/state/group'; -import { withSettingsState } from '~/logic/state/settings'; +import useSettingsState from '~/logic/state/settings'; -const Root = withSettingsState(styled.div` +const Root = withState(useSettingsState, styled.div` font-family: ${p => p.theme.fonts.sans}; height: 100%; width: 100%; @@ -100,7 +100,6 @@ class App extends React.Component { }, 500); this.api.local.getBaseHash(); this.api.settings.getAll(); - this.store.rehydrate(); Mousetrap.bindGlobal(['command+/', 'ctrl+/'], (e) => { e.preventDefault(); e.stopImmediatePropagation(); diff --git a/pkg/interface/src/views/apps/launch/app.js b/pkg/interface/src/views/apps/launch/app.js index ff66e65e18..211c7eb020 100644 --- a/pkg/interface/src/views/apps/launch/app.js +++ b/pkg/interface/src/views/apps/launch/app.js @@ -1,6 +1,5 @@ import React, { useState, useMemo, useEffect } from 'react'; import styled from 'styled-components'; -import { useHistory } from 'react-router-dom'; import f from 'lodash/fp'; import _ from 'lodash'; @@ -30,6 +29,7 @@ import { TUTORIAL_CHAT, TUTORIAL_LINKS } from '~/logic/lib/tutorialModal'; +import useLaunchState from '~/logic/state/launch'; import useSettingsState, { selectCalmState } from '~/logic/state/settings'; @@ -44,7 +44,8 @@ const ScrollbarLessBox = styled(Box)` const tutSelector = f.pick(['tutorialProgress', 'nextTutStep', 'hideGroups']); export default function LaunchApp(props) { - const [hashText, setHashText] = useState(props.baseHash); + const baseHash = useLaunchState(state => state.baseHash); + const [hashText, setHashText] = useState(baseHash); const hashBox = ( { - writeText(props.baseHash); + writeText(baseHash); setHashText('copied'); setTimeout(() => { - setHashText(props.baseHash); + setHashText(baseHash); }, 2000); }} > - {hashText || props.baseHash} + {hashText || baseHash} );