mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-01 03:23:09 +03:00
Merge pull request #5211 from urbit/lf/garden-settings
settings-store: move to garden, namespace
This commit is contained in:
commit
03a7bdda09
44
pkg/garden-dev/sur/settings.hoon
Normal file
44
pkg/garden-dev/sur/settings.hoon
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/+ *mip
|
||||||
|
|%
|
||||||
|
::
|
||||||
|
++ settings-0
|
||||||
|
=< settings
|
||||||
|
|%
|
||||||
|
+$ settings (map key bucket)
|
||||||
|
+$ bucket (map key val)
|
||||||
|
+$ val
|
||||||
|
$% [%s p=@t]
|
||||||
|
[%b p=?]
|
||||||
|
[%n p=@]
|
||||||
|
==
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ settings-1
|
||||||
|
=< settings
|
||||||
|
|%
|
||||||
|
+$ settings (map key bucket)
|
||||||
|
--
|
||||||
|
+$ bucket (map key val)
|
||||||
|
+$ key term
|
||||||
|
+$ val
|
||||||
|
$~ [%n 0]
|
||||||
|
$% [%s p=@t]
|
||||||
|
[%b p=?]
|
||||||
|
[%n p=@]
|
||||||
|
[%a p=(list val)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ settings (mip desk key bucket)
|
||||||
|
+$ event
|
||||||
|
$% [%put-bucket =desk =key =bucket]
|
||||||
|
[%del-bucket =desk =key]
|
||||||
|
[%put-entry =desk buc=key =key =val]
|
||||||
|
[%del-entry =desk buc=key =key]
|
||||||
|
==
|
||||||
|
+$ data
|
||||||
|
$% [%all =settings]
|
||||||
|
[%bucket =bucket]
|
||||||
|
[%desk desk=(map key bucket)]
|
||||||
|
[%entry =val]
|
||||||
|
==
|
||||||
|
--
|
@ -5,11 +5,13 @@
|
|||||||
+$ versioned-state
|
+$ versioned-state
|
||||||
$% state-0
|
$% state-0
|
||||||
state-1
|
state-1
|
||||||
|
state-2
|
||||||
==
|
==
|
||||||
+$ state-0 [%0 settings=settings-0]
|
+$ state-0 [%0 settings=settings-0]
|
||||||
+$ state-1 [%1 =settings]
|
+$ state-1 [%1 settings=settings-1]
|
||||||
|
+$ state-2 [%2 =settings]
|
||||||
--
|
--
|
||||||
=| state-1
|
=| state-2
|
||||||
=* state -
|
=* state -
|
||||||
::
|
::
|
||||||
%- agent:dbug
|
%- agent:dbug
|
||||||
@ -25,9 +27,8 @@
|
|||||||
++ on-init
|
++ on-init
|
||||||
^- (quip card _this)
|
^- (quip card _this)
|
||||||
=^ cards state
|
=^ cards state
|
||||||
(put-entry:do %tutorial %seen b+|)
|
(put-entry:do q.byk.bol %tutorial %seen b+|)
|
||||||
[cards this]
|
[cards this]
|
||||||
|
|
||||||
::
|
::
|
||||||
++ on-save !>(state)
|
++ on-save !>(state)
|
||||||
::
|
::
|
||||||
@ -38,7 +39,8 @@
|
|||||||
|-
|
|-
|
||||||
?- -.old
|
?- -.old
|
||||||
%0 $(old [%1 +.old])
|
%0 $(old [%1 +.old])
|
||||||
%1 [~ this(state old)]
|
%1 $(old [%2 (~(put by *^settings) q.byk.bol settings.old)])
|
||||||
|
%2 `this(state old)
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ on-poke
|
++ on-poke
|
||||||
@ -50,10 +52,10 @@
|
|||||||
=/ evt=event !<(event vas)
|
=/ evt=event !<(event vas)
|
||||||
=^ cards state
|
=^ cards state
|
||||||
?- -.evt
|
?- -.evt
|
||||||
%put-bucket (put-bucket:do key.evt bucket.evt)
|
%put-bucket (put-bucket:do [desk key bucket]:evt)
|
||||||
%del-bucket (del-bucket:do key.evt)
|
%del-bucket (del-bucket:do [desk key]:evt)
|
||||||
%put-entry (put-entry:do buc.evt key.evt val.evt)
|
%put-entry (put-entry:do [desk buc key val]:evt)
|
||||||
%del-entry (del-entry:do buc.evt key.evt)
|
%del-entry (del-entry:do [desk buc key]:evt)
|
||||||
==
|
==
|
||||||
[cards this]
|
[cards this]
|
||||||
::
|
::
|
||||||
@ -65,15 +67,22 @@
|
|||||||
[%all ~]
|
[%all ~]
|
||||||
[~ this]
|
[~ this]
|
||||||
::
|
::
|
||||||
[%bucket @ ~]
|
[%desk @ ~]
|
||||||
=* bucket-key i.t.pax
|
=* desk i.t.pax
|
||||||
?> (~(has by settings) bucket-key)
|
?> (~(has by settings) desk)
|
||||||
[~ this]
|
[~ this]
|
||||||
::
|
::
|
||||||
[%entry @ @ ~]
|
[%bucket @ @ ~]
|
||||||
=* bucket-key i.t.pax
|
=* desk i.t.pax
|
||||||
=* entry-key i.t.t.pax
|
=* bucket-key i.t.t.pax
|
||||||
=/ bucket (~(got by settings) bucket-key)
|
?> (~(has bi settings) desk bucket-key)
|
||||||
|
[~ this]
|
||||||
|
::
|
||||||
|
[%entry @ @ @ ~]
|
||||||
|
=* desk i.t.pax
|
||||||
|
=* bucket-key i.t.t.pax
|
||||||
|
=* entry-key i.t.t.t.pax
|
||||||
|
=/ bucket (~(got bi settings) desk bucket-key)
|
||||||
?> (~(has by bucket) entry-key)
|
?> (~(has by bucket) entry-key)
|
||||||
[~ this]
|
[~ this]
|
||||||
==
|
==
|
||||||
@ -85,29 +94,38 @@
|
|||||||
[%x %all ~]
|
[%x %all ~]
|
||||||
``settings-data+!>(`data`all+settings)
|
``settings-data+!>(`data`all+settings)
|
||||||
::
|
::
|
||||||
[%x %bucket @ ~]
|
[%x %desk @ ~]
|
||||||
=* buc i.t.t.pax
|
=* desk i.t.t.pax
|
||||||
=/ bucket=(unit bucket) (~(get by settings) buc)
|
?~ desk-settings=(~(get by settings) desk) [~ ~]
|
||||||
|
``settings-data+!>(desk+u.desk-settings)
|
||||||
|
::
|
||||||
|
[%x %bucket @ @ ~]
|
||||||
|
=* desk i.t.t.pax
|
||||||
|
=* buc i.t.t.t.pax
|
||||||
|
=/ bucket=(unit bucket) (~(get bi settings) desk buc)
|
||||||
?~ bucket [~ ~]
|
?~ bucket [~ ~]
|
||||||
``settings-data+!>(`data`bucket+u.bucket)
|
``settings-data+!>(`data`bucket+u.bucket)
|
||||||
::
|
::
|
||||||
[%x %entry @ @ ~]
|
[%x %entry @ @ @ ~]
|
||||||
=* buc i.t.t.pax
|
=* desk i.t.t.pax
|
||||||
=* key i.t.t.t.pax
|
=* buc i.t.t.t.pax
|
||||||
=/ =bucket (fall (~(get by settings) buc) ~)
|
=* key i.t.t.t.t.pax
|
||||||
|
=/ =bucket (~(gut bi settings) desk buc *bucket)
|
||||||
=/ entry=(unit val) (~(get by bucket) key)
|
=/ entry=(unit val) (~(get by bucket) key)
|
||||||
?~ entry [~ ~]
|
?~ entry [~ ~]
|
||||||
``settings-data+!>(`data`entry+u.entry)
|
``settings-data+!>(`data`entry+u.entry)
|
||||||
::
|
::
|
||||||
[%x %has-bucket @ ~]
|
[%x %has-bucket @ @ ~]
|
||||||
=* buc i.t.t.pax
|
=/ desk i.t.t.pax
|
||||||
=/ has-bucket=? (~(has by settings) buc)
|
=/ buc i.t.t.t.pax
|
||||||
|
=/ has-bucket=? (~(has bi settings) desk buc)
|
||||||
``noun+!>(`?`has-bucket)
|
``noun+!>(`?`has-bucket)
|
||||||
::
|
::
|
||||||
[%x %has-entry @ @ ~]
|
[%x %has-entry @ @ @ ~]
|
||||||
=* buc i.t.t.pax
|
=* desk i.t.t.pax
|
||||||
=* key i.t.t.t.pax
|
=* buc i.t.t.t.pax
|
||||||
=/ =bucket (fall (~(get by settings) buc) ~)
|
=* key i.t.t.t.t.pax
|
||||||
|
=/ =bucket (~(gut bi settings) desk buc *bucket)
|
||||||
=/ has-entry=? (~(has by bucket) key)
|
=/ has-entry=? (~(has by bucket) key)
|
||||||
``noun+!>(`?`has-entry)
|
``noun+!>(`?`has-entry)
|
||||||
==
|
==
|
||||||
@ -124,60 +142,63 @@
|
|||||||
:: already exists
|
:: already exists
|
||||||
::
|
::
|
||||||
++ put-bucket
|
++ put-bucket
|
||||||
|= [=key =bucket]
|
|= [=desk =key =bucket]
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
=/ pas=(list path)
|
=/ pas=(list path)
|
||||||
:~ /all
|
:~ /all
|
||||||
/bucket/[key]
|
/desk/[desk]
|
||||||
|
/bucket/[desk]/[key]
|
||||||
==
|
==
|
||||||
:- [(give-event pas %put-bucket key bucket)]~
|
:- [(give-event pas %put-bucket desk key bucket)]~
|
||||||
state(settings (~(put by settings) key bucket))
|
state(settings (~(put bi settings) desk key bucket))
|
||||||
::
|
::
|
||||||
:: +del-bucket: delete a bucket from the top level settings map
|
:: +del-bucket: delete a bucket from the top level settings map
|
||||||
::
|
::
|
||||||
++ del-bucket
|
++ del-bucket
|
||||||
|= =key
|
|= [=desk =key]
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
=/ pas=(list path)
|
=/ pas=(list path)
|
||||||
:~ /all
|
:~ /all
|
||||||
|
/desk/[desk]
|
||||||
/bucket/[key]
|
/bucket/[key]
|
||||||
==
|
==
|
||||||
:- [(give-event pas %del-bucket key)]~
|
:- [(give-event pas %del-bucket desk key)]~
|
||||||
state(settings (~(del by settings) key))
|
state(settings (~(del bi settings) desk key))
|
||||||
::
|
::
|
||||||
:: +put-entry: put an entry in a bucket, overwriting if it already exists
|
:: +put-entry: put an entry in a bucket, overwriting if it already exists
|
||||||
:: if bucket does not yet exist, create it
|
:: if bucket does not yet exist, create it
|
||||||
::
|
::
|
||||||
++ put-entry
|
++ put-entry
|
||||||
|= [buc=key =key =val]
|
|= [=desk buc=key =key =val]
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
=/ pas=(list path)
|
=/ pas=(list path)
|
||||||
:~ /all
|
:~ /all
|
||||||
/bucket/[buc]
|
/desk/[desk]
|
||||||
/entry/[buc]/[key]
|
/bucket/[desk]/[buc]
|
||||||
|
/entry/[desk]/[buc]/[key]
|
||||||
==
|
==
|
||||||
=/ =bucket (fall (~(get by settings) buc) ~)
|
=/ =bucket (~(put by (~(gut bi settings) desk buc *bucket)) key val)
|
||||||
=. bucket (~(put by bucket) key val)
|
:- [(give-event pas %put-entry desk buc key val)]~
|
||||||
:- [(give-event pas %put-entry buc key val)]~
|
state(settings (~(put bi settings) desk key bucket))
|
||||||
state(settings (~(put by settings) buc bucket))
|
|
||||||
::
|
::
|
||||||
:: +del-entry: delete an entry from a bucket, fail quietly if bucket does not
|
:: +del-entry: delete an entry from a bucket, fail quietly if bucket does not
|
||||||
:: exist
|
:: exist
|
||||||
::
|
::
|
||||||
++ del-entry
|
++ del-entry
|
||||||
|= [buc=key =key]
|
|= [=desk buc=key =key]
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
=/ pas=(list path)
|
=/ pas=(list path)
|
||||||
:~ /all
|
:~ /all
|
||||||
/bucket/[buc]
|
/desk/[desk]
|
||||||
/entry/[buc]/[key]
|
/bucket/[desk]/[buc]
|
||||||
|
/entry/[desk]/[buc]/[key]
|
||||||
==
|
==
|
||||||
=/ bucket=(unit bucket) (~(get by settings) buc)
|
=/ bucket=(unit bucket) (~(get bi settings) desk buc)
|
||||||
?~ bucket
|
?~ bucket
|
||||||
[~ state]
|
[~ state]
|
||||||
=. u.bucket (~(del by u.bucket) key)
|
=. u.bucket (~(del by u.bucket) key)
|
||||||
:- [(give-event pas %del-entry buc key)]~
|
:- [(give-event pas %del-entry desk buc key)]~
|
||||||
state(settings (~(put by settings) buc u.bucket))
|
state(settings (~(put bi settings) desk buc u.bucket))
|
||||||
::
|
::
|
||||||
++ give-event
|
++ give-event
|
||||||
|= [pas=(list path) evt=event]
|
|= [pas=(list path) evt=event]
|
@ -1,6 +1,7 @@
|
|||||||
:~ :- %apes
|
:~ :- %apes
|
||||||
:~ %docket
|
:~ %docket
|
||||||
%treaty
|
%treaty
|
||||||
|
%settings-store
|
||||||
==
|
==
|
||||||
:- %fish ~
|
:- %fish ~
|
||||||
==
|
==
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
:~ title+'Garden'
|
:~ title+'Garden'
|
||||||
info+'An app launcher for Urbit.'
|
info+'An app launcher for Urbit.'
|
||||||
color+0xee.5432
|
color+0xee.5432
|
||||||
::glob-http+'https://bootstrap.urbit.org/glob-0v6.t43bu.cpl0b.bsisc.sqr4d.dckpn.glob'
|
glob-http+'https://bootstrap.urbit.org/glob-0v6.t43bu.cpl0b.bsisc.sqr4d.dckpn.glob'
|
||||||
glob-ames+~zod
|
::glob-ames+~zod
|
||||||
base+'grid'
|
base+'grid'
|
||||||
version+[0 0 1]
|
version+[0 0 1]
|
||||||
website+'https://tlon.io'
|
website+'https://tlon.io'
|
||||||
|
55
pkg/garden/lib/mip.hoon
Normal file
55
pkg/garden/lib/mip.hoon
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
|%
|
||||||
|
++ mip :: map of maps
|
||||||
|
|$ [kex key value]
|
||||||
|
(map kex (map key value))
|
||||||
|
::
|
||||||
|
++ bi :: mip engine
|
||||||
|
=| a=(map * (map))
|
||||||
|
|@
|
||||||
|
++ del
|
||||||
|
|* [b=* c=*]
|
||||||
|
=+ d=(~(gut by a) b ~)
|
||||||
|
=+ e=(~(del by d) c)
|
||||||
|
?~ e
|
||||||
|
(~(del by a) b)
|
||||||
|
(~(put by a) b e)
|
||||||
|
::
|
||||||
|
++ get
|
||||||
|
|* [b=* c=*]
|
||||||
|
=> .(b `_?>(?=(^ a) p.n.a)`b, c `_?>(?=(^ a) ?>(?=(^ q.n.a) p.n.q.n.a))`c)
|
||||||
|
^- (unit _?>(?=(^ a) ?>(?=(^ q.n.a) q.n.q.n.a)))
|
||||||
|
(~(get by (~(gut by a) b ~)) c)
|
||||||
|
::
|
||||||
|
++ got
|
||||||
|
|* [b=* c=*]
|
||||||
|
(need (get b c))
|
||||||
|
::
|
||||||
|
++ gut
|
||||||
|
|* [b=* c=* d=*]
|
||||||
|
(~(gut by (~(gut by a) b ~)) c d)
|
||||||
|
::
|
||||||
|
++ has
|
||||||
|
|* [b=* c=*]
|
||||||
|
!=(~ (get b c))
|
||||||
|
::
|
||||||
|
++ key
|
||||||
|
|* b=*
|
||||||
|
~(key by (~(gut by a) b ~))
|
||||||
|
::
|
||||||
|
++ put
|
||||||
|
|* [b=* c=* d=*]
|
||||||
|
%+ ~(put by a) b
|
||||||
|
%. [c d]
|
||||||
|
%~ put by
|
||||||
|
(~(gut by a) b ~)
|
||||||
|
::
|
||||||
|
++ tap
|
||||||
|
::NOTE naive turn-based implementation find-errors ):
|
||||||
|
=< $
|
||||||
|
=+ b=`_?>(?=(^ a) *(list [x=_p.n.a _?>(?=(^ q.n.a) [y=p v=q]:n.q.n.a)]))`~
|
||||||
|
|. ^+ b
|
||||||
|
?~ a
|
||||||
|
b
|
||||||
|
$(a r.a, b (welp (turn ~(tap by q.n.a) (lead p.n.a)) $(a l.a)))
|
||||||
|
--
|
||||||
|
--
|
@ -11,11 +11,16 @@
|
|||||||
%all (settings +.dat)
|
%all (settings +.dat)
|
||||||
%bucket (bucket +.dat)
|
%bucket (bucket +.dat)
|
||||||
%entry (value +.dat)
|
%entry (value +.dat)
|
||||||
|
%desk (desk-settings +.dat)
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ settings
|
++ settings
|
||||||
|= s=^settings
|
|= s=^settings
|
||||||
^- json
|
^- json
|
||||||
|
[%o (~(run by s) desk-settings)]
|
||||||
|
::
|
||||||
|
++ desk-settings
|
||||||
|
|= s=(map key ^bucket)
|
||||||
[%o (~(run by s) bucket)]
|
[%o (~(run by s) bucket)]
|
||||||
::
|
::
|
||||||
++ event
|
++ event
|
||||||
@ -30,35 +35,39 @@
|
|||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ put-bucket
|
++ put-bucket
|
||||||
|= [k=key b=^bucket]
|
|= [d=desk k=key b=^bucket]
|
||||||
^- json
|
^- json
|
||||||
%- pairs
|
%- pairs
|
||||||
:~ bucket-key+s+k
|
:~ bucket-key+s+k
|
||||||
bucket+(bucket b)
|
bucket+(bucket b)
|
||||||
|
desk+s+d
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ del-bucket
|
++ del-bucket
|
||||||
|= k=key
|
|= [d=desk k=key]
|
||||||
^- json
|
^- json
|
||||||
%- pairs
|
%- pairs
|
||||||
:~ bucket-key+s+k
|
:~ bucket-key+s+k
|
||||||
|
desk+s+d
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ put-entry
|
++ put-entry
|
||||||
|= [b=key k=key v=val]
|
|= [d=desk b=key k=key v=val]
|
||||||
^- json
|
^- json
|
||||||
%- pairs
|
%- pairs
|
||||||
:~ bucket-key+s+b
|
:~ bucket-key+s+b
|
||||||
entry-key+s+k
|
entry-key+s+k
|
||||||
value+(value v)
|
value+(value v)
|
||||||
|
desk+s+d
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ del-entry
|
++ del-entry
|
||||||
|= [buc=key =key]
|
|= [d=desk buc=key =key]
|
||||||
^- json
|
^- json
|
||||||
%- pairs
|
%- pairs
|
||||||
:~ bucket-key+s+buc
|
:~ bucket-key+s+buc
|
||||||
entry-key+s+key
|
entry-key+s+key
|
||||||
|
desk+s+d
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ value
|
++ value
|
||||||
@ -93,25 +102,29 @@
|
|||||||
::
|
::
|
||||||
++ put-bucket
|
++ put-bucket
|
||||||
%- ot
|
%- ot
|
||||||
:~ bucket-key+so
|
:~ desk+so
|
||||||
|
bucket-key+so
|
||||||
bucket+bucket
|
bucket+bucket
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ del-bucket
|
++ del-bucket
|
||||||
%- ot
|
%- ot
|
||||||
:~ bucket-key+so
|
:~ desk+so
|
||||||
|
bucket-key+so
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ put-entry
|
++ put-entry
|
||||||
%- ot
|
%- ot
|
||||||
:~ bucket-key+so
|
:~ desk+so
|
||||||
|
bucket-key+so
|
||||||
entry-key+so
|
entry-key+so
|
||||||
value+value
|
value+value
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ del-entry
|
++ del-entry
|
||||||
%- ot
|
%- ot
|
||||||
:~ bucket-key+so
|
:~ desk+so
|
||||||
|
bucket-key+so
|
||||||
entry-key+so
|
entry-key+so
|
||||||
==
|
==
|
||||||
::
|
::
|
1
pkg/garden/sur/settings.hoon
Symbolic link
1
pkg/garden/sur/settings.hoon
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../garden-dev/sur/settings.hoon
|
@ -1,15 +1,23 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Setting } from '../../components/Setting';
|
import { Setting } from '../../components/Setting';
|
||||||
|
import { useSettingsState, SettingsState } from '../../state/settings';
|
||||||
import { usePreferencesStore } from './usePreferencesStore';
|
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 = () => {
|
export const NotificationPrefs = () => {
|
||||||
const { doNotDisturb, mentions, toggleDoNotDisturb, toggleMentions } = usePreferencesStore();
|
const { mentions, toggleMentions } = usePreferencesStore();
|
||||||
|
const doNotDisturb = useSettingsState(selDnd);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h2 className="h3 mb-7">Notifications</h2>
|
<h2 className="h3 mb-7">Notifications</h2>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<Setting on={doNotDisturb} toggle={toggleDoNotDisturb} name="Do Not Disturb">
|
<Setting on={doNotDisturb} toggle={toggleDnd} name="Do Not Disturb">
|
||||||
<p>
|
<p>
|
||||||
Block visual desktop notifications whenever Urbit software produces an in-Landscape
|
Block visual desktop notifications whenever Urbit software produces an in-Landscape
|
||||||
notification badge.
|
notification badge.
|
||||||
|
@ -7,6 +7,7 @@ import { persist } from 'zustand/middleware';
|
|||||||
import Urbit, { SubscriptionRequestInterface } from '@urbit/http-api';
|
import Urbit, { SubscriptionRequestInterface } from '@urbit/http-api';
|
||||||
import { Poke } from '@urbit/api';
|
import { Poke } from '@urbit/api';
|
||||||
import api from './api';
|
import api from './api';
|
||||||
|
import { useMockData } from './util';
|
||||||
|
|
||||||
setAutoFreeze(false);
|
setAutoFreeze(false);
|
||||||
enablePatches();
|
enablePatches();
|
||||||
@ -181,7 +182,7 @@ export async function pokeOptimisticallyN<A, S extends Record<string, unknown>>(
|
|||||||
let num: string | undefined;
|
let num: string | undefined;
|
||||||
try {
|
try {
|
||||||
num = optReduceState(state, poke.json, reduce);
|
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);
|
state.getState().removePatch(num);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
98
pkg/grid/src/state/settings.ts
Normal file
98
pkg/grid/src/state/settings.ts
Normal file
@ -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<void>;
|
||||||
|
[ref: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SettingsState = BaseSettingsState & BaseState<BaseSettingsState>;
|
||||||
|
|
||||||
|
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<string, string> = _.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<BaseSettingsState>(
|
||||||
|
'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<DeskData>(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);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
);
|
@ -40,8 +40,8 @@ function delEntry(json: SettingsUpdate, state: any): SettingsState {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAll(json: any, state: SettingsState): SettingsState {
|
function getDesk(json: any, state: SettingsState): SettingsState {
|
||||||
const data = _.get(json, 'all');
|
const data = _.get(json, 'desk');
|
||||||
if(data) {
|
if(data) {
|
||||||
_.mergeWith(state, data, (obj, src) => _.isArray(src) ? src : undefined);
|
_.mergeWith(state, data, (obj, src) => _.isArray(src) ? src : undefined);
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ export const reduceUpdate = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const reduceScry = [
|
export const reduceScry = [
|
||||||
getAll,
|
getDesk,
|
||||||
getBucket,
|
getBucket,
|
||||||
getEntry
|
getEntry
|
||||||
];
|
];
|
||||||
|
@ -16,7 +16,7 @@ import {
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { reduceUpdate } from '../reducers/settings-update';
|
import { reduceUpdate } from '../reducers/settings-update';
|
||||||
import airlock from '~/logic/api';
|
import airlock from '~/logic/api';
|
||||||
import { getAll, Value } from '@urbit/api';
|
import { getDeskSettings, Value } from '@urbit/api';
|
||||||
import { putEntry } from '@urbit/api/settings';
|
import { putEntry } from '@urbit/api/settings';
|
||||||
|
|
||||||
export interface ShortcutMapping {
|
export interface ShortcutMapping {
|
||||||
@ -45,7 +45,7 @@ export interface SettingsState {
|
|||||||
keyboard: ShortcutMapping;
|
keyboard: ShortcutMapping;
|
||||||
remoteContentPolicy: RemoteContentPolicy;
|
remoteContentPolicy: RemoteContentPolicy;
|
||||||
getAll: () => Promise<void>;
|
getAll: () => Promise<void>;
|
||||||
putEntry: (bucket: string, key: string, value: Value) => void;
|
putEntry: (bucket: string, key: string, value: Value) => Promise<void>;
|
||||||
leap: {
|
leap: {
|
||||||
categories: LeapCategories[];
|
categories: LeapCategories[];
|
||||||
};
|
};
|
||||||
@ -101,20 +101,22 @@ const useSettingsState = createState<SettingsState>(
|
|||||||
readGroup: 'shift+Escape'
|
readGroup: 'shift+Escape'
|
||||||
},
|
},
|
||||||
getAll: async () => {
|
getAll: async () => {
|
||||||
const { all } = await airlock.scry(getAll);
|
const { desk } = await airlock.scry(getDeskSettings((window as any).desk));
|
||||||
get().set((s) => {
|
get().set((s) => {
|
||||||
Object.assign(s, all);
|
for(const bucket in desk) {
|
||||||
|
s[bucket] = { ...(s[bucket] || {}), ...desk[bucket] };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
putEntry: (bucket: string, entry: string, value: Value) => {
|
putEntry: async (bucket: string, entry: string, value: Value) => {
|
||||||
const poke = putEntry(bucket, entry, value);
|
const poke = putEntry((window as any).desk, bucket, entry, value);
|
||||||
pokeOptimisticallyN(useSettingsState, poke, reduceUpdate);
|
pokeOptimisticallyN(useSettingsState, poke, reduceUpdate);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
[
|
[
|
||||||
(set, get) =>
|
(set, get) =>
|
||||||
createSubscription('settings-store', '/all', (e) => {
|
createSubscription('settings-store', `/desk/${(window as any).desk}`, (e) => {
|
||||||
const data = _.get(e, 'settings-event', false);
|
const data = _.get(e, 'settings-event', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
reduceStateN(get(), data, reduceUpdate);
|
reduceStateN(get(), data, reduceUpdate);
|
||||||
|
@ -32,7 +32,6 @@ import Tiles from './components/tiles';
|
|||||||
import Tile from './components/tiles/tile';
|
import Tile from './components/tiles/tile';
|
||||||
import './css/custom.css';
|
import './css/custom.css';
|
||||||
import { join } from '@urbit/api/groups';
|
import { join } from '@urbit/api/groups';
|
||||||
import { putEntry } from '@urbit/api/settings';
|
|
||||||
import { joinGraph } from '@urbit/api/graph';
|
import { joinGraph } from '@urbit/api/graph';
|
||||||
import airlock from '~/logic/api';
|
import airlock from '~/logic/api';
|
||||||
|
|
||||||
@ -103,15 +102,17 @@ export const LaunchApp = (props: LaunchAppProps): ReactElement | null => {
|
|||||||
maxWidth: '350px',
|
maxWidth: '350px',
|
||||||
modal: function modal(dismiss) {
|
modal: function modal(dismiss) {
|
||||||
const onDismiss = (e) => {
|
const onDismiss = (e) => {
|
||||||
|
const { putEntry } = useSettingsState.getState();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
airlock.poke(putEntry('tutorial', 'seen', true));
|
putEntry('tutorial', 'seen', true);
|
||||||
dismiss();
|
dismiss();
|
||||||
};
|
};
|
||||||
const onContinue = async (e) => {
|
const onContinue = async (e) => {
|
||||||
|
const { putEntry } = useSettingsState.getState();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (!hasTutorialGroup({ associations })) {
|
if (!hasTutorialGroup({ associations })) {
|
||||||
await airlock.poke(join(TUTORIAL_HOST, TUTORIAL_GROUP));
|
await airlock.poke(join(TUTORIAL_HOST, TUTORIAL_GROUP));
|
||||||
await airlock.poke(putEntry('tutorial', 'joined', Date.now()));
|
await putEntry('tutorial', 'joined', Date.now());
|
||||||
await waiter(hasTutorialGroup);
|
await waiter(hasTutorialGroup);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
[TUTORIAL_BOOK, TUTORIAL_CHAT, TUTORIAL_LINKS].map(graph => airlock.thread(joinGraph(TUTORIAL_HOST, graph))));
|
[TUTORIAL_BOOK, TUTORIAL_CHAT, TUTORIAL_LINKS].map(graph => airlock.thread(joinGraph(TUTORIAL_HOST, graph))));
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
ManagedCheckboxField, Text
|
ManagedCheckboxField, Text
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { Form, useFormikContext } from 'formik';
|
import { Form, useFormikContext } from 'formik';
|
||||||
import { putEntry } from '@urbit/api/settings';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import useSettingsState, { selectSettingsState } from '~/logic/state/settings';
|
import useSettingsState, { selectSettingsState } from '~/logic/state/settings';
|
||||||
@ -15,7 +14,6 @@ import {
|
|||||||
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
|
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
|
||||||
import { ShuffleFields } from '~/views/components/ShuffleFields';
|
import { ShuffleFields } from '~/views/components/ShuffleFields';
|
||||||
import { BackButton } from './BackButton';
|
import { BackButton } from './BackButton';
|
||||||
import airlock from '~/logic/api';
|
|
||||||
|
|
||||||
const labels: Record<LeapCategories, string> = {
|
const labels: Record<LeapCategories, string> = {
|
||||||
mychannel: 'My Channels',
|
mychannel: 'My Channels',
|
||||||
@ -60,11 +58,12 @@ export function LeapSettings() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = async (values: FormSchema) => {
|
const onSubmit = async (values: FormSchema) => {
|
||||||
|
const { putEntry } = useSettingsState.getState();
|
||||||
const result = values.categories.reduce(
|
const result = values.categories.reduce(
|
||||||
(acc, { display, category }) => (display ? [...acc, category] : acc),
|
(acc, { display, category }) => (display ? [...acc, category] : acc),
|
||||||
[] as LeapCategories[]
|
[] as LeapCategories[]
|
||||||
);
|
);
|
||||||
await airlock.poke(putEntry('leap', 'categories', result));
|
await putEntry('leap', 'categories', result);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -3,7 +3,6 @@ import _ from 'lodash';
|
|||||||
|
|
||||||
import { Box, Col, Text } from '@tlon/indigo-react';
|
import { Box, Col, Text } from '@tlon/indigo-react';
|
||||||
import { Formik, Form, useField } from 'formik';
|
import { Formik, Form, useField } from 'formik';
|
||||||
import { putEntry } from '@urbit/api/settings';
|
|
||||||
|
|
||||||
import { getChord } from '~/logic/lib/util';
|
import { getChord } from '~/logic/lib/util';
|
||||||
import useSettingsState, {
|
import useSettingsState, {
|
||||||
@ -12,7 +11,6 @@ import useSettingsState, {
|
|||||||
} from '~/logic/state/settings';
|
} from '~/logic/state/settings';
|
||||||
import { AsyncButton } from '~/views/components/AsyncButton';
|
import { AsyncButton } from '~/views/components/AsyncButton';
|
||||||
import { BackButton } from './BackButton';
|
import { BackButton } from './BackButton';
|
||||||
import airlock from '~/logic/api';
|
|
||||||
|
|
||||||
const settingsSel = selectSettingsState(['keyboard']);
|
const settingsSel = selectSettingsState(['keyboard']);
|
||||||
|
|
||||||
@ -69,9 +67,10 @@ export default function ShortcutSettings() {
|
|||||||
initialValues={keyboard}
|
initialValues={keyboard}
|
||||||
onSubmit={async (values: ShortcutMapping, actions) => {
|
onSubmit={async (values: ShortcutMapping, actions) => {
|
||||||
const promises = _.map(values, (value, key) => {
|
const promises = _.map(values, (value, key) => {
|
||||||
|
const { putEntry } = useSettingsState.getState();
|
||||||
return keyboard[key] !== value
|
return keyboard[key] !== value
|
||||||
? airlock.poke(putEntry('keyboard', key, value))
|
? putEntry('keyboard', key, value)
|
||||||
: Promise.resolve(0);
|
: Promise.resolve();
|
||||||
});
|
});
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
actions.setStatus({ success: null });
|
actions.setStatus({ success: null });
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
ManagedTextInputField as Input, Row,
|
ManagedTextInputField as Input, Row,
|
||||||
Text
|
Text
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { join, MetadataUpdatePreview, putEntry } from '@urbit/api';
|
import { join, MetadataUpdatePreview } from '@urbit/api';
|
||||||
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { ReactElement, useCallback, useEffect, useState } from 'react';
|
import React, { ReactElement, useCallback, useEffect, useState } from 'react';
|
||||||
@ -22,6 +22,7 @@ import { FormError } from '~/views/components/FormError';
|
|||||||
import { StatelessAsyncButton } from '~/views/components/StatelessAsyncButton';
|
import { StatelessAsyncButton } from '~/views/components/StatelessAsyncButton';
|
||||||
import { GroupSummary } from './GroupSummary';
|
import { GroupSummary } from './GroupSummary';
|
||||||
import airlock from '~/logic/api';
|
import airlock from '~/logic/api';
|
||||||
|
import useSettingsState from '~/logic/state/settings';
|
||||||
|
|
||||||
const formSchema = Yup.object({
|
const formSchema = Yup.object({
|
||||||
group: Yup.string()
|
group: Yup.string()
|
||||||
@ -73,8 +74,9 @@ export function JoinGroup(props: JoinGroupProps): ReactElement {
|
|||||||
|
|
||||||
const onConfirm = useCallback(async (group: string) => {
|
const onConfirm = useCallback(async (group: string) => {
|
||||||
const [,,ship,name] = group.split('/');
|
const [,,ship,name] = group.split('/');
|
||||||
|
const { putEntry } = useSettingsState.getState();
|
||||||
if(group === TUTORIAL_GROUP_RESOURCE) {
|
if(group === TUTORIAL_GROUP_RESOURCE) {
|
||||||
await airlock.poke(putEntry('tutorial', 'joined', Date.now()));
|
await putEntry('tutorial', 'joined', Date.now());
|
||||||
}
|
}
|
||||||
if (group in groups) {
|
if (group in groups) {
|
||||||
return history.push(`/~landscape${group}`);
|
return history.push(`/~landscape${group}`);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Box, Button, Col, Icon, Row, Text } from '@tlon/indigo-react';
|
import { Box, Button, Col, Icon, Row, Text } from '@tlon/indigo-react';
|
||||||
import { leaveGroup, putEntry } from '@urbit/api';
|
import { leaveGroup } from '@urbit/api';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
@ -16,6 +16,7 @@ import { Portal } from '~/views/components/Portal';
|
|||||||
import { StatelessAsyncButton } from '~/views/components/StatelessAsyncButton';
|
import { StatelessAsyncButton } from '~/views/components/StatelessAsyncButton';
|
||||||
import { Triangle } from '~/views/components/Triangle';
|
import { Triangle } from '~/views/components/Triangle';
|
||||||
import airlock from '~/logic/api';
|
import airlock from '~/logic/api';
|
||||||
|
import useSettingsState from '~/logic/state/settings';
|
||||||
|
|
||||||
const localSelector = selectLocalState([
|
const localSelector = selectLocalState([
|
||||||
'tutorialProgress',
|
'tutorialProgress',
|
||||||
@ -94,7 +95,8 @@ export function TutorialModal() {
|
|||||||
const dismiss = useCallback(async () => {
|
const dismiss = useCallback(async () => {
|
||||||
setPaused(false);
|
setPaused(false);
|
||||||
hideTutorial();
|
hideTutorial();
|
||||||
await airlock.poke(putEntry('tutorial', 'seen', true));
|
const { putEntry } = useSettingsState.getState();
|
||||||
|
await putEntry('tutorial', 'seen', true);
|
||||||
}, [hideTutorial]);
|
}, [hideTutorial]);
|
||||||
|
|
||||||
const bailExit = useCallback(() => {
|
const bailExit = useCallback(() => {
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
%observe-hook
|
%observe-hook
|
||||||
%s3-store
|
%s3-store
|
||||||
%sane
|
%sane
|
||||||
%settings-store
|
|
||||||
%weather
|
%weather
|
||||||
==
|
==
|
||||||
:- %fish
|
:- %fish
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
:~ title+'Landscape'
|
:~ title+'Landscape'
|
||||||
info+'A suite of applications to communicate on Urbit'
|
info+'A suite of applications to communicate on Urbit'
|
||||||
color+0xee.5432
|
color+0xee.5432
|
||||||
glob+'https://bootstrap.urbit.org/glob-0v4.0k6hb.4s38v.su79d.10vd5.7c8lu.glob'
|
glob-http+'https://bootstrap.urbit.org/glob-0v4.0k6hb.4s38v.su79d.10vd5.7c8lu.glob'
|
||||||
base+'landscape'
|
base+'landscape'
|
||||||
version+[0 0 1]
|
version+[0 0 1]
|
||||||
website+'https://tlon.io'
|
website+'https://tlon.io'
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
|%
|
|
||||||
+$ settings-0 (map key bucket-0)
|
|
||||||
+$ bucket-0 (map key val-0)
|
|
||||||
+$ val-0
|
|
||||||
$% [%s p=@t]
|
|
||||||
[%b p=?]
|
|
||||||
[%n p=@]
|
|
||||||
==
|
|
||||||
::
|
|
||||||
+$ settings (map key bucket)
|
|
||||||
+$ bucket (map key val)
|
|
||||||
+$ key term
|
|
||||||
+$ val
|
|
||||||
$~ [%n 0]
|
|
||||||
$% [%s p=@t]
|
|
||||||
[%b p=?]
|
|
||||||
[%n p=@]
|
|
||||||
[%a p=(list val)]
|
|
||||||
==
|
|
||||||
+$ event
|
|
||||||
$% [%put-bucket =key =bucket]
|
|
||||||
[%del-bucket =key]
|
|
||||||
[%put-entry buc=key =key =val]
|
|
||||||
[%del-entry buc=key =key]
|
|
||||||
==
|
|
||||||
+$ data
|
|
||||||
$% [%all =settings]
|
|
||||||
[%bucket =bucket]
|
|
||||||
[%entry =val]
|
|
||||||
==
|
|
||||||
--
|
|
1
pkg/landscape/sur/settings.hoon
Symbolic link
1
pkg/landscape/sur/settings.hoon
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../garden-dev/sur/settings.hoon
|
@ -44,15 +44,16 @@
|
|||||||
++ read-setting
|
++ read-setting
|
||||||
|= key=term
|
|= key=term
|
||||||
=/ m (strand @t) ^- form:m
|
=/ m (strand @t) ^- form:m
|
||||||
|
;< =bowl:spider bind:m get-bowl:strandio
|
||||||
;< has=? bind:m
|
;< has=? bind:m
|
||||||
%+ scry:strandio ?
|
%+ scry:strandio ?
|
||||||
/gx/settings-store/has-entry/gcp-store/[key]/noun
|
/gx/settings-store/has-entry/[q.byk.bowl]/gcp-store/[key]/noun
|
||||||
?. has
|
?. has
|
||||||
(strand-fail:strandio (rap 3 %gcp-missing- key ~) ~)
|
(strand-fail:strandio (rap 3 %gcp-missing- key ~) ~)
|
||||||
;< =data:settings bind:m
|
;< =data:settings bind:m
|
||||||
%+ scry:strandio
|
%+ scry:strandio
|
||||||
data:settings
|
data:settings
|
||||||
/gx/settings-store/entry/gcp-store/[key]/settings-data
|
/gx/settings-store/entry/[q.byk.bowl]/gcp-store/[key]/settings-data
|
||||||
?> ?=([%entry %s @] data)
|
?> ?=([%entry %s @] data)
|
||||||
(pure:m p.val.data)
|
(pure:m p.val.data)
|
||||||
::
|
::
|
||||||
|
@ -40,9 +40,10 @@ b+has
|
|||||||
|= key=@tas
|
|= key=@tas
|
||||||
=/ m (strand ?)
|
=/ m (strand ?)
|
||||||
^- form:m
|
^- form:m
|
||||||
|
;< =bowl:spider bind:m get-bowl:strandio
|
||||||
;< has=? bind:m
|
;< has=? bind:m
|
||||||
%+ scry:strandio ?
|
%+ scry:strandio ?
|
||||||
/gx/settings-store/has-entry/gcp-store/[key]/noun
|
/gx/settings-store/has-entry/[q.byk.bowl]/gcp-store/[key]/noun
|
||||||
(pure:m has)
|
(pure:m has)
|
||||||
::
|
::
|
||||||
--
|
--
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Poke, Scry } from "../lib";
|
import { Poke, Scry } from '../lib';
|
||||||
import { PutBucket, Key, Bucket, DelBucket, Value, PutEntry, DelEntry, SettingsUpdate } from './types';
|
import { PutBucket, Key, Bucket, DelBucket, Value, PutEntry, DelEntry, SettingsUpdate } from './types';
|
||||||
|
|
||||||
export const action = <T extends SettingsUpdate>(data: T): Poke<T> => ({
|
export const action = <T extends SettingsUpdate>(data: T): Poke<T> => ({
|
||||||
@ -8,29 +8,35 @@ export const action = <T extends SettingsUpdate>(data: T): Poke<T> => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const putBucket = (
|
export const putBucket = (
|
||||||
|
desk: string,
|
||||||
key: Key,
|
key: Key,
|
||||||
bucket: Bucket
|
bucket: Bucket
|
||||||
): Poke<PutBucket> => action({
|
): Poke<PutBucket> => action({
|
||||||
'put-bucket': {
|
'put-bucket': {
|
||||||
|
desk,
|
||||||
'bucket-key': key,
|
'bucket-key': key,
|
||||||
'bucket': bucket
|
'bucket': bucket
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const delBucket = (
|
export const delBucket = (
|
||||||
|
desk: string,
|
||||||
key: Key
|
key: Key
|
||||||
): Poke<DelBucket> => action({
|
): Poke<DelBucket> => action({
|
||||||
'del-bucket': {
|
'del-bucket': {
|
||||||
|
desk,
|
||||||
'bucket-key': key
|
'bucket-key': key
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const putEntry = (
|
export const putEntry = (
|
||||||
|
desk: string,
|
||||||
bucket: Key,
|
bucket: Key,
|
||||||
key: Key,
|
key: Key,
|
||||||
value: Value
|
value: Value
|
||||||
): Poke<PutEntry> => action({
|
): Poke<PutEntry> => action({
|
||||||
'put-entry': {
|
'put-entry': {
|
||||||
|
desk,
|
||||||
'bucket-key': bucket,
|
'bucket-key': bucket,
|
||||||
'entry-key': key,
|
'entry-key': key,
|
||||||
value: value
|
value: value
|
||||||
@ -38,10 +44,12 @@ export const putEntry = (
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const delEntry = (
|
export const delEntry = (
|
||||||
|
desk: string,
|
||||||
bucket: Key,
|
bucket: Key,
|
||||||
key: Key
|
key: Key
|
||||||
): Poke<DelEntry> => action({
|
): Poke<DelEntry> => action({
|
||||||
'del-entry': {
|
'del-entry': {
|
||||||
|
desk,
|
||||||
'bucket-key': bucket,
|
'bucket-key': bucket,
|
||||||
'entry-key': key
|
'entry-key': key
|
||||||
}
|
}
|
||||||
@ -50,17 +58,21 @@ export const delEntry = (
|
|||||||
export const getAll: Scry = {
|
export const getAll: Scry = {
|
||||||
app: 'settings-store',
|
app: 'settings-store',
|
||||||
path: '/all'
|
path: '/all'
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getBucket = (bucket: string) => ({
|
export const getBucket = (desk: string, bucket: string) => ({
|
||||||
app: 'settings-store',
|
app: 'settings-store',
|
||||||
path: `/bucket/${bucket}`
|
path: `/bucket/${bucket}`
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getEntry = (bucket: string, entry: string) => ({
|
export const getEntry = (desk: string, bucket: string, entry: string) => ({
|
||||||
app: 'settings-store',
|
app: 'settings-store',
|
||||||
path: `/entry/${bucket}/${entry}`
|
path: `/entry/${desk}/${bucket}/${entry}`
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getDeskSettings = (desk: string) => ({
|
||||||
|
app: 'settings-store',
|
||||||
|
path: `/desk/${desk}`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
@ -1,46 +1,54 @@
|
|||||||
export type Key = string;
|
export type Key = string;
|
||||||
export type Value = string | string[] | boolean | number;
|
export type Value = string | string[] | boolean | number;
|
||||||
export type Bucket = Map<string, Value>;
|
export type Bucket = { [key: string]: Value; };
|
||||||
export type Settings = Map<string, Bucket>;
|
export type DeskSettings = { [bucket: string]: Bucket; };
|
||||||
|
export type Settings = { [desk: string]: Settings; }
|
||||||
|
|
||||||
export interface PutBucket {
|
export interface PutBucket {
|
||||||
"put-bucket": {
|
'put-bucket': {
|
||||||
"bucket-key": Key;
|
desk: string;
|
||||||
"bucket": Bucket;
|
'bucket-key': Key;
|
||||||
|
'bucket': Bucket;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DelBucket {
|
export interface DelBucket {
|
||||||
"del-bucket": {
|
'del-bucket': {
|
||||||
"bucket-key": Key;
|
desk: string;
|
||||||
|
'bucket-key': Key;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PutEntry {
|
export interface PutEntry {
|
||||||
"put-entry": {
|
'put-entry': {
|
||||||
"bucket-key": Key;
|
'bucket-key': Key;
|
||||||
"entry-key": Key;
|
'entry-key': Key;
|
||||||
"value"?: Value;
|
'value'?: Value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DelEntry {
|
export interface DelEntry {
|
||||||
"del-entry": {
|
'del-entry': {
|
||||||
"bucket-key": Key;
|
desk: string;
|
||||||
"entry-key": Key;
|
'bucket-key': Key;
|
||||||
|
'entry-key': Key;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AllData {
|
export interface AllData {
|
||||||
"all": Settings;
|
'all': Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeskData {
|
||||||
|
desk: DeskSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BucketData {
|
export interface BucketData {
|
||||||
"bucket": Bucket;
|
'bucket': Bucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntryData {
|
export interface EntryData {
|
||||||
"entry": Value;
|
'entry': Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SettingsUpdate =
|
export type SettingsUpdate =
|
||||||
@ -52,4 +60,5 @@ export type SettingsUpdate =
|
|||||||
export type SettingsData =
|
export type SettingsData =
|
||||||
| AllData
|
| AllData
|
||||||
| BucketData
|
| BucketData
|
||||||
| EntryData;
|
| EntryData
|
||||||
|
| DeskData;
|
||||||
|
Loading…
Reference in New Issue
Block a user