From 17f628543068d359a7f61f54861dcfdf914ed2aa Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 14 Sep 2021 23:04:24 +1000 Subject: [PATCH 1/6] btc-wallet: fix webpack output --- pkg/bitcoin/desk.docket | 2 +- pkg/btc-wallet/config/webpack.prod.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/bitcoin/desk.docket b/pkg/bitcoin/desk.docket index 32cd059b55..2dd49e7340 100644 --- a/pkg/bitcoin/desk.docket +++ b/pkg/bitcoin/desk.docket @@ -2,7 +2,7 @@ title+'Bitcoin' info+'BTC wallet for Urbit. Testing' color+0xf9.8e40 - glob-http+'https://bootstrap.urbit.org/glob-0v2.sl9s6.ud2bs.l9ft0.mstja.5f8kt.glob' + glob-http+'https://bootstrap.urbit.org/glob-0v4.ghaim.of1as.9ucee.uj93f.a9nbs.glob' image+'https://urbit.ewr1.vultrobjects.com/hastuc-dibtux/2021.8.24..02.57.38-bitcoin.svg' base+'bitcoin' version+[0 0 1] diff --git a/pkg/btc-wallet/config/webpack.prod.js b/pkg/btc-wallet/config/webpack.prod.js index 7f184e5473..fbdbae0590 100644 --- a/pkg/btc-wallet/config/webpack.prod.js +++ b/pkg/btc-wallet/config/webpack.prod.js @@ -55,7 +55,7 @@ module.exports = { filename: (pathData) => { return pathData.chunk.name === 'app' ? 'index.[contenthash].js' : '[name].js'; }, - path: path.resolve(__dirname, 'dist'), + path: path.resolve(__dirname, '../dist'), publicPath: '/apps/bitcoin/', }, optimization: { From 8dd91138431fc84075f9d78b9d9e558565d4151a Mon Sep 17 00:00:00 2001 From: Hunter Miller Date: Tue, 14 Sep 2021 10:50:39 -0500 Subject: [PATCH 2/6] prefs: hooking up mentions pref --- pkg/grid/src/app.tsx | 2 + pkg/grid/src/components/Setting.tsx | 4 +- pkg/grid/src/components/Toggle.tsx | 7 ++- .../src/nav/preferences/InterfacePrefs.tsx | 21 ++++--- .../src/nav/preferences/NotificationPrefs.tsx | 12 +++- pkg/grid/src/state/hark.ts | 55 +++++++++++++++++-- 6 files changed, 80 insertions(+), 21 deletions(-) diff --git a/pkg/grid/src/app.tsx b/pkg/grid/src/app.tsx index a46304484b..403f5fae20 100644 --- a/pkg/grid/src/app.tsx +++ b/pkg/grid/src/app.tsx @@ -8,6 +8,7 @@ import useKilnState from './state/kiln'; import { usePreferencesStore } from './nav/preferences/usePreferencesStore'; import useContactState from './state/contact'; import api from './state/api'; +import { useHarkStore } from './state/hark'; const AppRoutes = () => { const { push } = useHistory(); @@ -46,6 +47,7 @@ const AppRoutes = () => { fetchVats(); fetchLag(); useContactState.getState().initialize(api); + useHarkStore.getState().initialize(api); Mousetrap.bind(['command+/', 'ctrl+/'], () => { push('/leap/search'); diff --git a/pkg/grid/src/components/Setting.tsx b/pkg/grid/src/components/Setting.tsx index dff93480fc..8dd8803747 100644 --- a/pkg/grid/src/components/Setting.tsx +++ b/pkg/grid/src/components/Setting.tsx @@ -20,12 +20,12 @@ export const Setting: FC = ({ name, on, toggle, className, childr

{name} {status === 'loading' && }

-
+
{children}
diff --git a/pkg/grid/src/components/Toggle.tsx b/pkg/grid/src/components/Toggle.tsx index e6d3be2ff7..f9c31beeed 100644 --- a/pkg/grid/src/components/Toggle.tsx +++ b/pkg/grid/src/components/Toggle.tsx @@ -6,12 +6,13 @@ import type * as Polymorphic from '@radix-ui/react-polymorphic'; type ToggleComponent = Polymorphic.ForwardRefComponent< Polymorphic.IntrinsicElement, Polymorphic.OwnProps & { + toggleClass?: string; knobClass?: string; } >; export const Toggle = React.forwardRef( - ({ defaultPressed, pressed, onPressedChange, disabled, className }, ref) => { + ({ defaultPressed, pressed, onPressedChange, disabled, className, toggleClass }, ref) => { const [on, setOn] = useState(defaultPressed); const isControlled = !!onPressedChange; const proxyPressed = isControlled ? pressed : on; @@ -20,14 +21,14 @@ export const Toggle = React.forwardRef( return ( { if (!protocolHandling && window?.navigator?.registerProtocolHandler) { try { - window.navigator.registerProtocolHandler('web+urbitgraph', '/apps/grid/perma?ext=%s', 'Urbit Links'); - setLocalState((s) => { - s.protocolHandling = true; + window.navigator.registerProtocolHandler( + 'web+urbitgraph', + '/apps/grid/perma?ext=%s', + 'Urbit Links' + ); + setLocalState((draft) => { + draft.protocolHandling = true; }); } catch (e) { console.error(e); @@ -18,8 +21,8 @@ export function InterfacePrefs() { } else if (protocolHandling && window.navigator?.unregisterProtocolHandler) { try { window.navigator.unregisterProtocolHandler('web+urbitgraph', '/apps/grid/perma?ext=%s'); - setLocalState((s) => { - s.protocolHandling = false; + setLocalState((draft) => { + draft.protocolHandling = false; }); } catch (e) { console.error(e); @@ -31,10 +34,10 @@ export function InterfacePrefs() { <>

Interface Settings

-

Automatically open urbit links with this urbit

+

+ Automatically open urbit links with this urbit +

- -
); } diff --git a/pkg/grid/src/nav/preferences/NotificationPrefs.tsx b/pkg/grid/src/nav/preferences/NotificationPrefs.tsx index d3acf833d1..3e62175dd2 100644 --- a/pkg/grid/src/nav/preferences/NotificationPrefs.tsx +++ b/pkg/grid/src/nav/preferences/NotificationPrefs.tsx @@ -1,7 +1,9 @@ +import { setMentions } from '@urbit/api/dist'; import React from 'react'; import { Setting } from '../../components/Setting'; +import { pokeOptimisticallyN } from '../../state/base'; +import { HarkState, reduceGraph, useHarkStore } from '../../state/hark'; import { useSettingsState, SettingsState } from '../../state/settings'; -import { usePreferencesStore } from './usePreferencesStore'; const selDnd = (s: SettingsState) => s.display.doNotDisturb; async function toggleDnd() { @@ -9,9 +11,15 @@ async function toggleDnd() { await state.putEntry('display', 'doNotDisturb', !selDnd(state)); } +const selMentions = (s: HarkState) => s.notificationsGraphConfig.mentions; +async function toggleMentions() { + const state = useHarkStore.getState(); + await pokeOptimisticallyN(useHarkStore, setMentions(!selMentions(state)), reduceGraph); +} + export const NotificationPrefs = () => { - const { mentions, toggleMentions } = usePreferencesStore(); const doNotDisturb = useSettingsState(selDnd); + const mentions = useHarkStore(selMentions); return ( <> diff --git a/pkg/grid/src/state/hark.ts b/pkg/grid/src/state/hark.ts index 519c661bd8..6e19a2b5b6 100644 --- a/pkg/grid/src/state/hark.ts +++ b/pkg/grid/src/state/hark.ts @@ -1,12 +1,57 @@ -import create from 'zustand'; +import _ from 'lodash'; +import { NotificationGraphConfig } from '@urbit/api'; import { Notification } from './hark-types'; import { mockNotification } from './mock-data'; import { useMockData } from './util'; +import { BaseState, createState, createSubscription, reduceStateN } from './base'; -interface HarkStore { +export interface HarkState { notifications: Notification[]; + notificationsGraphConfig: NotificationGraphConfig; + [ref: string]: unknown; } -export const useHarkStore = create(() => ({ - notifications: useMockData ? [mockNotification] : [] -})); +type BaseHarkState = HarkState & BaseState; + +function updateState( + key: string, + transform: (state: BaseHarkState, data: any) => void +): (json: any, state: BaseHarkState) => BaseHarkState { + return (json: any, state: BaseHarkState) => { + if (_.has(json, key)) { + transform(state, _.get(json, key, undefined)); + } + return state; + }; +} + +export const reduceGraph = [ + updateState('initial', (draft, data) => { + draft.notificationsGraphConfig = data; + }), + updateState('set-mentions', (draft, data) => { + draft.notificationsGraphConfig.mentions = data; + }) +]; + +export const useHarkStore = createState( + 'Hark', + () => ({ + notifications: useMockData ? [mockNotification] : [], + notificationsGraphConfig: { + watchOnSelf: false, + mentions: false, + watching: [] + } + }), + [], + [ + (set, get) => + createSubscription('hark-graph-hook', '/updates', (j) => { + const graphHookData = _.get(j, 'hark-graph-hook-update', false); + if (graphHookData) { + reduceStateN(get(), graphHookData, reduceGraph); + } + }) + ] +); From 8027ab9d50f07fb67a5e9ad8060da2586bee9fb9 Mon Sep 17 00:00:00 2001 From: Hunter Miller Date: Tue, 14 Sep 2021 16:15:29 -0500 Subject: [PATCH 3/6] prefs: hooking up system updates and cleaning up theme handling --- pkg/grid/src/app.tsx | 9 +-- pkg/grid/src/components/Setting.tsx | 2 +- .../src/nav/preferences/InterfacePrefs.tsx | 4 +- .../src/nav/preferences/NotificationPrefs.tsx | 9 +-- .../src/nav/preferences/SystemUpdatePrefs.tsx | 31 ++++++++--- .../nav/preferences/usePreferencesStore.ts | 55 ------------------- pkg/grid/src/state/api.ts | 26 +++++---- pkg/grid/src/state/kiln.ts | 38 ++++++++++++- pkg/grid/src/state/local.ts | 7 +++ pkg/grid/src/state/settings.ts | 5 ++ pkg/grid/src/tiles/useTileColor.tsx | 4 +- pkg/npm/api/hood/types.ts | 1 + 12 files changed, 96 insertions(+), 95 deletions(-) delete mode 100644 pkg/grid/src/nav/preferences/usePreferencesStore.ts diff --git a/pkg/grid/src/app.tsx b/pkg/grid/src/app.tsx index 403f5fae20..27a9187f57 100644 --- a/pkg/grid/src/app.tsx +++ b/pkg/grid/src/app.tsx @@ -5,23 +5,24 @@ import { Grid } from './pages/Grid'; import useDocketState from './state/docket'; import { PermalinkRoutes } from './pages/PermalinkRoutes'; import useKilnState from './state/kiln'; -import { usePreferencesStore } from './nav/preferences/usePreferencesStore'; import useContactState from './state/contact'; import api from './state/api'; import { useHarkStore } from './state/hark'; +import { useTheme } from './state/settings'; +import { useLocalState } from './state/local'; const AppRoutes = () => { const { push } = useHistory(); - const theme = usePreferencesStore((s) => s.theme); + const theme = useTheme(); const updateThemeClass = useCallback( (e: MediaQueryListEvent) => { if ((e.matches && theme === 'automatic') || theme === 'dark') { document.body.classList.add('dark'); - usePreferencesStore.setState({ currentTheme: 'dark' }); + useLocalState.setState({ currentTheme: 'dark' }); } else { document.body.classList.remove('dark'); - usePreferencesStore.setState({ currentTheme: 'light' }); + useLocalState.setState({ currentTheme: 'light' }); } }, [theme] diff --git a/pkg/grid/src/components/Setting.tsx b/pkg/grid/src/components/Setting.tsx index 8dd8803747..c0412b3b5d 100644 --- a/pkg/grid/src/components/Setting.tsx +++ b/pkg/grid/src/components/Setting.tsx @@ -27,7 +27,7 @@ export const Setting: FC = ({ name, on, toggle, className, childr onPressedChange={call} className="flex-none self-start text-blue-400" /> -
{children}
+
{children}
); diff --git a/pkg/grid/src/nav/preferences/InterfacePrefs.tsx b/pkg/grid/src/nav/preferences/InterfacePrefs.tsx index 8824256775..5890ddfc82 100644 --- a/pkg/grid/src/nav/preferences/InterfacePrefs.tsx +++ b/pkg/grid/src/nav/preferences/InterfacePrefs.tsx @@ -34,9 +34,7 @@ export function InterfacePrefs() { <>

Interface Settings

-

- Automatically open urbit links with this urbit -

+

Automatically open urbit links with this urbit

); diff --git a/pkg/grid/src/nav/preferences/NotificationPrefs.tsx b/pkg/grid/src/nav/preferences/NotificationPrefs.tsx index 3e62175dd2..ea65bab3ea 100644 --- a/pkg/grid/src/nav/preferences/NotificationPrefs.tsx +++ b/pkg/grid/src/nav/preferences/NotificationPrefs.tsx @@ -36,14 +36,7 @@ export const NotificationPrefs = () => {

-

- [PLACEHOLDER] Block visual desktop notifications whenever Urbit software produces an - in-Landscape notification badge. -

-

- Turning this "off" will prompt your browser to ask if you'd like to - enable notifications -

+

Notify me if someone mentions my @p in a channel I've joined

diff --git a/pkg/grid/src/nav/preferences/SystemUpdatePrefs.tsx b/pkg/grid/src/nav/preferences/SystemUpdatePrefs.tsx index 31339bdce1..07252172ff 100644 --- a/pkg/grid/src/nav/preferences/SystemUpdatePrefs.tsx +++ b/pkg/grid/src/nav/preferences/SystemUpdatePrefs.tsx @@ -1,19 +1,30 @@ +import _ from 'lodash'; import React, { ChangeEvent, FormEvent, useCallback, useEffect, useState } from 'react'; import { Button } from '../../components/Button'; import { Setting } from '../../components/Setting'; import { ShipName } from '../../components/ShipName'; import { Spinner } from '../../components/Spinner'; import { useAsyncCall } from '../../logic/useAsyncCall'; -import { usePreferencesStore } from './usePreferencesStore'; +import useKilnState, { useVat } from '../../state/kiln'; export const SystemUpdatePrefs = () => { - const { otasEnabled, otaSource, toggleOTAs, setOTASource } = usePreferencesStore(); - const [source, setSource] = useState(otaSource); + const { changeOTASource, toggleOTAs } = useKilnState((s) => + _.pick(s, ['toggleOTAs', 'changeOTASource']) + ); + const base = useVat('base'); + const otasEnabled = base && !base.arak.paused; + const otaSource = base?.arak.ship; + + const toggleBase = useCallback((on: boolean) => toggleOTAs('base', on), [toggleOTAs]); + + const [source, setSource] = useState(''); const sourceDirty = source !== otaSource; - const { status: sourceStatus, call: setOTA } = useAsyncCall(setOTASource); + const { status: sourceStatus, call: setOTA } = useAsyncCall(changeOTASource); useEffect(() => { - setSource(otaSource); + if (otaSource) { + setSource(otaSource); + } }, [otaSource]); const handleSourceChange = useCallback((e: ChangeEvent) => { @@ -34,11 +45,13 @@ export const SystemUpdatePrefs = () => { <>

System Updates

- +

Automatically download and apply system updates to keep your Urbit up to date.

-

- OTA Source: -

+ {otaSource && ( +

+ OTA Source: +

+ )}