From d79130af47f1f71eee4f32fcaae1e159759d441c Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Thu, 9 Sep 2021 11:37:52 +1000 Subject: [PATCH] grid: wire to real settings store --- .../src/nav/preferences/NotificationPrefs.tsx | 12 ++- pkg/grid/src/state/base.ts | 3 +- pkg/grid/src/state/settings.ts | 98 +++++++++++++++++++ 3 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 pkg/grid/src/state/settings.ts diff --git a/pkg/grid/src/nav/preferences/NotificationPrefs.tsx b/pkg/grid/src/nav/preferences/NotificationPrefs.tsx index ff0a306b33..d3acf833d1 100644 --- a/pkg/grid/src/nav/preferences/NotificationPrefs.tsx +++ b/pkg/grid/src/nav/preferences/NotificationPrefs.tsx @@ -1,15 +1,23 @@ import React from 'react'; import { Setting } from '../../components/Setting'; +import { useSettingsState, SettingsState } from '../../state/settings'; import { usePreferencesStore } from './usePreferencesStore'; +const selDnd = (s: SettingsState) => s.display.doNotDisturb; +async function toggleDnd() { + const state = useSettingsState.getState(); + await state.putEntry('display', 'doNotDisturb', !selDnd(state)); +} + export const NotificationPrefs = () => { - const { doNotDisturb, mentions, toggleDoNotDisturb, toggleMentions } = usePreferencesStore(); + const { mentions, toggleMentions } = usePreferencesStore(); + const doNotDisturb = useSettingsState(selDnd); return ( <>

Notifications

- +

Block visual desktop notifications whenever Urbit software produces an in-Landscape notification badge. diff --git a/pkg/grid/src/state/base.ts b/pkg/grid/src/state/base.ts index b285b829e5..ddba611383 100644 --- a/pkg/grid/src/state/base.ts +++ b/pkg/grid/src/state/base.ts @@ -7,6 +7,7 @@ import { persist } from 'zustand/middleware'; import Urbit, { SubscriptionRequestInterface } from '@urbit/http-api'; import { Poke } from '@urbit/api'; import api from './api'; +import { useMockData } from './util'; setAutoFreeze(false); enablePatches(); @@ -181,7 +182,7 @@ export async function pokeOptimisticallyN>( let num: string | undefined; try { num = optReduceState(state, poke.json, reduce); - await api.poke(poke); + await (useMockData ? new Promise((res) => setTimeout(res, 500)) : api.poke(poke)); state.getState().removePatch(num); } catch (e) { console.error(e); diff --git a/pkg/grid/src/state/settings.ts b/pkg/grid/src/state/settings.ts new file mode 100644 index 0000000000..1292547ac0 --- /dev/null +++ b/pkg/grid/src/state/settings.ts @@ -0,0 +1,98 @@ +/* eslint-disable no-param-reassign */ +import { + SettingsUpdate, + Value, + putEntry as doPutEntry, + getDeskSettings, + DeskData +} from '@urbit/api/settings'; +import _ from 'lodash'; +import { + BaseState, + createState, + createSubscription, + pokeOptimisticallyN, + reduceStateN +} from './base'; +import api from './api'; + +interface BaseSettingsState { + display: { + theme: 'light' | 'dark' | 'automatic'; + doNotDisturb: boolean; + }; + putEntry: (bucket: string, key: string, value: Value) => Promise; + [ref: string]: unknown; +} + +export type SettingsState = BaseSettingsState & BaseState; + +function putBucket(json: SettingsUpdate, state: SettingsState): SettingsState { + const data = _.get(json, 'put-bucket', false); + if (data) { + state[data['bucket-key']] = data.bucket; + } + return state; +} + +function delBucket(json: SettingsUpdate, state: SettingsState): SettingsState { + const data = _.get(json, 'del-bucket', false); + if (data) { + delete state[data['bucket-key']]; + } + return state; +} + +function putEntry(json: SettingsUpdate, state: any): SettingsState { + const data: Record = _.get(json, 'put-entry', false); + if (data) { + if (!state[data['bucket-key']]) { + state[data['bucket-key']] = {}; + } + state[data['bucket-key']][data['entry-key']] = data.value; + } + return state; +} + +function delEntry(json: SettingsUpdate, state: any): SettingsState { + const data = _.get(json, 'del-entry', false); + if (data) { + delete state[data['bucket-key']][data['entry-key']]; + } + return state; +} + +export const reduceUpdate = [putBucket, delBucket, putEntry, delEntry]; + +export const useSettingsState = createState( + 'Settings', + (set, get) => ({ + display: { + theme: 'automatic', + doNotDisturb: true + }, + loaded: false, + putEntry: async (bucket, key, val) => { + const poke = doPutEntry(window.desk, bucket, key, val); + await pokeOptimisticallyN(useSettingsState, poke, reduceUpdate); + }, + fetchAll: async () => { + const result = (await api.scry(getDeskSettings(window.desk))).desk; + const newState = { + loaded: true, + ..._.mergeWith(get(), result, (obj, src) => (_.isArray(src) ? src : undefined)) + }; + set(newState); + } + }), + [], + [ + (set, get) => + createSubscription('settings-store', `/desk/${window.desk}`, (e) => { + const data = _.get(e, 'settings-event', false); + if (data) { + reduceStateN(get(), data, reduceUpdate); + } + }) + ] +);