mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-29 12:15:43 +03:00
Merge remote-tracking branch 'origin/release/next-userspace' into lf/revive-resume
This commit is contained in:
commit
77c2b5d46c
@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:02677dba866b8c165c10bffc409cef6a74c979edb83cade6cab2f67a50bb0fc1
|
oid sha256:a36f646746ed95440fa7586e1c51c5402a2e117386ec82fdb6263a1c20b2fd65
|
||||||
size 12852855
|
size 12867464
|
||||||
|
@ -26,6 +26,6 @@
|
|||||||
<div id="portal-root"></div>
|
<div id="portal-root"></div>
|
||||||
<script src="/~landscape/js/channel.js"></script>
|
<script src="/~landscape/js/channel.js"></script>
|
||||||
<script src="/~landscape/js/session.js"></script>
|
<script src="/~landscape/js/session.js"></script>
|
||||||
<script src="/~btc/js/bundle/index.3e8bcc150ebd820dd3b2.js"></script>
|
<script src="/~btc/js/bundle/index.02730169f3d73fd22950.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
/- glob, *resource
|
/- glob, *resource
|
||||||
/+ default-agent, verb, dbug
|
/+ default-agent, verb, dbug
|
||||||
|%
|
|%
|
||||||
++ landscape-hash 0vrbiqe.v6al2.0b4jc.u9vp7.k1e0i
|
++ landscape-hash 0v5.48552.hdu43.jrjb7.jd19b.74vpc
|
||||||
++ btc-wallet-hash 0v7.v4dng.o33qi.kc497.5jc02.ke5es
|
++ btc-wallet-hash 0v2.ifoe4.fbv35.aigir.66su4.fbspu
|
||||||
+$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))]
|
+$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))]
|
||||||
+$ state-1 [%1 =globs:glob]
|
+$ state-1 [%1 =globs:glob]
|
||||||
+$ all-states
|
+$ all-states
|
||||||
|
@ -180,10 +180,7 @@
|
|||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ add-nodes
|
++ add-nodes
|
||||||
|= $: =time
|
|= [=time =resource:store nodes=(map index:store node:store)]
|
||||||
=resource:store
|
|
||||||
nodes=(map index:store node:store)
|
|
||||||
==
|
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
|^
|
|^
|
||||||
=/ [=graph:store mark=(unit mark:store)]
|
=/ [=graph:store mark=(unit mark:store)]
|
||||||
@ -618,392 +615,283 @@
|
|||||||
~/ %graph-store-peek
|
~/ %graph-store-peek
|
||||||
|= =path
|
|= =path
|
||||||
^- (unit (unit cage))
|
^- (unit (unit cage))
|
||||||
|^
|
?+ path (on-peek:def path)
|
||||||
?> (team:title our.bowl src.bowl)
|
[%x %export ~] ``noun+!>(state)
|
||||||
?+ path (on-peek:def path)
|
|
||||||
[%x %graph-mark @ @ ~]
|
|
||||||
=/ =ship (slav %p i.t.t.path)
|
|
||||||
=/ =term i.t.t.t.path
|
|
||||||
=/ result=(unit marked-graph:store)
|
|
||||||
(~(get by graphs) [ship term])
|
|
||||||
?~ result [~ ~]
|
|
||||||
``noun+!>(`(unit mark)`q.u.result)
|
|
||||||
::
|
::
|
||||||
[%x %keys ~]
|
[%x %keys ~]
|
||||||
:- ~ :- ~ :- %graph-update-2
|
:- ~ :- ~ :- %graph-update-2
|
||||||
!>(`update:store`[now.bowl [%keys ~(key by graphs)]])
|
!>(`update:store`[now.bowl [%keys ~(key by graphs)]])
|
||||||
::
|
::
|
||||||
[%x %tags ~]
|
[%x %tag-queries *]
|
||||||
:- ~ :- ~ :- %graph-update-2
|
|
||||||
!>(`update:store`[now.bowl [%tags ~(key by tag-queries)]])
|
|
||||||
::
|
|
||||||
[%x %tag-queries ~]
|
|
||||||
:- ~ :- ~ :- %graph-update-2
|
|
||||||
!>(`update:store`[now.bowl [%tag-queries tag-queries]])
|
|
||||||
::
|
|
||||||
[%x %graph @ @ ~]
|
|
||||||
=/ =ship (slav %p i.t.t.path)
|
|
||||||
=/ =term i.t.t.t.path
|
|
||||||
=/ result=(unit marked-graph:store)
|
|
||||||
(~(get by graphs) [ship term])
|
|
||||||
?~ result [~ ~]
|
|
||||||
:- ~ :- ~ :- %graph-update-2
|
:- ~ :- ~ :- %graph-update-2
|
||||||
!> ^- update:store
|
!> ^- update:store
|
||||||
:- now.bowl
|
:- now.bowl
|
||||||
[%add-graph [ship term] `graph:store`p.u.result q.u.result %.y]
|
?+ t.t.path (on-peek:def path)
|
||||||
|
~ [%tag-queries tag-queries]
|
||||||
|
[%tags ~] [%tags ~(key by tag-queries)]
|
||||||
|
==
|
||||||
::
|
::
|
||||||
:: note: near-duplicate of /x/graph
|
|
||||||
::
|
|
||||||
[%x %archive @ @ ~]
|
[%x %archive @ @ ~]
|
||||||
=/ =ship (slav %p i.t.t.path)
|
=/ =ship (slav %p i.t.t.path)
|
||||||
=/ =term i.t.t.t.path
|
=/ =term i.t.t.t.path
|
||||||
=/ result=(unit marked-graph:store)
|
=/ marked-graph=(unit marked-graph:store)
|
||||||
(~(get by archive) [ship term])
|
|
||||||
?~ result
|
|
||||||
~& no-archived-graph+[ship term]
|
|
||||||
[~ ~]
|
|
||||||
:- ~ :- ~ :- %graph-update-2
|
|
||||||
!> ^- update:store
|
|
||||||
:- now.bowl
|
|
||||||
[%add-graph [ship term] `graph:store`p.u.result q.u.result %.y]
|
|
||||||
::
|
|
||||||
[%x %export ~]
|
|
||||||
``noun+!>(state)
|
|
||||||
::
|
|
||||||
[%x %graph-subset @ @ @ @ ~]
|
|
||||||
=/ =ship (slav %p i.t.t.path)
|
|
||||||
=/ =term i.t.t.t.path
|
|
||||||
=/ start=(unit atom) (rush i.t.t.t.t.path dem:ag)
|
|
||||||
=/ end=(unit atom) (rush i.t.t.t.t.t.path dem:ag)
|
|
||||||
=/ graph=(unit marked-graph:store)
|
|
||||||
(~(get by graphs) [ship term])
|
(~(get by graphs) [ship term])
|
||||||
?~ graph [~ ~]
|
?~ marked-graph [~ ~]
|
||||||
|
=* graph p.u.marked-graph
|
||||||
|
=* mark q.u.marked-graph
|
||||||
:- ~ :- ~ :- %graph-update-2
|
:- ~ :- ~ :- %graph-update-2
|
||||||
!> ^- update:store
|
!>(`update:store`[now.bowl [%add-graph [ship term] graph mark %.y]])
|
||||||
:- now.bowl
|
|
||||||
:+ %add-nodes
|
|
||||||
[ship term]
|
|
||||||
%- ~(gas by *(map index:store node:store))
|
|
||||||
%+ turn (tap:orm `graph:store`(lot:orm p.u.graph start end))
|
|
||||||
|= [=atom =node:store]
|
|
||||||
^- [index:store node:store]
|
|
||||||
[~[atom] node]
|
|
||||||
::
|
::
|
||||||
[%x %node-exists @ @ @ *]
|
[%x %update-log @ @ *]
|
||||||
=/ =ship (slav %p i.t.t.path)
|
=/ =ship (slav %p i.t.t.path)
|
||||||
=/ =term i.t.t.t.path
|
=/ =term i.t.t.t.path
|
||||||
=/ =index:store
|
=/ update-log
|
||||||
(turn t.t.t.t.path (cury slav %ud))
|
(~(get by update-logs) [ship term])
|
||||||
=/ node=(unit node:store)
|
?~ update-log [~ ~]
|
||||||
(get-node ship term index)
|
:- ~ :- ~ :- %noun
|
||||||
``noun+!>(`?`?=(^ node))
|
!>
|
||||||
::
|
?+ t.t.t.t.path (on-peek:def path)
|
||||||
[%x %node @ @ @ *]
|
~ `update-log:store`u.update-log
|
||||||
=/ =ship (slav %p i.t.t.path)
|
|
||||||
=/ =term i.t.t.t.path
|
|
||||||
=/ =index:store
|
|
||||||
(turn t.t.t.t.path (cury slav %ud))
|
|
||||||
=/ node=(unit node:store) (get-node ship term index)
|
|
||||||
?~ node [~ ~]
|
|
||||||
:- ~ :- ~ :- %graph-update-2
|
|
||||||
!> ^- update:store
|
|
||||||
:- now.bowl
|
|
||||||
:+ %add-nodes
|
|
||||||
[ship term]
|
|
||||||
(~(gas by *(map index:store node:store)) [index u.node] ~)
|
|
||||||
::
|
|
||||||
[%x %node-siblings ?(%older %younger) @ @ @ *]
|
|
||||||
|^
|
|
||||||
=/ older ?=(%older i.t.t.path)
|
|
||||||
=/ =ship (slav %p i.t.t.t.path)
|
|
||||||
=/ =term i.t.t.t.t.path
|
|
||||||
=/ count (slav %ud i.t.t.t.t.t.path)
|
|
||||||
=/ =index:store
|
|
||||||
(turn t.t.t.t.t.t.path (cury slav %ud))
|
|
||||||
=/ parent=index:store
|
|
||||||
(scag (dec (lent index)) index)
|
|
||||||
=/ graph
|
|
||||||
(get-node-children ship term parent)
|
|
||||||
?~ graph [~ ~]
|
|
||||||
:- ~ :- ~ :- %graph-update-2
|
|
||||||
!> ^- update:store
|
|
||||||
:- now.bowl
|
|
||||||
:+ %add-nodes
|
|
||||||
[ship term]
|
|
||||||
%- ~(gas by *(map index:store node:store))
|
|
||||||
%+ turn
|
|
||||||
?: older
|
|
||||||
(tab:orm u.graph `(rear index) count)
|
|
||||||
:: TODO time complexity not desirable for %younger case
|
|
||||||
::
|
|
||||||
%+ slag (safe-sub (lent -) count)
|
|
||||||
%- tap:orm
|
|
||||||
%+ lot:orm u.graph
|
|
||||||
[~ `(snag (dec (lent index)) index)]
|
|
||||||
|= [=atom =node:store]
|
|
||||||
^- [index:store node:store]
|
|
||||||
[(snoc parent atom) node]
|
|
||||||
::
|
::
|
||||||
++ safe-sub
|
[%latest ~]
|
||||||
|= [a=@ b=@]
|
^- (unit time)
|
||||||
^- @
|
%+ biff update-log
|
||||||
?: (gte b a)
|
|= =update-log:store
|
||||||
0
|
(bind (pry:orm-log:store update-log) head)
|
||||||
(sub a b)
|
::
|
||||||
--
|
[%subset @ @ ~]
|
||||||
|
^- update-log:store
|
||||||
|
=* start i.t.t.t.t.t.path
|
||||||
|
=* end i.t.t.t.t.t.t.path
|
||||||
|
%^ lot:orm-log
|
||||||
|
u.update-log
|
||||||
|
(slaw %da start)
|
||||||
|
(slaw %da end)
|
||||||
|
==
|
||||||
::
|
::
|
||||||
[%x %shallow-children @ @ *]
|
[%x %graph @ @ *]
|
||||||
=/ =ship (slav %p i.t.t.path)
|
=/ =ship (slav %p i.t.t.path)
|
||||||
=/ =term i.t.t.t.path
|
=/ =term i.t.t.t.path
|
||||||
=/ =index:store
|
=/ marked-graph=(unit marked-graph:store)
|
||||||
(turn t.t.t.t.path (cury slav %ud))
|
(~(get by graphs) [ship term])
|
||||||
=/ children
|
?~ marked-graph [~ ~]
|
||||||
(get-node-children ship term index)
|
=* graph p.u.marked-graph
|
||||||
?~ children [~ ~]
|
=* mark q.u.marked-graph
|
||||||
:- ~ :- ~ :- %graph-update-2
|
?+ t.t.t.t.path (on-peek:def path)
|
||||||
!> ^- update:store
|
~
|
||||||
:+ now.bowl %add-nodes
|
:- ~ :- ~ :- %graph-update-2
|
||||||
:- [ship term]
|
!>(`update:store`[now.bowl [%add-graph [ship term] graph mark %.y]])
|
||||||
%- ~(gas by *(map index:store node:store))
|
::
|
||||||
%+ turn (tap:orm u.children)
|
[%mark ~]
|
||||||
|= [=atom =node:store]
|
``noun+!>(`(unit ^mark)`mark)
|
||||||
^- [index:store node:store]
|
::
|
||||||
:- (snoc index atom)
|
[%subset ?(%lone %kith) @ @ ~]
|
||||||
node(children [%empty ~])
|
=/ start=(unit atom) (rush i.t.t.t.t.t.t.path dem:ag)
|
||||||
::
|
=/ end=(unit atom) (rush i.t.t.t.t.t.t.t.path dem:ag)
|
||||||
[%x ?(%newest %oldest) @ @ @ *]
|
|
||||||
=/ newest ?=(%newest i.t.path)
|
|
||||||
=/ =ship (slav %p i.t.t.path)
|
|
||||||
=/ =term i.t.t.t.path
|
|
||||||
=/ count=@ud
|
|
||||||
(slav %ud i.t.t.t.t.path)
|
|
||||||
=/ =index:store
|
|
||||||
(turn t.t.t.t.t.path (cury slav %ud))
|
|
||||||
=/ children
|
|
||||||
(get-node-children ship term index)
|
|
||||||
?~ children [~ ~]
|
|
||||||
:- ~ :- ~ :- %graph-update-2
|
|
||||||
!> ^- update:store
|
|
||||||
:- now.bowl
|
|
||||||
:+ %add-nodes
|
|
||||||
[ship term]
|
|
||||||
%- ~(gas by *(map index:store node:store))
|
|
||||||
%+ turn
|
|
||||||
%+ scag count
|
|
||||||
?: newest
|
|
||||||
(tap:orm u.children)
|
|
||||||
(bap:orm u.children)
|
|
||||||
|= [=atom =node:store]
|
|
||||||
^- [index:store node:store]
|
|
||||||
[(snoc index atom) node]
|
|
||||||
::
|
|
||||||
[%x %node-children-subset @ @ @ @ @ *]
|
|
||||||
=/ =ship (slav %p i.t.t.path)
|
|
||||||
=/ =term i.t.t.t.path
|
|
||||||
=/ start=(unit atom) (rush i.t.t.t.t.path dem:ag)
|
|
||||||
=/ end=(unit atom) (rush i.t.t.t.t.t.path dem:ag)
|
|
||||||
=/ =index:store
|
|
||||||
(turn t.t.t.t.t.t.path |=(=cord (slav %ud cord)))
|
|
||||||
=/ node=(unit node:store) (get-node ship term index)
|
|
||||||
?~ node [~ ~]
|
|
||||||
?- -.children.u.node
|
|
||||||
%empty [~ ~]
|
|
||||||
%graph
|
|
||||||
:- ~ :- ~ :- %graph-update-2
|
:- ~ :- ~ :- %graph-update-2
|
||||||
!> ^- update:store
|
!> ^- update:store
|
||||||
:- now.bowl
|
:^ now.bowl %add-nodes [ship term]
|
||||||
:+ %add-nodes
|
|
||||||
[ship term]
|
|
||||||
%- ~(gas by *(map index:store node:store))
|
%- ~(gas by *(map index:store node:store))
|
||||||
%+ turn (tap:orm `graph:store`(lot:orm p.children.u.node end start))
|
%+ turn (tap:orm (lot:orm graph start end))
|
||||||
|= [=atom =node:store]
|
|= [=atom =node:store]
|
||||||
^- [index:store node:store]
|
^- [index:store node:store]
|
||||||
[(snoc index atom) node]
|
:- atom^~
|
||||||
==
|
?: ?=(%kith i.t.t.t.t.t.path)
|
||||||
::
|
node
|
||||||
[%x %deep-nodes-older-than @ @ @ @ ~]
|
node(children [%empty ~])
|
||||||
=/ =ship (slav %p i.t.t.path)
|
|
||||||
=/ =term i.t.t.t.path
|
|
||||||
=/ count=(unit atom) (rush i.t.t.t.t.path dem:ag)
|
|
||||||
=/ start=(unit atom) (rush i.t.t.t.t.t.path dem:ag)
|
|
||||||
?: ?=(~ count)
|
|
||||||
[~ ~]
|
|
||||||
=/ result=(unit marked-graph:store)
|
|
||||||
(~(get by graphs) [ship term])
|
|
||||||
?~ result
|
|
||||||
[~ ~]
|
|
||||||
:- ~ :- ~ :- %graph-update-2
|
|
||||||
!> ^- update:store
|
|
||||||
:- now.bowl
|
|
||||||
:+ %add-nodes
|
|
||||||
[ship term]
|
|
||||||
=* a u.count
|
|
||||||
=/ b=(list (pair atom node:store))
|
|
||||||
(tab:orm p.u.result start u.count)
|
|
||||||
=| c=index:store
|
|
||||||
=| d=(map index:store node:store)
|
|
||||||
=| e=@ud
|
|
||||||
=- d
|
|
||||||
|- ^- [e=@ud d=(map index:store node:store)]
|
|
||||||
?: ?|(?=(~ b) =(e a))
|
|
||||||
[e d]
|
|
||||||
=* atom p.i.b
|
|
||||||
=* node q.i.b
|
|
||||||
=. c (snoc c atom)
|
|
||||||
?- -.children.node
|
|
||||||
%empty
|
|
||||||
$(b t.b, e +(e), d (~(put by d) c node), c (snip c))
|
|
||||||
::
|
::
|
||||||
%graph
|
[%node *]
|
||||||
=/ f $(b (tab:orm p.children.node ~ (sub a e)))
|
|^
|
||||||
?: =(e.f a) f
|
=* pax t.t.t.t.t.path
|
||||||
%_ $
|
?+ pax (on-peek:def path)
|
||||||
b t.b
|
[%exists ^]
|
||||||
e +(e.f)
|
=/ =index:store
|
||||||
d (~(put by d.f) c node(children [%empty ~]))
|
(turn t.pax (cury slav %ud))
|
||||||
c (snip c)
|
=/ node (get-node graph index)
|
||||||
==
|
``noun+!>(`?`?=(^ node))
|
||||||
==
|
::
|
||||||
::
|
[%index ?(%lone %kith) ^]
|
||||||
[%x %firstborn @ @ @ *]
|
=/ =index:store
|
||||||
|^
|
(turn t.t.pax (cury slav %ud))
|
||||||
=/ =ship (slav %p i.t.t.path)
|
=/ node (get-node graph index)
|
||||||
=/ =term i.t.t.t.path
|
?~ node [~ ~]
|
||||||
=/ =index:store
|
|
||||||
(turn t.t.t.t.path (cury slav %ud))
|
|
||||||
?> ?=(^ index)
|
|
||||||
=/ result=(unit marked-graph:store)
|
|
||||||
(~(get by graphs) [ship term])
|
|
||||||
?~ result
|
|
||||||
[~ ~]
|
|
||||||
%- (bond |.(`(unit (unit cage))`[~ ~]))
|
|
||||||
%+ biff
|
|
||||||
(collect-parents p.u.result index ship term)
|
|
||||||
(corl some collect-firstborn)
|
|
||||||
::
|
|
||||||
++ collect-parents
|
|
||||||
|= [=graph:store =index:store =ship =term]
|
|
||||||
^- %- unit
|
|
||||||
[node:store index:store (map index:store node:store) ^ship ^term]
|
|
||||||
=| =(map index:store node:store)
|
|
||||||
=| =node:store
|
|
||||||
=| ind=index:store
|
|
||||||
=/ len (lent index)
|
|
||||||
|-
|
|
||||||
?: (gte (lent ind) len)
|
|
||||||
`[node ind map ship term]
|
|
||||||
?> ?=(^ index)
|
|
||||||
=* atom i.index
|
|
||||||
?. (has:orm graph atom)
|
|
||||||
~
|
|
||||||
=: node (got:orm graph atom)
|
|
||||||
ind (snoc ind atom)
|
|
||||||
==
|
|
||||||
?: ?=(%empty -.children.node)
|
|
||||||
?. (gte (lent ind) len)
|
|
||||||
~
|
|
||||||
:- ~
|
|
||||||
:* node ind
|
|
||||||
(~(put by map) ind node)
|
|
||||||
ship term
|
|
||||||
==
|
|
||||||
%_ $
|
|
||||||
index t.index
|
|
||||||
graph p.children.node
|
|
||||||
map (~(put by map) ind node(children empty+~))
|
|
||||||
==
|
|
||||||
::
|
|
||||||
++ collect-firstborn
|
|
||||||
|= [=node:store =index:store mp=(map index:store node:store) =ship =term]
|
|
||||||
^- (unit (unit cage))
|
|
||||||
?: ?=(%empty -.children.node)
|
|
||||||
:- ~ :- ~ :- %graph-update-2
|
:- ~ :- ~ :- %graph-update-2
|
||||||
!> ^- update:store
|
!> ^- update:store
|
||||||
[now.bowl [%add-nodes [ship term] mp]]
|
:^ now.bowl %add-nodes [ship term]
|
||||||
=/ item=[k=atom v=node:store]
|
%- ~(gas by *(map index:store node:store))
|
||||||
(need (ram:orm p.children.node))
|
:_ ~ :- index
|
||||||
=. index (snoc index k.item)
|
?: ?=(%kith i.t.pax) u.node
|
||||||
$(mp (~(put by mp) index v.item(children empty+~)), node v.item)
|
u.node(children [%empty ~])
|
||||||
--
|
::
|
||||||
::
|
[%children ?(%lone %kith) @ @ *]
|
||||||
[%x %update-log-subset @ @ @ @ ~]
|
=/ start=(unit atom) (rush i.t.t.path dem:ag)
|
||||||
=/ =ship (slav %p i.t.t.path)
|
=/ end=(unit atom) (rush i.t.t.t.path dem:ag)
|
||||||
=/ =term i.t.t.t.path
|
=/ =index:store
|
||||||
=/ start=(unit time) (slaw %da i.t.t.t.t.path)
|
(turn t.t.t.t.pax (cury slav %ud))
|
||||||
=/ end=(unit time) (slaw %da i.t.t.t.t.t.path)
|
=/ node (get-node graph index)
|
||||||
=/ update-log=(unit update-log:store) (~(get by update-logs) [ship term])
|
?: ?& ?=(~ node)
|
||||||
?~ update-log [~ ~]
|
?=(^ index)
|
||||||
:: orm-log is ordered backwards, so swap start and end
|
==
|
||||||
``noun+!>(`update-log:store`(lot:orm-log u.update-log end start))
|
[~ ~]
|
||||||
::
|
=/ children=graph:store
|
||||||
[%x %update-log @ @ ~]
|
?~ node
|
||||||
=/ =ship (slav %p i.t.t.path)
|
graph
|
||||||
=/ =term i.t.t.t.path
|
?: ?=(%empty -.children.u.node)
|
||||||
=/ update-log=(unit update-log:store) (~(get by update-logs) [ship term])
|
~
|
||||||
?~ update-log [~ ~]
|
p.children.u.node
|
||||||
``noun+!>(`update-log:store`u.update-log)
|
:- ~ :- ~ :- %graph-update-2
|
||||||
::
|
!> ^- update:store
|
||||||
[%x %peek-update-log @ @ ~]
|
:^ now.bowl %add-nodes [ship term]
|
||||||
=/ =ship (slav %p i.t.t.path)
|
%- ~(gas by *(map index:store node:store))
|
||||||
=/ =term i.t.t.t.path
|
%+ turn (tap:orm (lot:orm children end start))
|
||||||
=/ m-update-log=(unit update-log:store)
|
|= [=atom =node:store]
|
||||||
(~(get by update-logs) [ship term])
|
^- [index:store node:store]
|
||||||
:- ~ :- ~ :- %noun
|
:- (snoc index atom)
|
||||||
!> ^- (unit time)
|
?: ?=(%kith i.t.pax) node
|
||||||
%+ biff m-update-log
|
node(children [%empty ~])
|
||||||
|= =update-log:store
|
::
|
||||||
=/ result=(unit [=time =update:store])
|
[%siblings ?(%older %newer %oldest %newest) ?(%lone %kith) @ *]
|
||||||
(pry:orm-log:store update-log)
|
=/ count (slav %ud i.t.t.t.pax)
|
||||||
(bind result head)
|
=/ =index:store
|
||||||
==
|
(turn t.t.t.t.pax (cury slav %ud))
|
||||||
::
|
=/ parent=index:store (snip index)
|
||||||
++ get-node-children
|
=/ node
|
||||||
|= [=ship =term =index:store]
|
(get-node graph ?:(?=(?(%oldest %newest) i.t.pax) index parent))
|
||||||
^- (unit graph:store)
|
=/ children=graph:store
|
||||||
?: ?=(~ index)
|
?~ node
|
||||||
=/ graph
|
graph
|
||||||
(~(get by graphs) [ship term])
|
?: ?=(%empty -.children.u.node)
|
||||||
?~ graph ~
|
~
|
||||||
`p.u.graph
|
p.children.u.node
|
||||||
=/ node
|
:- ~ :- ~ :- %graph-update-2
|
||||||
(get-node ship term index)
|
!> ^- update:store
|
||||||
?~ node ~
|
:^ now.bowl %add-nodes [ship term]
|
||||||
?: ?=(%empty -.children.u.node)
|
%- ~(gas by *(map index:store node:store))
|
||||||
~
|
%+ turn
|
||||||
`p.children.u.node
|
?- i.t.pax
|
||||||
::
|
%oldest (scag count (bap:orm children))
|
||||||
++ get-node
|
%older (tab:orm children `(rear index) count)
|
||||||
|= [=ship =term =index:store]
|
%newest (scag count (tap:orm children))
|
||||||
^- (unit node:store)
|
::
|
||||||
=/ parent-graph=(unit marked-graph:store)
|
%newer
|
||||||
(~(get by graphs) [ship term])
|
%+ slag (safe-sub (lent -) count)
|
||||||
?~ parent-graph ~
|
(tap:orm (lot:orm children ~ `(rear index)))
|
||||||
=/ node=(unit node:store) ~
|
==
|
||||||
=/ =graph:store p.u.parent-graph
|
|= [=atom =node:store]
|
||||||
|-
|
^- [index:store node:store]
|
||||||
?~ index
|
:- %- snoc
|
||||||
node
|
:_ atom
|
||||||
?~ t.index
|
?:(?=(?(%newest %oldest) i.t.pax) index parent)
|
||||||
(get:orm graph i.index)
|
?: ?=(%kith i.t.t.pax) node
|
||||||
=. node (get:orm graph i.index)
|
node(children [%empty ~])
|
||||||
?~ node ~
|
::
|
||||||
?- -.children.u.node
|
[%firstborn ^]
|
||||||
%empty ~
|
|^
|
||||||
%graph $(graph p.children.u.node, index t.index)
|
=/ =index:store
|
||||||
|
(turn t.pax (cury slav %ud))
|
||||||
|
%- (bond |.(`(unit (unit cage))`[~ ~]))
|
||||||
|
%+ biff
|
||||||
|
(collect-parents graph index)
|
||||||
|
(corl some collect-firstborn)
|
||||||
|
::
|
||||||
|
++ collect-parents
|
||||||
|
|= [=graph:store =index:store]
|
||||||
|
^- (unit [node:store index:store (map index:store node:store)])
|
||||||
|
=| =(map index:store node:store)
|
||||||
|
=| =node:store
|
||||||
|
=| ind=index:store
|
||||||
|
=/ len (lent index)
|
||||||
|
|-
|
||||||
|
?: (gte (lent ind) len)
|
||||||
|
`[node ind map]
|
||||||
|
?> ?=(^ index)
|
||||||
|
=* atom i.index
|
||||||
|
?. (has:orm graph atom)
|
||||||
|
~
|
||||||
|
=: node (got:orm graph atom)
|
||||||
|
ind (snoc ind atom)
|
||||||
|
==
|
||||||
|
?: ?=(%empty -.children.node)
|
||||||
|
?. (gte (lent ind) len)
|
||||||
|
~
|
||||||
|
`[node ind (~(put by map) ind node)]
|
||||||
|
%_ $
|
||||||
|
index t.index
|
||||||
|
graph p.children.node
|
||||||
|
map (~(put by map) ind node(children empty+~))
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ collect-firstborn
|
||||||
|
|= [=node:store =index:store =(map index:store node:store)]
|
||||||
|
^- (unit (unit cage))
|
||||||
|
?: ?=(%empty -.children.node)
|
||||||
|
:- ~ :- ~ :- %graph-update-2
|
||||||
|
!>(`update:store`[now.bowl [%add-nodes [ship term] map]])
|
||||||
|
=/ item=[k=atom v=node:store]
|
||||||
|
(need (ram:orm p.children.node))
|
||||||
|
=. index (snoc index k.item)
|
||||||
|
$(map (~(put by map) index v.item(children empty+~)), node v.item)
|
||||||
|
--
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ get-node
|
||||||
|
|= [=graph:store =index:store]
|
||||||
|
^- (unit node:store)
|
||||||
|
=| node=(unit node:store)
|
||||||
|
|-
|
||||||
|
?~ index node
|
||||||
|
?~ t.index (get:orm graph i.index)
|
||||||
|
=. node (get:orm graph i.index)
|
||||||
|
?~ node ~
|
||||||
|
?: ?=(%empty -.children.u.node)
|
||||||
|
~
|
||||||
|
$(graph p.children.u.node, index t.index)
|
||||||
|
::
|
||||||
|
++ safe-sub
|
||||||
|
|= [a=@ b=@]
|
||||||
|
^- @
|
||||||
|
?:((gte b a) 0 (sub a b))
|
||||||
|
--
|
||||||
|
::
|
||||||
|
[%depth-first @ @ ~]
|
||||||
|
=/ count=(unit atom) (rush i.t.t.t.t.path dem:ag)
|
||||||
|
=/ start=(unit atom) (rush i.t.t.t.t.t.path dem:ag)
|
||||||
|
?: ?=(~ count)
|
||||||
|
[~ ~]
|
||||||
|
:- ~ :- ~ :- %graph-update-2
|
||||||
|
!> ^- update:store
|
||||||
|
:^ now.bowl %add-nodes [ship term]
|
||||||
|
=* a u.count
|
||||||
|
=/ b=(list (pair atom node:store))
|
||||||
|
(tab:orm graph start u.count)
|
||||||
|
=| c=index:store
|
||||||
|
=| d=(map index:store node:store)
|
||||||
|
=| e=@ud
|
||||||
|
=- d
|
||||||
|
|- ^- [e=@ud d=(map index:store node:store)]
|
||||||
|
?: ?|(?=(~ b) =(e a))
|
||||||
|
[e d]
|
||||||
|
=* atom p.i.b
|
||||||
|
=* node q.i.b
|
||||||
|
=. c (snoc c atom)
|
||||||
|
?- -.children.node
|
||||||
|
%empty
|
||||||
|
$(b t.b, e +(e), d (~(put by d) c node), c (snip c))
|
||||||
|
::
|
||||||
|
%graph
|
||||||
|
=/ f $(b (tab:orm p.children.node ~ (sub a e)))
|
||||||
|
?: =(e.f a) f
|
||||||
|
%_ $
|
||||||
|
b t.b
|
||||||
|
e +(e.f)
|
||||||
|
d (~(put by d.f) c node(children [%empty ~]))
|
||||||
|
c (snip c)
|
||||||
|
==
|
||||||
|
==
|
||||||
==
|
==
|
||||||
--
|
|
||||||
::
|
|
||||||
++ on-arvo
|
|
||||||
|= [=wire =sign-arvo]
|
|
||||||
^- (quip card _this)
|
|
||||||
?+ wire (on-arvo:def wire sign-arvo)
|
|
||||||
::
|
|
||||||
:: old wire, do nothing
|
|
||||||
[%graph *] [~ this]
|
|
||||||
[%validator @ ~] [~ this]
|
|
||||||
[%try-rejoin @ *] [~ this]
|
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
|
++ on-arvo on-arvo:def
|
||||||
++ on-agent on-agent:def
|
++ on-agent on-agent:def
|
||||||
++ on-leave on-leave:def
|
++ on-leave on-leave:def
|
||||||
++ on-fail on-fail:def
|
++ on-fail on-fail:def
|
||||||
|
@ -289,7 +289,7 @@
|
|||||||
::
|
::
|
||||||
++ md-fact
|
++ md-fact
|
||||||
|= [=mark =vase]
|
|= [=mark =vase]
|
||||||
?. ?=(%metadata-update-1 mark) jn-core
|
?. ?=(%metadata-update-2 mark) jn-core
|
||||||
=+ !<(=update:metadata vase)
|
=+ !<(=update:metadata vase)
|
||||||
?. ?=(%initial-group -.update) jn-core
|
?. ?=(%initial-group -.update) jn-core
|
||||||
?. =(group.update rid) jn-core
|
?. =(group.update rid) jn-core
|
||||||
|
@ -285,7 +285,7 @@
|
|||||||
^- $-(indexed-post:graph-store (unit notif-kind:hook))
|
^- $-(indexed-post:graph-store (unit notif-kind:hook))
|
||||||
=+ %^ scry [our now]:bowl
|
=+ %^ scry [our now]:bowl
|
||||||
,mark=(unit mark)
|
,mark=(unit mark)
|
||||||
/gx/graph-store/graph-mark/(scot %p entity.rid)/[name.rid]/noun
|
/gx/graph-store/graph/(scot %p entity.rid)/[name.rid]/mark/noun
|
||||||
?~ mark
|
?~ mark
|
||||||
|=(=indexed-post:graph-store ~)
|
|=(=indexed-post:graph-store ~)
|
||||||
(scry-notif-conversion [our now]:bowl q.byk.bowl u.mark)
|
(scry-notif-conversion [our now]:bowl q.byk.bowl u.mark)
|
||||||
|
@ -113,7 +113,7 @@
|
|||||||
(group-update !<(update:group-store q.cage.sign))
|
(group-update !<(update:group-store q.cage.sign))
|
||||||
[cards this]
|
[cards this]
|
||||||
::
|
::
|
||||||
%metadata-update-1
|
%metadata-update-2
|
||||||
=^ cards state
|
=^ cards state
|
||||||
(metadata-update !<(update:metadata q.cage.sign))
|
(metadata-update !<(update:metadata q.cage.sign))
|
||||||
[cards this]
|
[cards this]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln
|
/+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln
|
||||||
|%
|
|%
|
||||||
+$ state
|
+$ state
|
||||||
$: %13
|
$: %14
|
||||||
drum=state:drum
|
drum=state:drum
|
||||||
helm=state:helm
|
helm=state:helm
|
||||||
kiln=state:kiln
|
kiln=state:kiln
|
||||||
@ -10,12 +10,13 @@
|
|||||||
+$ any-state
|
+$ any-state
|
||||||
$% state
|
$% state
|
||||||
[ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)]
|
[ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)]
|
||||||
[%7 drum=state:drum helm=state:helm kiln=state:kiln]
|
[%7 drum=state:drum helm=state:helm kiln=state-1:kiln]
|
||||||
[%8 drum=state:drum helm=state:helm kiln=state:kiln]
|
[%8 drum=state:drum helm=state:helm kiln=state-1:kiln]
|
||||||
[%9 drum=state:drum helm=state:helm kiln=state:kiln]
|
[%9 drum=state:drum helm=state:helm kiln=state-1:kiln]
|
||||||
[%10 drum=state:drum helm=state:helm kiln=state:kiln]
|
[%10 drum=state:drum helm=state:helm kiln=state-1:kiln]
|
||||||
[%11 drum=state:drum helm=state:helm kiln=state:kiln]
|
[%11 drum=state:drum helm=state:helm kiln=state-1:kiln]
|
||||||
[%12 drum=state:drum helm=state:helm kiln=state:kiln]
|
[%12 drum=state:drum helm=state:helm kiln=state-1:kiln]
|
||||||
|
[%13 drum=state:drum helm=state:helm kiln=state-1:kiln]
|
||||||
==
|
==
|
||||||
+$ any-state-tuple
|
+$ any-state-tuple
|
||||||
$: drum=any-state:drum
|
$: drum=any-state:drum
|
||||||
|
@ -24,6 +24,6 @@
|
|||||||
<div id="portal-root"></div>
|
<div id="portal-root"></div>
|
||||||
<script src="/~landscape/js/channel.js"></script>
|
<script src="/~landscape/js/channel.js"></script>
|
||||||
<script src="/~landscape/js/session.js"></script>
|
<script src="/~landscape/js/session.js"></script>
|
||||||
<script src="/~landscape/js/bundle/index.8074ae0006fba19803f5.js"></script>
|
<script src="/~landscape/js/bundle/index.25a7d11c5e34f8db1f8c.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
update:metadata
|
update:metadata
|
||||||
%metadata-update
|
%metadata-update
|
||||||
%metadata-push-hook
|
%metadata-push-hook
|
||||||
1 1
|
2 2
|
||||||
%.n
|
%.n
|
||||||
==
|
==
|
||||||
+$ state-zero
|
+$ state-zero
|
||||||
@ -180,7 +180,7 @@
|
|||||||
%kick [watch-store^~ state]
|
%kick [watch-store^~ state]
|
||||||
::
|
::
|
||||||
%fact
|
%fact
|
||||||
?> ?=(%metadata-update-1 p.cage.sign)
|
?> ?=(%metadata-update-2 p.cage.sign)
|
||||||
=+ !<(=update:metadata q.cage.sign)
|
=+ !<(=update:metadata q.cage.sign)
|
||||||
?. ?=(%initial-group -.update) `state
|
?. ?=(%initial-group -.update) `state
|
||||||
`state(previews (~(del by previews) group.update))
|
`state(previews (~(del by previews) group.update))
|
||||||
@ -325,7 +325,7 @@
|
|||||||
%+ turn ~(tap by associations)
|
%+ turn ~(tap by associations)
|
||||||
|= [=md-resource:metadata =association:metadata]
|
|= [=md-resource:metadata =association:metadata]
|
||||||
%+ poke-our:pass:io %metadata-store
|
%+ poke-our:pass:io %metadata-store
|
||||||
:- %metadata-update-1
|
:- %metadata-update-2
|
||||||
!> ^- update:metadata
|
!> ^- update:metadata
|
||||||
[%remove resource md-resource]
|
[%remove resource md-resource]
|
||||||
::
|
::
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
update:store
|
update:store
|
||||||
%metadata-update
|
%metadata-update
|
||||||
%metadata-pull-hook
|
%metadata-pull-hook
|
||||||
1 1
|
2 2
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
+$ agent (push-hook:push-hook config)
|
+$ agent (push-hook:push-hook config)
|
||||||
@ -94,7 +94,7 @@
|
|||||||
^- (quip card (unit vase))
|
^- (quip card (unit vase))
|
||||||
=/ =update:store !<(update:store vas)
|
=/ =update:store !<(update:store vas)
|
||||||
:- ~
|
:- ~
|
||||||
?. ?=(?(%add %remove) -.update)
|
?. ?=(?(%add %remove %edit) -.update)
|
||||||
~
|
~
|
||||||
=/ role=(unit (unit role-tag))
|
=/ role=(unit (unit role-tag))
|
||||||
(role-for-ship:grp group.update src.bowl)
|
(role-for-ship:grp group.update src.bowl)
|
||||||
|
@ -153,18 +153,145 @@
|
|||||||
++ on-poke
|
++ on-poke
|
||||||
|= [=mark =vase]
|
|= [=mark =vase]
|
||||||
^- (quip card _this)
|
^- (quip card _this)
|
||||||
?> (team:title our.bowl src.bowl)
|
?> (team:title [our src]:bowl)
|
||||||
|
|^
|
||||||
=^ cards state
|
=^ cards state
|
||||||
?+ mark (on-poke:def mark vase)
|
?+ mark (on-poke:def mark vase)
|
||||||
?(%metadata-action %metadata-update-1)
|
?(%metadata-action %metadata-update-2)
|
||||||
(poke-metadata-update:mc !<(update:store vase))
|
(poke-metadata-update !<(update:store vase))
|
||||||
::
|
::
|
||||||
%import
|
%import
|
||||||
(poke-import:mc q.vase)
|
(poke-import q.vase)
|
||||||
::
|
::
|
||||||
%noun ~& +.state `state
|
%noun ~& +.state `state
|
||||||
==
|
==
|
||||||
[cards this]
|
[cards this]
|
||||||
|
::
|
||||||
|
++ poke-metadata-update
|
||||||
|
|= upd=update:store
|
||||||
|
^- (quip card _state)
|
||||||
|
|^
|
||||||
|
?+ -.upd ~|(%bad-poke !!)
|
||||||
|
%add (handle-add +.upd)
|
||||||
|
%remove (handle-remove +.upd)
|
||||||
|
%edit (handle-edit +.upd)
|
||||||
|
%initial-group (handle-initial-group +.upd)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ handle-add
|
||||||
|
|= [group=resource =md-resource:store =metadatum:store]
|
||||||
|
^- (quip card _state)
|
||||||
|
:- %- send-diff:mc
|
||||||
|
[%add group md-resource metadatum]
|
||||||
|
%= state
|
||||||
|
associations
|
||||||
|
(~(put by associations) md-resource [group metadatum])
|
||||||
|
::
|
||||||
|
app-indices
|
||||||
|
%+ ~(put ju app-indices)
|
||||||
|
app-name.md-resource
|
||||||
|
[group resource.md-resource]
|
||||||
|
::
|
||||||
|
resource-indices
|
||||||
|
(~(put by resource-indices) md-resource group)
|
||||||
|
::
|
||||||
|
group-indices
|
||||||
|
(~(put ju group-indices) group md-resource)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ handle-edit
|
||||||
|
|= [group=resource =md-resource:store =edit-field:store]
|
||||||
|
^- (quip card _state)
|
||||||
|
=/ [new-group=resource =metadatum:store]
|
||||||
|
~| %no-assoc-for-edit
|
||||||
|
(~(got by associations) md-resource)
|
||||||
|
~| %cant-reassign-groups
|
||||||
|
?> =(new-group group)
|
||||||
|
=. metadatum
|
||||||
|
?- -.edit-field
|
||||||
|
%title metadatum(title title.edit-field)
|
||||||
|
%description metadatum(description description.edit-field)
|
||||||
|
%color metadatum(color color.edit-field)
|
||||||
|
%picture metadatum(picture url.edit-field)
|
||||||
|
%hidden metadatum(hidden hidden.edit-field)
|
||||||
|
%preview metadatum(preview preview.edit-field)
|
||||||
|
%vip metadatum(vip vip.edit-field)
|
||||||
|
==
|
||||||
|
:- (send-diff:mc %add group md-resource metadatum)
|
||||||
|
%_ state
|
||||||
|
associations (~(put by associations) md-resource group metadatum)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ handle-remove
|
||||||
|
|= [group=resource =md-resource:store]
|
||||||
|
^- (quip card _state)
|
||||||
|
:- (send-diff:mc [%remove group md-resource])
|
||||||
|
%= state
|
||||||
|
associations
|
||||||
|
(~(del by associations) md-resource)
|
||||||
|
::
|
||||||
|
app-indices
|
||||||
|
%+ ~(del ju app-indices)
|
||||||
|
app-name.md-resource
|
||||||
|
[group resource.md-resource]
|
||||||
|
::
|
||||||
|
resource-indices
|
||||||
|
(~(del by resource-indices) md-resource)
|
||||||
|
::
|
||||||
|
group-indices
|
||||||
|
(~(del ju group-indices) group md-resource)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ handle-initial-group
|
||||||
|
|= [group=resource =associations:store]
|
||||||
|
=/ assocs=(list [=md-resource:store grp=resource =metadatum:store])
|
||||||
|
~(tap by associations)
|
||||||
|
:- (send-diff:mc %initial-group group associations)
|
||||||
|
|-
|
||||||
|
?~ assocs
|
||||||
|
state
|
||||||
|
=, assocs
|
||||||
|
?> =(group grp.i)
|
||||||
|
=^ cards state
|
||||||
|
(handle-add group [md-resource metadatum]:i)
|
||||||
|
$(assocs t)
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ poke-import
|
||||||
|
|= arc=*
|
||||||
|
^- (quip card _state)
|
||||||
|
|^
|
||||||
|
=^ cards state
|
||||||
|
(on-load:mc !>([%9 (remake-metadata ;;(tree-metadata +.arc))]))
|
||||||
|
:_ state
|
||||||
|
%+ weld cards
|
||||||
|
%+ turn ~(tap in ~(key by group-indices))
|
||||||
|
|= rid=resource
|
||||||
|
%- poke-our
|
||||||
|
?: =(entity.rid our.bowl)
|
||||||
|
:- %metadata-push-hook
|
||||||
|
push-hook-action+!>([%add rid])
|
||||||
|
:- %metadata-pull-hook
|
||||||
|
pull-hook-action+!>([%add [entity .]:rid])
|
||||||
|
::
|
||||||
|
++ poke-our
|
||||||
|
|= [app=term =cage]
|
||||||
|
^- card
|
||||||
|
[%pass / %agent [our.bowl app] %poke cage]
|
||||||
|
::
|
||||||
|
+$ tree-metadata
|
||||||
|
$: associations=(tree [md-resource:store [resource metadatum:store]])
|
||||||
|
~
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ remake-metadata
|
||||||
|
|= tm=tree-metadata
|
||||||
|
^- base-state-3
|
||||||
|
:* (remake-map associations.tm)
|
||||||
|
~
|
||||||
|
==
|
||||||
|
--
|
||||||
|
--
|
||||||
::
|
::
|
||||||
++ on-watch
|
++ on-watch
|
||||||
|= =path
|
|= =path
|
||||||
@ -174,7 +301,7 @@
|
|||||||
=/ cards=(list card)
|
=/ cards=(list card)
|
||||||
?+ path (on-watch:def path)
|
?+ path (on-watch:def path)
|
||||||
[%all ~]
|
[%all ~]
|
||||||
(give %metadata-update-1 !>([%associations associations]))
|
(give %metadata-update-2 !>([%associations associations]))
|
||||||
::
|
::
|
||||||
[%updates ~]
|
[%updates ~]
|
||||||
~
|
~
|
||||||
@ -182,7 +309,7 @@
|
|||||||
[%app-name @ ~]
|
[%app-name @ ~]
|
||||||
=/ =app-name:store i.t.path
|
=/ =app-name:store i.t.path
|
||||||
=/ app-indices (metadata-for-app:mc app-name)
|
=/ app-indices (metadata-for-app:mc app-name)
|
||||||
(give %metadata-update-1 !>([%associations app-indices]))
|
(give %metadata-update-2 !>([%associations app-indices]))
|
||||||
==
|
==
|
||||||
[cards this]
|
[cards this]
|
||||||
::
|
::
|
||||||
@ -418,109 +545,6 @@
|
|||||||
ship+path.md-resource
|
ship+path.md-resource
|
||||||
[[path [%graph new-path]] m(module app)]
|
[[path [%graph new-path]] m(module app)]
|
||||||
--
|
--
|
||||||
::
|
|
||||||
:: TODO: refactor into a |^ inside the agent core
|
|
||||||
++ poke-metadata-update
|
|
||||||
|= upd=update:store
|
|
||||||
^- (quip card _state)
|
|
||||||
?> (team:title [our src]:bowl)
|
|
||||||
?+ -.upd !!
|
|
||||||
%add (handle-add +.upd)
|
|
||||||
%remove (handle-remove +.upd)
|
|
||||||
%initial-group (handle-initial-group +.upd)
|
|
||||||
==
|
|
||||||
::
|
|
||||||
:: TODO: refactor into a |^ inside the agent core
|
|
||||||
++ poke-import
|
|
||||||
|= arc=*
|
|
||||||
^- (quip card _state)
|
|
||||||
|^
|
|
||||||
=^ cards state
|
|
||||||
(on-load !>([%9 (remake-metadata ;;(tree-metadata +.arc))]))
|
|
||||||
:_ state
|
|
||||||
%+ weld cards
|
|
||||||
%+ turn ~(tap in ~(key by group-indices))
|
|
||||||
|= rid=resource
|
|
||||||
%- poke-our
|
|
||||||
?: =(entity.rid our.bowl)
|
|
||||||
:- %metadata-push-hook
|
|
||||||
push-hook-action+!>([%add rid])
|
|
||||||
:- %metadata-pull-hook
|
|
||||||
pull-hook-action+!>([%add [entity .]:rid])
|
|
||||||
::
|
|
||||||
++ poke-our
|
|
||||||
|= [app=term =cage]
|
|
||||||
^- card
|
|
||||||
[%pass / %agent [our.bowl app] %poke cage]
|
|
||||||
::
|
|
||||||
+$ tree-metadata
|
|
||||||
$: associations=(tree [md-resource:store [resource metadatum:store]])
|
|
||||||
~
|
|
||||||
==
|
|
||||||
::
|
|
||||||
++ remake-metadata
|
|
||||||
|= tm=tree-metadata
|
|
||||||
^- base-state-3
|
|
||||||
:* (remake-map associations.tm)
|
|
||||||
~
|
|
||||||
==
|
|
||||||
--
|
|
||||||
::
|
|
||||||
++ handle-add
|
|
||||||
|= [group=resource =md-resource:store =metadatum:store]
|
|
||||||
^- (quip card _state)
|
|
||||||
:- %- send-diff
|
|
||||||
[%add group md-resource metadatum]
|
|
||||||
%= state
|
|
||||||
associations
|
|
||||||
(~(put by associations) md-resource [group metadatum])
|
|
||||||
::
|
|
||||||
app-indices
|
|
||||||
%+ ~(put ju app-indices)
|
|
||||||
app-name.md-resource
|
|
||||||
[group resource.md-resource]
|
|
||||||
::
|
|
||||||
resource-indices
|
|
||||||
(~(put by resource-indices) md-resource group)
|
|
||||||
::
|
|
||||||
group-indices
|
|
||||||
(~(put ju group-indices) group md-resource)
|
|
||||||
==
|
|
||||||
::
|
|
||||||
++ handle-remove
|
|
||||||
|= [group=resource =md-resource:store]
|
|
||||||
^- (quip card _state)
|
|
||||||
:- (send-diff [%remove group md-resource])
|
|
||||||
%= state
|
|
||||||
associations
|
|
||||||
(~(del by associations) md-resource)
|
|
||||||
::
|
|
||||||
app-indices
|
|
||||||
%+ ~(del ju app-indices)
|
|
||||||
app-name.md-resource
|
|
||||||
[group resource.md-resource]
|
|
||||||
::
|
|
||||||
resource-indices
|
|
||||||
(~(del by resource-indices) md-resource)
|
|
||||||
::
|
|
||||||
group-indices
|
|
||||||
(~(del ju group-indices) group md-resource)
|
|
||||||
==
|
|
||||||
::
|
|
||||||
++ handle-initial-group
|
|
||||||
|= [group=resource =associations:store]
|
|
||||||
=/ assocs=(list [=md-resource:store grp=resource =metadatum:store])
|
|
||||||
~(tap by associations)
|
|
||||||
:- (send-diff %initial-group group associations)
|
|
||||||
|-
|
|
||||||
?~ assocs
|
|
||||||
state
|
|
||||||
=, assocs
|
|
||||||
?> =(group grp.i)
|
|
||||||
=^ cards state
|
|
||||||
(handle-add group [md-resource metadatum]:i)
|
|
||||||
$(assocs t)
|
|
||||||
::
|
|
||||||
++ metadata-for-app
|
++ metadata-for-app
|
||||||
|= =app-name:store
|
|= =app-name:store
|
||||||
^- associations:store
|
^- associations:store
|
||||||
@ -556,6 +580,6 @@
|
|||||||
++ update-subscribers
|
++ update-subscribers
|
||||||
|= [pax=path =update:store]
|
|= [pax=path =update:store]
|
||||||
^- (list card)
|
^- (list card)
|
||||||
[%give %fact ~[pax] %metadata-update-1 !>(update)]~
|
[%give %fact ~[pax] %metadata-update-2 !>(update)]~
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
|
20
pkg/arvo/gen/hood/fuse-list.hoon
Normal file
20
pkg/arvo/gen/hood/fuse-list.hoon
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
:: Kiln: Fuse local desk from (optionally-)foreign sources
|
||||||
|
::
|
||||||
|
:::: /hoon/fuse/hood/gen
|
||||||
|
::
|
||||||
|
/+ *hood-kiln
|
||||||
|
/* help-text %txt /gen/hood/fuse/help/txt
|
||||||
|
=, clay
|
||||||
|
::
|
||||||
|
::::
|
||||||
|
::
|
||||||
|
=>
|
||||||
|
|%
|
||||||
|
+$ fuse-list-arg $@(~ [des=desk ~])
|
||||||
|
--
|
||||||
|
:- %say
|
||||||
|
|= [* [arg=fuse-list-arg] ~]
|
||||||
|
:- %kiln-fuse-list
|
||||||
|
?~ arg
|
||||||
|
~
|
||||||
|
`des.arg
|
@ -2,14 +2,59 @@
|
|||||||
::
|
::
|
||||||
:::: /hoon/fuse/hood/gen
|
:::: /hoon/fuse/hood/gen
|
||||||
::
|
::
|
||||||
|
/+ *hood-kiln
|
||||||
/* help-text %txt /gen/hood/fuse/help/txt
|
/* help-text %txt /gen/hood/fuse/help/txt
|
||||||
=, clay
|
=, clay
|
||||||
::
|
::
|
||||||
::::
|
::::
|
||||||
::
|
::
|
||||||
|
=>
|
||||||
|
|%
|
||||||
|
+$ fuse-arg
|
||||||
|
$: des=desk
|
||||||
|
:: specified as [germ path] instead of [path germ] so
|
||||||
|
:: users can write mate//=home= instead of [/=home= %mate]
|
||||||
|
::
|
||||||
|
res=[?([%cancel ~] [bas=path con=(list [germ path])])]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ parse-fuse-source
|
||||||
|
|= bec=beak
|
||||||
|
^- fuse-source
|
||||||
|
:: This is a slight overload of the label, but
|
||||||
|
:: it provides a nicer interface for the user so
|
||||||
|
:: we'll go with it.
|
||||||
|
::
|
||||||
|
?: ?=([%tas *] r.bec)
|
||||||
|
?: =(p.r.bec %track)
|
||||||
|
[p.bec q.bec %trak]
|
||||||
|
bec
|
||||||
|
bec
|
||||||
|
::
|
||||||
|
++ de-beak
|
||||||
|
|= pax=path
|
||||||
|
^- beak
|
||||||
|
=/ bem=beam (need (de-beam pax))
|
||||||
|
?> =(s.bem /)
|
||||||
|
-.bem
|
||||||
|
::
|
||||||
|
++ path-to-fuse-source
|
||||||
|
|= pax=path
|
||||||
|
^- fuse-source
|
||||||
|
(parse-fuse-source (de-beak pax))
|
||||||
|
--
|
||||||
:- %say
|
:- %say
|
||||||
|= [[now=@da eny=@uvJ bec=beak] [arg=[?(~ [des=desk bas=beak con=(list [beak germ]) ~])]] ~]
|
|= [* [arg=[?(~ fuse-arg)]] [overwrite=$~(| flag) ~]]
|
||||||
:- %kiln-fuse
|
:- %kiln-fuse
|
||||||
?~ arg
|
?~ arg
|
||||||
((slog (turn `wain`help-text |=(=@t leaf+(trip t)))) ~)
|
((slog (turn `wain`help-text |=(=@t leaf+(trip t)))) ~)
|
||||||
[des bas con]:arg
|
:- des.arg
|
||||||
|
?: ?=([%cancel ~] res.arg)
|
||||||
|
~
|
||||||
|
:+ overwrite
|
||||||
|
(path-to-fuse-source bas.res.arg)
|
||||||
|
%+ turn
|
||||||
|
con.res.arg
|
||||||
|
|= [g=germ pax=path]
|
||||||
|
^- [fuse-source germ]
|
||||||
|
[(path-to-fuse-source pax) g]
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
|fuse %destination-desk base-beak ~[[source-beak %some-germ] [another-beak %another-germ]]
|
|fuse %dest /=kids= mate//~nel/home= meet//~zod/kids/track
|
||||||
|
|fuse %old-desk /=kids= only-that//~nus/test=, =overwrite &
|
||||||
|
|fuse %desk-to-cancel-fuse-into %cancel
|
||||||
|
|
||||||
A fuse replaces the contents of %destination-desk with the merge of the
|
A %fuse request in clay replaces the contents of %destination-desk
|
||||||
specified beaks according to their merge strategies. This has no dependence
|
with the merge of the specified beaks according to their merge
|
||||||
on the previous state of %destination-desk so any commits/work there will
|
strategies. This has no dependence on the previous state of %dest
|
||||||
be overwritten.
|
so any commits/work there will be overwritten.
|
||||||
|
|
||||||
|
|fuse extends this concept with the idea of a tracked source. When
|
||||||
|
specifying beaks to include in your fuse, specify %track instead of
|
||||||
|
a case. This will tell |fuse to retrieve the latest version of the
|
||||||
|
source beak AND to rerun the %fuse request whenever that tracked
|
||||||
|
source changes. A fuse can have many tracked sources, or none. The
|
||||||
|
base may be tracked as well.
|
||||||
|
|
||||||
|
The overwrite flag allows you to overwrite a currently ongoing fuse.
|
||||||
|
Without this flag, attempting a fuse into a desk that you already
|
||||||
|
|fuse'd into will error.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/- sur=graph-store, pos=post
|
/- sur=graph-store, pos=post, pull-hook
|
||||||
/+ res=resource, migrate
|
/+ res=resource, migrate
|
||||||
=< [sur .]
|
=< [sur .]
|
||||||
=< [pos .]
|
=< [pos .]
|
||||||
@ -872,6 +872,10 @@
|
|||||||
^- card:agent:gall
|
^- card:agent:gall
|
||||||
=/ res-path (en-path:res rid)
|
=/ res-path (en-path:res rid)
|
||||||
=/ wire [%try-rejoin (scot %ud nack-count) res-path]
|
=/ wire [%try-rejoin (scot %ud nack-count) res-path]
|
||||||
[%pass wire %agent [entity.rid %graph-push-hook] %watch resource+res-path]
|
=/ =cage
|
||||||
|
:- %pull-hook-action
|
||||||
|
!> ^- action:pull-hook
|
||||||
|
[%add [entity .]:rid]
|
||||||
|
[%pass wire %agent [our %graph-pull-hook] %poke cage]
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
|
@ -96,22 +96,12 @@
|
|||||||
?> ?=(%add-graph -.q.update)
|
?> ?=(%add-graph -.q.update)
|
||||||
graph.q.update
|
graph.q.update
|
||||||
::
|
::
|
||||||
++ gut-younger-node-siblings
|
|
||||||
|= [res=resource =index:store]
|
|
||||||
^- (map index:store node:store)
|
|
||||||
=+ %+ scry-for ,=update:store
|
|
||||||
%+ weld
|
|
||||||
/node-siblings/younger/(scot %p entity.res)/[name.res]/all
|
|
||||||
(turn index (cury scot %ud))
|
|
||||||
?> ?=(%add-nodes -.q.update)
|
|
||||||
nodes.q.update
|
|
||||||
::
|
|
||||||
++ got-node
|
++ got-node
|
||||||
|= [res=resource =index:store]
|
|= [res=resource =index:store]
|
||||||
^- node:store
|
^- node:store
|
||||||
=+ %+ scry-for ,=update:store
|
=+ %+ scry-for ,=update:store
|
||||||
%+ weld
|
%+ weld
|
||||||
/node/(scot %p entity.res)/[name.res]
|
/graph/(scot %p entity.res)/[name.res]/node/index/kith
|
||||||
(turn index (cury scot %ud))
|
(turn index (cury scot %ud))
|
||||||
?> ?=(%add-nodes -.q.update)
|
?> ?=(%add-nodes -.q.update)
|
||||||
?> ?=(^ nodes.q.update)
|
?> ?=(^ nodes.q.update)
|
||||||
@ -122,7 +112,7 @@
|
|||||||
^- ?
|
^- ?
|
||||||
%+ scry-for ,?
|
%+ scry-for ,?
|
||||||
%+ weld
|
%+ weld
|
||||||
/node-exists/(scot %p entity.res)/[name.res]
|
/graph/(scot %p entity.res)/[name.res]/node/exists
|
||||||
(turn index (cury scot %ud))
|
(turn index (cury scot %ud))
|
||||||
::
|
::
|
||||||
++ get-update-log
|
++ get-update-log
|
||||||
@ -134,13 +124,13 @@
|
|||||||
++ peek-update-log
|
++ peek-update-log
|
||||||
|= res=resource
|
|= res=resource
|
||||||
^- (unit time)
|
^- (unit time)
|
||||||
(scry-for (unit time) /peek-update-log/(scot %p entity.res)/[name.res])
|
(scry-for (unit time) /update-log/(scot %p entity.res)/[name.res]/latest)
|
||||||
::
|
::
|
||||||
++ get-update-log-subset
|
++ get-update-log-subset
|
||||||
|= [res=resource start=@da]
|
|= [res=resource start=@da]
|
||||||
^- update-log:store
|
^- update-log:store
|
||||||
%+ scry-for update-log:store
|
%+ scry-for update-log:store
|
||||||
/update-log-subset/(scot %p entity.res)/[name.res]/(scot %da start)/'~'
|
/update-log/(scot %p entity.res)/[name.res]/subset/(scot %da start)/'~'
|
||||||
::
|
::
|
||||||
++ get-keys
|
++ get-keys
|
||||||
^- resources
|
^- resources
|
||||||
@ -183,5 +173,5 @@
|
|||||||
::
|
::
|
||||||
++ get-mark
|
++ get-mark
|
||||||
|= res=resource
|
|= res=resource
|
||||||
(scry-for ,(unit mark) /graph-mark/(scot %p entity.res)/[name.res])
|
(scry-for ,(unit mark) /graph/(scot %p entity.res)/[name.res]/mark)
|
||||||
--
|
--
|
||||||
|
@ -3,11 +3,29 @@
|
|||||||
=, space:userlib
|
=, space:userlib
|
||||||
=, format
|
=, format
|
||||||
|%
|
|%
|
||||||
+$ state [%1 pith-1]
|
+$ state state-2
|
||||||
|
+$ state-2 [%2 pith-2]
|
||||||
|
+$ state-1 [%1 pith-1]
|
||||||
|
+$ state-0 [%0 pith-0]
|
||||||
+$ any-state
|
+$ any-state
|
||||||
$% state
|
$% state-2
|
||||||
[%0 pith-0]
|
state-1
|
||||||
|
state-0
|
||||||
==
|
==
|
||||||
|
+$ pith-2 ::
|
||||||
|
$: rem=(map desk per-desk) ::
|
||||||
|
syn=(map kiln-sync let=@ud) ::
|
||||||
|
ota=(unit [=ship =desk =aeon]) ::
|
||||||
|
commit-timer=[way=wire nex=@da tim=@dr mon=term] ::
|
||||||
|
:: map desk to the currently ongoing fuse request
|
||||||
|
:: and the latest version numbers for beaks to
|
||||||
|
fus=(map desk per-fuse)
|
||||||
|
:: used for fuses - every time we get a fuse we
|
||||||
|
:: bump this. used when calculating hashes to
|
||||||
|
:: ensure they're unique even when the same
|
||||||
|
:: request is made multiple times.
|
||||||
|
hxs=(map desk @ud)
|
||||||
|
== ::
|
||||||
+$ pith-1 ::
|
+$ pith-1 ::
|
||||||
$: rem=(map desk per-desk) ::
|
$: rem=(map desk per-desk) ::
|
||||||
syn=(map kiln-sync let=@ud) ::
|
syn=(map kiln-sync let=@ud) ::
|
||||||
@ -31,6 +49,15 @@
|
|||||||
sud=@tas :: from desk
|
sud=@tas :: from desk
|
||||||
cas=case :: at case
|
cas=case :: at case
|
||||||
==
|
==
|
||||||
|
+$ per-fuse :: per fuse state
|
||||||
|
:: map [ship desk] to latest version number we
|
||||||
|
:: have for them. used for things we're %trak-ing
|
||||||
|
:: our invariant here is to store the latest version
|
||||||
|
:: number we've heard of.
|
||||||
|
$: mox=(map [ship desk] let=@ud)
|
||||||
|
:: relevant parts of originating request
|
||||||
|
kf=kiln-fuse-data
|
||||||
|
==
|
||||||
+$ kiln-commit term ::
|
+$ kiln-commit term ::
|
||||||
+$ kiln-mount ::
|
+$ kiln-mount ::
|
||||||
$: pax=path ::
|
$: pax=path ::
|
||||||
@ -55,12 +82,26 @@
|
|||||||
cas=case ::
|
cas=case ::
|
||||||
gim=?(%auto germ) ::
|
gim=?(%auto germ) ::
|
||||||
==
|
==
|
||||||
|
+$ fuse-source [who=ship des=desk ver=$@(%trak case)]
|
||||||
|
:: actual poke
|
||||||
+$ kiln-fuse
|
+$ kiln-fuse
|
||||||
$@ ~
|
$@ ~
|
||||||
$: syd=desk
|
$: syd=desk
|
||||||
bas=beak
|
$@ ~ :: signifies clearing the fuse
|
||||||
con=(list [beak germ])
|
$: overwrite=flag :: force overwrite previous fuse
|
||||||
|
bas=fuse-source
|
||||||
|
con=(list [fuse-source germ])
|
||||||
|
==
|
||||||
==
|
==
|
||||||
|
:: state tracked by kiln
|
||||||
|
+$ kiln-fuse-data
|
||||||
|
$: syd=desk
|
||||||
|
bas=fuse-source
|
||||||
|
con=(list [fuse-source germ])
|
||||||
|
==
|
||||||
|
:: Request to list current fuses. ~ means "list all"
|
||||||
|
::
|
||||||
|
+$ kiln-fuse-list (unit desk)
|
||||||
--
|
--
|
||||||
|= [bowl:gall state]
|
|= [bowl:gall state]
|
||||||
?> =(src our)
|
?> =(src our)
|
||||||
@ -85,6 +126,15 @@
|
|||||||
~[leaf+"from {<sud>}" leaf+"on {<who>}" leaf+"to {<syd>}"]
|
~[leaf+"from {<sud>}" leaf+"on {<who>}" leaf+"to {<syd>}"]
|
||||||
::
|
::
|
||||||
++ on-load
|
++ on-load
|
||||||
|
=>
|
||||||
|
|%
|
||||||
|
++ state-1-to-2
|
||||||
|
|= s=state-1
|
||||||
|
^- state-2
|
||||||
|
=/ p=pith-1 +.s
|
||||||
|
:- %2
|
||||||
|
[rem.p syn.p ota.p commit-timer.p *(map desk per-fuse) *(map desk @ud)]
|
||||||
|
--
|
||||||
|= [hood-version=@ud old=any-state]
|
|= [hood-version=@ud old=any-state]
|
||||||
=< abet
|
=< abet
|
||||||
=? . ?=(%0 -.old)
|
=? . ?=(%0 -.old)
|
||||||
@ -97,8 +147,8 @@
|
|||||||
?: &(=(%base syd.i.syncs) !=(our her.i.syncs) =(%kids sud.i.syncs))
|
?: &(=(%base syd.i.syncs) !=(our her.i.syncs) =(%kids sud.i.syncs))
|
||||||
`[syd her sud]:i.syncs
|
`[syd her sud]:i.syncs
|
||||||
$(syncs t.syncs)
|
$(syncs t.syncs)
|
||||||
::
|
|
||||||
=. +<+.$.abet
|
=. +<+.$.abet
|
||||||
|
%- state-1-to-2
|
||||||
=- old(- %1, |3 [ota=~ commit-timer.old], syn -)
|
=- old(- %1, |3 [ota=~ commit-timer.old], syn -)
|
||||||
?~ recognized-ota
|
?~ recognized-ota
|
||||||
syn
|
syn
|
||||||
@ -108,7 +158,8 @@
|
|||||||
(poke-internal:update `[her sud]:u.recognized-ota)
|
(poke-internal:update `[her sud]:u.recognized-ota)
|
||||||
+(old +<+.$.abet)
|
+(old +<+.$.abet)
|
||||||
::
|
::
|
||||||
?> ?=(%1 -.old)
|
=? old ?=(%1 -.old) (state-1-to-2 old)
|
||||||
|
?> ?=(%2 -.old)
|
||||||
=. +<+.$.abet old
|
=. +<+.$.abet old
|
||||||
..abet
|
..abet
|
||||||
::
|
::
|
||||||
@ -387,10 +438,76 @@
|
|||||||
?~ +< abet
|
?~ +< abet
|
||||||
abet:abet:(merge:(work syd) ali sud cas gim)
|
abet:abet:(merge:(work syd) ali sud cas gim)
|
||||||
::
|
::
|
||||||
|
++ poke-fuse-list
|
||||||
|
=>
|
||||||
|
|%
|
||||||
|
++ format-fuse
|
||||||
|
|= [into=desk pf=per-fuse]
|
||||||
|
^- tank
|
||||||
|
=/ sources=tape
|
||||||
|
%+ reel
|
||||||
|
con.kf.pf
|
||||||
|
|= [[fs=fuse-source g=germ] acc=tape]
|
||||||
|
^- tape
|
||||||
|
;: weld
|
||||||
|
" ["
|
||||||
|
(format-fuse-source fs)
|
||||||
|
" "
|
||||||
|
<g>
|
||||||
|
"]"
|
||||||
|
acc
|
||||||
|
==
|
||||||
|
:- %leaf
|
||||||
|
;: weld
|
||||||
|
"|fuse {<into>} "
|
||||||
|
(format-fuse-source bas.kf.pf)
|
||||||
|
sources
|
||||||
|
==
|
||||||
|
:: +format-fuse-source: fuse source -> beak -> path
|
||||||
|
::
|
||||||
|
++ format-fuse-source
|
||||||
|
|= fs=fuse-source
|
||||||
|
^- tape
|
||||||
|
=/ bec=beak [who.fs des.fs ?:(?=([%trak] ver.fs) [%tas %track] ver.fs)]
|
||||||
|
<(en-beam [bec /])>
|
||||||
|
--
|
||||||
|
|= k=kiln-fuse-list
|
||||||
|
^+ abet
|
||||||
|
%. abet
|
||||||
|
?~ k
|
||||||
|
?~ fus
|
||||||
|
(slog [leaf+"no ongoing fuses" ~])
|
||||||
|
%- slog
|
||||||
|
%+ roll
|
||||||
|
~(tap by `(map desk per-fuse)`fus)
|
||||||
|
|= [[syd=desk pf=per-fuse] acc=tang]
|
||||||
|
^- tang
|
||||||
|
[(format-fuse syd pf) acc]
|
||||||
|
=/ pfu=(unit per-fuse) (~(get by fus) u.k)
|
||||||
|
?~ pfu
|
||||||
|
(slog [leaf+"no ongoing fuse for {<u.k>}" ~])
|
||||||
|
(slog [(format-fuse u.k u.pfu) ~])
|
||||||
|
::
|
||||||
++ poke-fuse
|
++ poke-fuse
|
||||||
|= k=kiln-fuse
|
|= k=kiln-fuse
|
||||||
?~ k abet
|
?~ k abet
|
||||||
abet:(emit [%pass /kiln/fuse/[syd.k] %arvo %c [%fuse syd.k bas.k con.k]])
|
=/ payload +.k
|
||||||
|
?~ payload
|
||||||
|
:: cancelling an ongoing fuse
|
||||||
|
%- (slog [leaf+"cancelling fuse into {<syd.k>}" ~])
|
||||||
|
=/ f (fuzz syd.k now)
|
||||||
|
?~ f
|
||||||
|
abet
|
||||||
|
abet:abet:delete:u.f
|
||||||
|
?: &(!overwrite.payload (~(has by fus) syd.k))
|
||||||
|
((slog [leaf+"existing fuse into {<syd.k>} - need =overwrite &" ~]) abet)
|
||||||
|
=. fus (~(put by fus) syd.k [~ [syd.k bas.payload con.payload]])
|
||||||
|
=/ old-cnt=@ud (~(gut by hxs) syd.k 0)
|
||||||
|
=. hxs (~(put by hxs) syd.k +(old-cnt))
|
||||||
|
=/ f (fuzz syd.k now)
|
||||||
|
?~ f
|
||||||
|
abet
|
||||||
|
abet:abet:fuse:u.f
|
||||||
::
|
::
|
||||||
++ poke-cancel
|
++ poke-cancel
|
||||||
|= a=@tas
|
|= a=@tas
|
||||||
@ -442,6 +559,7 @@
|
|||||||
%kiln-label =;(f (f !<(_+<.f vase)) poke-label)
|
%kiln-label =;(f (f !<(_+<.f vase)) poke-label)
|
||||||
%kiln-merge =;(f (f !<(_+<.f vase)) poke-merge)
|
%kiln-merge =;(f (f !<(_+<.f vase)) poke-merge)
|
||||||
%kiln-fuse =;(f (f !<(_+<.f vase)) poke-fuse)
|
%kiln-fuse =;(f (f !<(_+<.f vase)) poke-fuse)
|
||||||
|
%kiln-fuse-list =;(f (f !<(_+<.f vase)) poke-fuse-list)
|
||||||
%kiln-mount =;(f (f !<(_+<.f vase)) poke-mount)
|
%kiln-mount =;(f (f !<(_+<.f vase)) poke-mount)
|
||||||
%kiln-ota =;(f (f !<(_+<.f vase)) poke:update)
|
%kiln-ota =;(f (f !<(_+<.f vase)) poke:update)
|
||||||
%kiln-ota-info =;(f (f !<(_+<.f vase)) poke-ota-info)
|
%kiln-ota-info =;(f (f !<(_+<.f vase)) poke-ota-info)
|
||||||
@ -489,6 +607,21 @@
|
|||||||
[%autocommit *] %+ take-wake-autocommit t.wire
|
[%autocommit *] %+ take-wake-autocommit t.wire
|
||||||
?>(?=(%wake +<.sign-arvo) +>.sign-arvo)
|
?>(?=(%wake +<.sign-arvo) +>.sign-arvo)
|
||||||
[%ota *] abet:(take:update t.wire sign-arvo)
|
[%ota *] abet:(take:update t.wire sign-arvo)
|
||||||
|
[%fuse-request @tas *]
|
||||||
|
=/ f (fuzz i.t.wire now)
|
||||||
|
?~ f
|
||||||
|
abet
|
||||||
|
abet:abet:(take:u.f t.t.wire sign-arvo)
|
||||||
|
[%fuse @tas *] ?> ?=(%mere +<.sign-arvo)
|
||||||
|
=/ syd=desk i.t.wire
|
||||||
|
?. ?=([%| *] +>.sign-arvo)
|
||||||
|
?~ p.p.sign-arvo
|
||||||
|
abet
|
||||||
|
=/ msg=tape "fuse merge conflict for {<syd>}"
|
||||||
|
%- (slog [leaf+msg >p.p.sign-arvo< ~])
|
||||||
|
abet
|
||||||
|
%- (slog leaf+"failed fuse for {<syd>}" p.p.sign-arvo)
|
||||||
|
abet
|
||||||
*
|
*
|
||||||
?+ +<.sign-arvo
|
?+ +<.sign-arvo
|
||||||
((slog leaf+"kiln: strange card {<+<.sign-arvo wire>}" ~) abet)
|
((slog leaf+"kiln: strange card {<+<.sign-arvo wire>}" ~) abet)
|
||||||
@ -567,6 +700,122 @@
|
|||||||
++ spam
|
++ spam
|
||||||
|= mes=(list tank)
|
|= mes=(list tank)
|
||||||
((slog mes) ..spam)
|
((slog mes) ..spam)
|
||||||
|
:: state machine for fuses
|
||||||
|
::
|
||||||
|
++ fuzz
|
||||||
|
|= [syd=desk now=@da]
|
||||||
|
=/ pfu=(unit per-fuse) (~(get by fus) syd)
|
||||||
|
?~ pfu
|
||||||
|
~
|
||||||
|
=* kf kf.u.pfu
|
||||||
|
=* mox mox.u.pfu
|
||||||
|
=/ should-delete=flag |
|
||||||
|
%- some
|
||||||
|
|%
|
||||||
|
:: finalize
|
||||||
|
::
|
||||||
|
++ abet
|
||||||
|
?: should-delete
|
||||||
|
..fuzz(fus (~(del by fus) syd))
|
||||||
|
..fuzz(fus (~(put by fus) syd [mox kf]))
|
||||||
|
::
|
||||||
|
++ delete
|
||||||
|
^+ ..delete
|
||||||
|
=. should-delete &
|
||||||
|
..delete
|
||||||
|
:: queue moves
|
||||||
|
::
|
||||||
|
++ blab
|
||||||
|
|= new=(list card:agent:gall)
|
||||||
|
^+ +>
|
||||||
|
+>.$(moz (welp new moz))
|
||||||
|
:: +make-requests: send requests for each %trak source.
|
||||||
|
::
|
||||||
|
++ make-requests
|
||||||
|
^+ ..abet
|
||||||
|
=/ movs=(list card:agent:gall)
|
||||||
|
%+ murn
|
||||||
|
[[bas.kf *germ] con.kf]
|
||||||
|
|= [fs=fuse-source germ]
|
||||||
|
^- (unit card:agent:gall)
|
||||||
|
?^ ver.fs
|
||||||
|
:: static source, don't need to track
|
||||||
|
~
|
||||||
|
=/ bec=beak (realize-fuse-source fs &)
|
||||||
|
?> =(who.fs p.bec)
|
||||||
|
?> =(des.fs q.bec)
|
||||||
|
=/ hax=@ud (mug [kf (~(got by hxs) syd)])
|
||||||
|
=/ wir=wire
|
||||||
|
/kiln/fuse-request/[syd]/(scot %p p.bec)/[q.bec]/(scot %ud hax)
|
||||||
|
=/ rav=rave [%sing %w r.bec /]
|
||||||
|
=/ rif=riff [q.bec `rav]
|
||||||
|
`[%pass wir %arvo %c [%warp who.fs rif]]
|
||||||
|
:: No need to keep state if all the sources are static
|
||||||
|
?~ movs
|
||||||
|
delete
|
||||||
|
(blab movs)
|
||||||
|
::
|
||||||
|
++ send-fuse
|
||||||
|
^+ ..abet
|
||||||
|
=/ bas=beak (realize-fuse-source bas.kf |)
|
||||||
|
=/ con=(list [beak germ])
|
||||||
|
%+ turn
|
||||||
|
con.kf
|
||||||
|
|= [fs=fuse-source g=germ]
|
||||||
|
[(realize-fuse-source fs |) g]
|
||||||
|
%- blab
|
||||||
|
[%pass /kiln/fuse/[syd] %arvo %c [%fuse syd bas con]]~
|
||||||
|
::
|
||||||
|
++ fuse
|
||||||
|
^+ ..abet
|
||||||
|
send-fuse:make-requests
|
||||||
|
::
|
||||||
|
++ take
|
||||||
|
|= [wir=wire =sign-arvo]
|
||||||
|
^+ ..fuse
|
||||||
|
?> =((lent wir) 3)
|
||||||
|
=/ who=ship (slav %p (snag 0 wir))
|
||||||
|
=/ src=desk (snag 1 wir)
|
||||||
|
=/ hax=@ud (slav %ud (snag 2 wir))
|
||||||
|
?. =(hax (mug [kf (~(got by hxs) syd)]))
|
||||||
|
:: If the hash in the wire doesn't match the current request
|
||||||
|
:: this is a response for a previous fuse that we can ignore.
|
||||||
|
..take
|
||||||
|
?> ?=([?(%clay %behn) %writ *] sign-arvo)
|
||||||
|
=/ gif +.sign-arvo
|
||||||
|
?~ p.gif
|
||||||
|
%- (slog leaf+"|fuse request failed for {<src>} on <who> - cancelling")
|
||||||
|
delete
|
||||||
|
=/ cas=cass:clay !<(cass:clay +.r.u.p.gif)
|
||||||
|
=. mox (~(put by mox) [who src] ud.cas)
|
||||||
|
fuse
|
||||||
|
::
|
||||||
|
:: utility functions below
|
||||||
|
::
|
||||||
|
:: +realize-fuse-source: convert a fuse-source to a
|
||||||
|
:: fully realized beak.
|
||||||
|
::
|
||||||
|
++ realize-fuse-source
|
||||||
|
|= [fs=fuse-source incr=flag]
|
||||||
|
^- beak
|
||||||
|
:+ who.fs
|
||||||
|
des.fs
|
||||||
|
?@ ver.fs
|
||||||
|
(realize-case [who.fs des.fs incr])
|
||||||
|
`case`ver.fs
|
||||||
|
::
|
||||||
|
++ realize-case
|
||||||
|
|= [who=ship des=desk incr=flag]
|
||||||
|
^- case
|
||||||
|
=/ let=(unit @ud) (~(get by mox) [who des])
|
||||||
|
^- case
|
||||||
|
?~ let
|
||||||
|
da+now
|
||||||
|
:- %ud
|
||||||
|
?: incr
|
||||||
|
+(u.let)
|
||||||
|
u.let
|
||||||
|
--
|
||||||
::
|
::
|
||||||
++ auto
|
++ auto
|
||||||
|= kiln-sync
|
|= kiln-sync
|
||||||
|
@ -37,6 +37,17 @@
|
|||||||
[%metadata (^metadatum metadatum)]
|
[%metadata (^metadatum metadatum)]
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
|
++ edit-field
|
||||||
|
|= edt=^edit-field
|
||||||
|
^- json
|
||||||
|
%+ frond -.edt
|
||||||
|
^- json
|
||||||
|
?- -.edt
|
||||||
|
%color [%s `@t`(scot %ux color.edt)]
|
||||||
|
?(%title %description %picture %vip) [%s `@t`+.edt]
|
||||||
|
?(%preview %hidden) [%b `?`+.edt]
|
||||||
|
==
|
||||||
|
::
|
||||||
++ metadatum
|
++ metadatum
|
||||||
|= met=^metadatum
|
|= met=^metadatum
|
||||||
^- json
|
^- json
|
||||||
@ -85,6 +96,16 @@
|
|||||||
[%resource s+(enjs-path:resource resource.resource.upd)]
|
[%resource s+(enjs-path:resource resource.resource.upd)]
|
||||||
[%metadata (metadatum metadatum.upd)]
|
[%metadata (metadatum metadatum.upd)]
|
||||||
==
|
==
|
||||||
|
::
|
||||||
|
%edit
|
||||||
|
:- %edit
|
||||||
|
%- pairs
|
||||||
|
:~ [%group s+(enjs-path:resource group.upd)]
|
||||||
|
[%app-name s+app-name.resource.upd]
|
||||||
|
[%resource s+(enjs-path:resource resource.resource.upd)]
|
||||||
|
[%edit (edit-field edit-field.upd)]
|
||||||
|
==
|
||||||
|
::
|
||||||
%updated-metadata
|
%updated-metadata
|
||||||
:- %add
|
:- %add
|
||||||
%- pairs
|
%- pairs
|
||||||
@ -136,6 +157,25 @@
|
|||||||
:~ [%add add]
|
:~ [%add add]
|
||||||
[%remove remove]
|
[%remove remove]
|
||||||
[%initial-group initial-group]
|
[%initial-group initial-group]
|
||||||
|
[%edit edit]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ edit
|
||||||
|
%- ot
|
||||||
|
:~ [%group dejs-path:resource]
|
||||||
|
[%resource md-resource]
|
||||||
|
[%edit edit-field]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ edit-field
|
||||||
|
%- of
|
||||||
|
:~ [%title so]
|
||||||
|
[%description so]
|
||||||
|
[%color nu]
|
||||||
|
[%picture so]
|
||||||
|
[%preview bo]
|
||||||
|
[%hidden bo]
|
||||||
|
[%vip vip]
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ initial-group
|
++ initial-group
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|= =vase
|
|= =vase
|
||||||
^- (list resource)
|
^- (list resource)
|
||||||
=/ =update:store !<(update:store vase)
|
=/ =update:store !<(update:store vase)
|
||||||
?. ?=(?(%add %remove %initial-group) -.update) ~
|
?. ?=(?(%add %remove %initial-group %edit) -.update) ~
|
||||||
~[group.update]
|
~[group.update]
|
||||||
::
|
::
|
||||||
++ app-paths-from-group
|
++ app-paths-from-group
|
||||||
|
@ -232,58 +232,76 @@
|
|||||||
:: +veri:dawn: validate keys, life, discontinuity, &c
|
:: +veri:dawn: validate keys, life, discontinuity, &c
|
||||||
::
|
::
|
||||||
++ veri
|
++ veri
|
||||||
|= [=seed:jael =point:azimuth =live]
|
|= [=ship =feed:jael =point:azimuth =live]
|
||||||
^- (unit error=term)
|
^- (each seed:jael (lest error=term))
|
||||||
=/ rac (clan:title who.seed)
|
|^ ?@ -.feed
|
||||||
=/ cub (nol:nu:crub:crypto key.seed)
|
?^ err=(test feed) |+[u.err ~]
|
||||||
?- rac
|
&+feed
|
||||||
%pawn
|
?> ?=([%1 ~] -.feed)
|
||||||
:: a comet address is the fingerprint of the keypair
|
=| errs=(list term)
|
||||||
::
|
|-
|
||||||
?. =(who.seed `@`fig:ex:cub)
|
?~ kyz.feed
|
||||||
`%key-mismatch
|
|+?~(errs [%no-key ~] errs)
|
||||||
:: a comet can never be breached
|
=/ =seed:jael [who [lyf key ~]:i.kyz]:feed
|
||||||
::
|
?~ err=(test seed)
|
||||||
?^ live
|
&+seed
|
||||||
`%already-booted
|
=. errs (snoc errs u.err)
|
||||||
:: a comet can never be re-keyed
|
$(kyz.feed t.kyz.feed)
|
||||||
::
|
|
||||||
?. ?=(%1 lyf.seed)
|
|
||||||
`%invalid-life
|
|
||||||
~
|
|
||||||
::
|
::
|
||||||
%earl
|
++ test
|
||||||
~
|
|= =seed:jael
|
||||||
::
|
^- (unit error=term)
|
||||||
*
|
?. =(ship who.seed) `%not-our-key
|
||||||
:: on-chain ships must be launched
|
=/ rac (clan:title who.seed)
|
||||||
|
=/ cub (nol:nu:crub:crypto key.seed)
|
||||||
|
?- rac
|
||||||
|
%pawn
|
||||||
|
:: a comet address is the fingerprint of the keypair
|
||||||
|
::
|
||||||
|
?. =(who.seed `@`fig:ex:cub)
|
||||||
|
`%key-mismatch
|
||||||
|
:: a comet can never be breached
|
||||||
|
::
|
||||||
|
?^ live
|
||||||
|
`%already-booted
|
||||||
|
:: a comet can never be re-keyed
|
||||||
|
::
|
||||||
|
?. ?=(%1 lyf.seed)
|
||||||
|
`%invalid-life
|
||||||
|
~
|
||||||
::
|
::
|
||||||
?~ net.point
|
%earl
|
||||||
`%not-keyed
|
~
|
||||||
=* net u.net.point
|
|
||||||
:: boot keys must match the contract
|
|
||||||
::
|
::
|
||||||
?. =(pub:ex:cub pass.net)
|
*
|
||||||
~& [%key-mismatch pub:ex:cub pass.net]
|
:: on-chain ships must be launched
|
||||||
`%key-mismatch
|
::
|
||||||
:: life must match the contract
|
?~ net.point
|
||||||
::
|
`%not-keyed
|
||||||
?. =(lyf.seed life.net)
|
=* net u.net.point
|
||||||
`%life-mismatch
|
:: boot keys must match the contract
|
||||||
:: the boot life must be greater than and discontinuous with
|
::
|
||||||
:: the last seen life (per the sponsor)
|
?. =(pub:ex:cub pass.net)
|
||||||
::
|
`%key-mismatch
|
||||||
?: ?& ?=(^ live)
|
:: life must match the contract
|
||||||
?| ?=(%| breach.u.live)
|
::
|
||||||
(lte life.net life.u.live)
|
?. =(lyf.seed life.net)
|
||||||
== ==
|
`%life-mismatch
|
||||||
`%already-booted
|
:: the boot life must be greater than and discontinuous with
|
||||||
:: produce the sponsor for vere
|
:: the last seen life (per the sponsor)
|
||||||
::
|
::
|
||||||
~? !has.sponsor.net
|
?: ?& ?=(^ live)
|
||||||
[%no-sponsorship-guarantees-from who.sponsor.net]
|
?| ?=(%| breach.u.live)
|
||||||
~
|
(lte life.net life.u.live)
|
||||||
==
|
== ==
|
||||||
|
`%already-booted
|
||||||
|
:: produce the sponsor for vere
|
||||||
|
::
|
||||||
|
~? !has.sponsor.net
|
||||||
|
[%no-sponsorship-guarantees-from who.sponsor.net]
|
||||||
|
~
|
||||||
|
==
|
||||||
|
--
|
||||||
:: +sponsor:dawn: retreive sponsor from point
|
:: +sponsor:dawn: retreive sponsor from point
|
||||||
::
|
::
|
||||||
++ sponsor
|
++ sponsor
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
/+ store=metadata-store
|
/+ store=metadata-store
|
||||||
|_ =update:store
|
|_ =update:one:store
|
||||||
++ grad %noun
|
++ grad %noun
|
||||||
++ grow
|
++ grow
|
||||||
|%
|
|%
|
||||||
++ noun update
|
++ noun update
|
||||||
++ json (update:enjs:store update)
|
++ metadata-update-2
|
||||||
|
^- update:store
|
||||||
|
update
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ grab
|
++ grab
|
||||||
|%
|
|%
|
||||||
++ noun update:store
|
++ noun update:one:store
|
||||||
++ json action:dejs:store
|
:: This is ok, we don't send %edit over the wire yet.
|
||||||
|
++ metadata-update-2
|
||||||
|
|= upd=update:store
|
||||||
|
^- update:one:store
|
||||||
|
?< ?=(%edit -.upd)
|
||||||
|
upd
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
|
15
pkg/arvo/mar/metadata/update-2.hoon
Normal file
15
pkg/arvo/mar/metadata/update-2.hoon
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/+ store=metadata-store
|
||||||
|
|_ =update:store
|
||||||
|
++ grad %noun
|
||||||
|
++ grow
|
||||||
|
|%
|
||||||
|
++ noun update
|
||||||
|
++ json (update:enjs:store update)
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ grab
|
||||||
|
|%
|
||||||
|
++ noun update:store
|
||||||
|
++ json action:dejs:store
|
||||||
|
--
|
||||||
|
--
|
@ -44,6 +44,16 @@
|
|||||||
[%empty ~]
|
[%empty ~]
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
|
+$ edit-field
|
||||||
|
$% [%title title=cord]
|
||||||
|
[%description description=cord]
|
||||||
|
[%color color=@ux]
|
||||||
|
[%picture =url]
|
||||||
|
[%preview preview=?]
|
||||||
|
[%hidden hidden=?]
|
||||||
|
[%vip vip=vip-metadata]
|
||||||
|
==
|
||||||
|
::
|
||||||
+$ metadatum
|
+$ metadatum
|
||||||
$: title=cord
|
$: title=cord
|
||||||
description=cord
|
description=cord
|
||||||
@ -60,6 +70,7 @@
|
|||||||
+$ action
|
+$ action
|
||||||
$% [%add group=resource resource=md-resource =metadatum]
|
$% [%add group=resource resource=md-resource =metadatum]
|
||||||
[%remove group=resource resource=md-resource]
|
[%remove group=resource resource=md-resource]
|
||||||
|
[%edit group=resource resource=md-resource =edit-field]
|
||||||
[%initial-group group=resource =associations]
|
[%initial-group group=resource =associations]
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
@ -79,6 +90,18 @@
|
|||||||
==
|
==
|
||||||
==
|
==
|
||||||
:: historical
|
:: historical
|
||||||
|
++ one
|
||||||
|
|%
|
||||||
|
::
|
||||||
|
+$ action
|
||||||
|
$~ [%remove *resource *md-resource]
|
||||||
|
$< %edit ^action
|
||||||
|
::
|
||||||
|
+$ update
|
||||||
|
$~ [%remove *resource *md-resource]
|
||||||
|
$< %edit ^update
|
||||||
|
::
|
||||||
|
--
|
||||||
++ zero
|
++ zero
|
||||||
|%
|
|%
|
||||||
::
|
::
|
||||||
|
@ -1879,7 +1879,12 @@
|
|||||||
[%public-keys =public-keys-result] :: ethereum changes
|
[%public-keys =public-keys-result] :: ethereum changes
|
||||||
[%turf turf=(list turf)] :: domains
|
[%turf turf=(list turf)] :: domains
|
||||||
== ::
|
== ::
|
||||||
:: +seed: private boot parameters
|
:: +feed: potential boot parameters
|
||||||
|
::
|
||||||
|
+$ feed
|
||||||
|
$^ [[%1 ~] who=ship kyz=(list [lyf=life key=ring])]
|
||||||
|
seed
|
||||||
|
:: +seed: individual boot parameters
|
||||||
::
|
::
|
||||||
+$ seed [who=ship lyf=life key=ring sig=(unit oath:pki)]
|
+$ seed [who=ship lyf=life key=ring sig=(unit oath:pki)]
|
||||||
::
|
::
|
||||||
|
@ -2096,7 +2096,7 @@
|
|||||||
|= [k=beak v=(unit dome:clay)]
|
|= [k=beak v=(unit dome:clay)]
|
||||||
^- tank
|
^- tank
|
||||||
=/ received=tape ?~(v "missing" "received")
|
=/ received=tape ?~(v "missing" "received")
|
||||||
leaf+"{<k>} {received}"
|
leaf+"{<(en-beam k ~)>} {received}"
|
||||||
:_ discarded
|
:_ discarded
|
||||||
leaf+"fusing into {<syd>} from {<bas>} {<con>} - overwriting prior fuse"
|
leaf+"fusing into {<syd>} from {<bas>} {<con>} - overwriting prior fuse"
|
||||||
=. fiz (make-melt bas con)
|
=. fiz (make-melt bas con)
|
||||||
@ -2113,8 +2113,11 @@
|
|||||||
:: responses we get for the merge will cause take-fuse to crash
|
:: responses we get for the merge will cause take-fuse to crash
|
||||||
::
|
::
|
||||||
=. fiz *melt
|
=. fiz *melt
|
||||||
((slog [leaf+"clay: fuse failed, missing {<bec>}"]~) ..take-fuse)
|
=/ msg=tape <(en-beam bec ~)>
|
||||||
?> (~(has by sto.fiz) bec)
|
((slog [leaf+"clay: fuse failed, missing {msg}"]~) ..take-fuse)
|
||||||
|
?. (~(has by sto.fiz) bec)
|
||||||
|
=/ msg=tape <(en-beam bec ~)>
|
||||||
|
((slog [leaf+"clay: got strange fuse response {<msg>}"]~) ..take-fuse)
|
||||||
=. fiz
|
=. fiz
|
||||||
:+ bas.fiz con.fiz
|
:+ bas.fiz con.fiz
|
||||||
(~(put by sto.fiz) bec `!<(dome:clay q.r.u.riot))
|
(~(put by sto.fiz) bec `!<(dome:clay q.r.u.riot))
|
||||||
@ -2135,7 +2138,6 @@
|
|||||||
|-
|
|-
|
||||||
^+ ..take-fuse
|
^+ ..take-fuse
|
||||||
?~ merges
|
?~ merges
|
||||||
=/ t=tang [leaf+"{<syd>} fused from {<bas.fiz>} {<con.fiz>}" ~]
|
|
||||||
=. ..take-fuse (done-fuse clean-state %& ~)
|
=. ..take-fuse (done-fuse clean-state %& ~)
|
||||||
(park | [%| continuation-yaki(p (flop parents))] rag)
|
(park | [%| continuation-yaki(p (flop parents))] rag)
|
||||||
=/ [bec=beak g=germ] i.merges
|
=/ [bec=beak g=germ] i.merges
|
||||||
@ -2143,7 +2145,8 @@
|
|||||||
=/ result (merge-helper p.bec q.bec g ali-dom `continuation-yaki)
|
=/ result (merge-helper p.bec q.bec g ali-dom `continuation-yaki)
|
||||||
?- -.result
|
?- -.result
|
||||||
%|
|
%|
|
||||||
(done-fuse clean-state %| %fuse-merge-failed p.result)
|
=/ failing-merge=tape "{<bec>} {<g>}"
|
||||||
|
(done-fuse clean-state %| %fuse-merge-failed leaf+failing-merge p.result)
|
||||||
::
|
::
|
||||||
%&
|
%&
|
||||||
=/ merge-result=(unit merge-result) +.result
|
=/ merge-result=(unit merge-result) +.result
|
||||||
|
@ -554,6 +554,7 @@
|
|||||||
:: +per-server-event: per-event server core
|
:: +per-server-event: per-event server core
|
||||||
::
|
::
|
||||||
++ per-server-event
|
++ per-server-event
|
||||||
|
~% %eyre-per-server-event ..part ~
|
||||||
:: gate that produces the +per-server-event core from event information
|
:: gate that produces the +per-server-event core from event information
|
||||||
::
|
::
|
||||||
|= [[eny=@ =duct now=@da rof=roof] state=server-state]
|
|= [[eny=@ =duct now=@da rof=roof] state=server-state]
|
||||||
@ -781,7 +782,7 @@
|
|||||||
:* duct %pass /run-app-request/[eyre-id]
|
:* duct %pass /run-app-request/[eyre-id]
|
||||||
%g %deal [our our] app
|
%g %deal [our our] app
|
||||||
%poke %handle-http-request
|
%poke %handle-http-request
|
||||||
!>([eyre-id inbound-request])
|
!>(`[@ta inbound-request:eyre]`[eyre-id inbound-request])
|
||||||
==
|
==
|
||||||
==
|
==
|
||||||
:: +cancel-request: handles a request being externally aborted
|
:: +cancel-request: handles a request being externally aborted
|
||||||
@ -1205,15 +1206,21 @@
|
|||||||
?~ maybe-channel=(~(get by session.channel-state.state) channel-id)
|
?~ maybe-channel=(~(get by session.channel-state.state) channel-id)
|
||||||
%^ return-static-data-on-duct 404 'text/html'
|
%^ return-static-data-on-duct 404 'text/html'
|
||||||
(error-page 404 %.y url.request ~)
|
(error-page 404 %.y url.request ~)
|
||||||
:: if there's already a duct listening to this channel, we must 400
|
|
||||||
::
|
|
||||||
?: ?=([%| *] state.u.maybe-channel)
|
|
||||||
%^ return-static-data-on-duct 400 'text/html'
|
|
||||||
(error-page 400 %.y url.request "channel already bound")
|
|
||||||
:: when opening an event-stream, we must cancel our timeout timer
|
:: when opening an event-stream, we must cancel our timeout timer
|
||||||
|
:: if there's no duct already bound. Else, kill the old request
|
||||||
|
:: and replace it
|
||||||
::
|
::
|
||||||
=. moves
|
=^ cancel-moves state
|
||||||
[(cancel-timeout-move channel-id p.state.u.maybe-channel) moves]
|
?. ?=([%| *] state.u.maybe-channel)
|
||||||
|
:_ state
|
||||||
|
(cancel-timeout-move channel-id p.state.u.maybe-channel)^~
|
||||||
|
=/ cancel-heartbeat
|
||||||
|
?~ heartbeat.u.maybe-channel ~
|
||||||
|
:_ ~
|
||||||
|
%+ cancel-heartbeat-move channel-id
|
||||||
|
[date duct]:u.heartbeat.u.maybe-channel
|
||||||
|
=- [(weld cancel-heartbeat -<) ->]
|
||||||
|
(handle-response(duct p.state.u.maybe-channel) [%cancel ~])
|
||||||
:: the request may include a 'Last-Event-Id' header
|
:: the request may include a 'Last-Event-Id' header
|
||||||
::
|
::
|
||||||
=/ maybe-last-event-id=(unit @ud)
|
=/ maybe-last-event-id=(unit @ud)
|
||||||
@ -1282,7 +1289,7 @@
|
|||||||
|= =channel
|
|= =channel
|
||||||
channel(events ~, state [%| duct], heartbeat (some [heartbeat-time duct]))
|
channel(events ~, state [%| duct], heartbeat (some [heartbeat-time duct]))
|
||||||
::
|
::
|
||||||
[[heartbeat (weld http-moves moves)] state]
|
[[heartbeat :(weld http-moves cancel-moves moves)] state]
|
||||||
:: +acknowledge-events: removes events before :last-event-id on :channel-id
|
:: +acknowledge-events: removes events before :last-event-id on :channel-id
|
||||||
::
|
::
|
||||||
++ acknowledge-events
|
++ acknowledge-events
|
||||||
@ -1710,7 +1717,7 @@
|
|||||||
=/ res
|
=/ res
|
||||||
%- handle-response
|
%- handle-response
|
||||||
:* %continue
|
:* %continue
|
||||||
data=(some (as-octs:mimes:html '\0a'))
|
data=(some (as-octs:mimes:html ':\0a'))
|
||||||
complete=%.n
|
complete=%.n
|
||||||
==
|
==
|
||||||
=/ http-moves -.res
|
=/ http-moves -.res
|
||||||
|
@ -760,12 +760,10 @@
|
|||||||
mo-core
|
mo-core
|
||||||
=^ [=duct =routes blocker=(each deal sign:agent)] blocked
|
=^ [=duct =routes blocker=(each deal sign:agent)] blocked
|
||||||
~(get to blocked)
|
~(get to blocked)
|
||||||
|
?: ?=(%| -.blocker) $
|
||||||
=/ =move
|
=/ =move
|
||||||
=/ =sock [attributing.routes our]
|
=/ =sock [attributing.routes our]
|
||||||
=/ card
|
=/ card [%slip %g %deal sock dap p.blocker]
|
||||||
?: ?=(%& -.blocker)
|
|
||||||
[%slip %g %deal sock dap p.blocker]
|
|
||||||
[%pass /clear-huck %b %huck `sign-arvo`[%gall %unto p.blocker]]
|
|
||||||
[duct card]
|
[duct card]
|
||||||
$(moves [move moves])
|
$(moves [move moves])
|
||||||
:: +mo-filter-queue: remove all blocked tasks from ship.
|
:: +mo-filter-queue: remove all blocked tasks from ship.
|
||||||
|
@ -434,7 +434,7 @@
|
|||||||
%- curd =< abet
|
%- curd =< abet
|
||||||
(private-keys:~(feel su hen now pki etn) life.tac ring.tac)
|
(private-keys:~(feel su hen now pki etn) life.tac ring.tac)
|
||||||
::
|
::
|
||||||
:: update private keys
|
:: register moon keys
|
||||||
::
|
::
|
||||||
%moon
|
%moon
|
||||||
?. =(%earl (clan:title ship.tac))
|
?. =(%earl (clan:title ship.tac))
|
||||||
@ -717,6 +717,14 @@
|
|||||||
=/ a-point=point (~(gut by pos.zim.pki) ship.i.udiffs *point)
|
=/ a-point=point (~(gut by pos.zim.pki) ship.i.udiffs *point)
|
||||||
=/ a-diff=(unit diff:point) (udiff-to-diff:point udiff.i.udiffs a-point)
|
=/ a-diff=(unit diff:point) (udiff-to-diff:point udiff.i.udiffs a-point)
|
||||||
=? this-su ?=(^ a-diff)
|
=? this-su ?=(^ a-diff)
|
||||||
|
:: if this about our keys, and we already know these, start using them
|
||||||
|
::
|
||||||
|
=? lyf.own
|
||||||
|
?& =(our ship.i.udiffs)
|
||||||
|
?=(%keys -.u.a-diff)
|
||||||
|
(~(has by jaw.own) life.to.u.a-diff)
|
||||||
|
==
|
||||||
|
life.to.u.a-diff
|
||||||
(public-keys:feel original-pos %diff ship.i.udiffs u.a-diff)
|
(public-keys:feel original-pos %diff ship.i.udiffs u.a-diff)
|
||||||
$(udiffs t.udiffs)
|
$(udiffs t.udiffs)
|
||||||
::
|
::
|
||||||
@ -926,7 +934,16 @@
|
|||||||
^+ ..feel
|
^+ ..feel
|
||||||
?: &(=(lyf.own life) =((~(get by jaw.own) life) `ring))
|
?: &(=(lyf.own life) =((~(get by jaw.own) life) `ring))
|
||||||
..feel
|
..feel
|
||||||
=. lyf.own life
|
:: only eagerly update lyf if we were behind the chain life
|
||||||
|
::
|
||||||
|
=? lyf.own
|
||||||
|
?& (gth life lyf.own)
|
||||||
|
::
|
||||||
|
=+ pon=(~(get by pos.zim) our)
|
||||||
|
?~ pon |
|
||||||
|
(lth lyf.own life.u.pon)
|
||||||
|
==
|
||||||
|
life
|
||||||
=. jaw.own (~(put by jaw.own) life ring)
|
=. jaw.own (~(put by jaw.own) life ring)
|
||||||
(exec yen.own [%give %private-keys lyf.own jaw.own])
|
(exec yen.own [%give %private-keys lyf.own jaw.own])
|
||||||
::
|
::
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
(poke-our %graph-push-hook %push-hook-action !>([%add feed-rid]))
|
(poke-our %graph-push-hook %push-hook-action !>([%add feed-rid]))
|
||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
%+ poke-our %metadata-push-hook
|
%+ poke-our %metadata-push-hook
|
||||||
:- %metadata-update-1
|
:- %metadata-update-2
|
||||||
!> ^- action:met
|
!> ^- action:met
|
||||||
:^ %add
|
:^ %add
|
||||||
group.action
|
group.action
|
||||||
@ -54,7 +54,7 @@
|
|||||||
metadatum(feed.config ``[%graph feed-rid])
|
metadatum(feed.config ``[%graph feed-rid])
|
||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
%+ poke-our %metadata-push-hook
|
%+ poke-our %metadata-push-hook
|
||||||
:- %metadata-update-1
|
:- %metadata-update-2
|
||||||
!> ^- action:met
|
!> ^- action:met
|
||||||
:^ %add
|
:^ %add
|
||||||
group.action
|
group.action
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
=/ met-action=action:met
|
=/ met-action=action:met
|
||||||
[%add group graph+rid.action metadatum]
|
[%add group graph+rid.action metadatum]
|
||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
(poke-our %metadata-push-hook metadata-update-1+!>(met-action))
|
(poke-our %metadata-push-hook metadata-update-2+!>(met-action))
|
||||||
::
|
::
|
||||||
:: Send invites
|
:: Send invites
|
||||||
::
|
::
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
(poke-our %graph-push-hook %push-hook-action !>([%remove rid]))
|
(poke-our %graph-push-hook %push-hook-action !>([%remove rid]))
|
||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
%+ poke-our %metadata-push-hook
|
%+ poke-our %metadata-push-hook
|
||||||
:- %metadata-update-1
|
:- %metadata-update-2
|
||||||
!> ^- action:metadata
|
!> ^- action:metadata
|
||||||
[%remove group-rid [%graph rid]]
|
[%remove group-rid [%graph rid]]
|
||||||
(pure:m ~)
|
(pure:m ~)
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
==
|
==
|
||||||
;< ~ bind:m
|
;< ~ bind:m
|
||||||
%+ poke-our %metadata-push-hook
|
%+ poke-our %metadata-push-hook
|
||||||
:- %metadata-update-1
|
:- %metadata-update-2
|
||||||
!> ^- action:met
|
!> ^- action:met
|
||||||
:^ %add
|
:^ %add
|
||||||
group.action
|
group.action
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|= arg=vase
|
|= arg=vase
|
||||||
=/ m (strand ,vase)
|
=/ m (strand ,vase)
|
||||||
^- form:m
|
^- form:m
|
||||||
=+ !<(desks=(list desk) arg)
|
=+ !<([~ desks=(list desk)] arg)
|
||||||
=? desks =(~ desks) [%work]~
|
=? desks =(~ desks) [%work]~
|
||||||
|- ^- form:m
|
|- ^- form:m
|
||||||
=* loop $
|
=* loop $
|
||||||
|
@ -188,37 +188,53 @@
|
|||||||
++ test-veri-good
|
++ test-veri-good
|
||||||
=/ sed [~zod 1 sec ~]
|
=/ sed [~zod 1 sec ~]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> ~
|
!> &+sed
|
||||||
!> (veri:dawn sed pot ~)
|
!> (veri:dawn ~zod sed pot ~)
|
||||||
::
|
::
|
||||||
++ test-veri-not-spawned
|
++ test-veri-not-spawned
|
||||||
=/ sed [~zod 1 sec ~]
|
=/ sed [~zod 1 sec ~]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> `%not-keyed
|
!> |+[%not-keyed ~]
|
||||||
!> (veri:dawn sed =>(pot .(net ~)) ~)
|
!> (veri:dawn ~zod sed =>(pot .(net ~)) ~)
|
||||||
::
|
::
|
||||||
++ test-veri-wrong-key
|
++ test-veri-wrong-key
|
||||||
=/ sed [~zod 1 sec:ex:(pit:nu:crub:crypto 24 %foo) ~]
|
=/ sed [~zod 1 sec:ex:(pit:nu:crub:crypto 24 %foo) ~]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> `%key-mismatch
|
!> |+[%key-mismatch ~]
|
||||||
!> (veri:dawn sed pot ~)
|
!> (veri:dawn ~zod sed pot ~)
|
||||||
::
|
::
|
||||||
++ test-veri-life-mismatch
|
++ test-veri-life-mismatch
|
||||||
=/ sed [~zod 2 sec ~]
|
=/ sed [~zod 2 sec ~]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> `%life-mismatch
|
!> |+[%life-mismatch ~]
|
||||||
!> (veri:dawn sed pot ~)
|
!> (veri:dawn ~zod sed pot ~)
|
||||||
|
::
|
||||||
|
++ test-veri-bad-multikey
|
||||||
|
=/ fed=feed:jael
|
||||||
|
:- [%1 ~]
|
||||||
|
:- ~zod
|
||||||
|
:~ [1 sec:ex:(pit:nu:crub:crypto 24 %foo)]
|
||||||
|
[2 sec]
|
||||||
|
==
|
||||||
|
%+ expect-eq
|
||||||
|
!> |+[%key-mismatch %life-mismatch ~]
|
||||||
|
!> (veri:dawn ~zod fed pot ~)
|
||||||
|
::
|
||||||
|
++ test-veri-none-multikey
|
||||||
|
%+ expect-eq
|
||||||
|
!> |+[%no-key ~]
|
||||||
|
!> (veri:dawn ~zod [[%1 ~] ~zod ~] pot ~)
|
||||||
::
|
::
|
||||||
++ test-veri-already-booted
|
++ test-veri-already-booted
|
||||||
=/ sed [~zod 1 sec ~]
|
=/ sed [~zod 1 sec ~]
|
||||||
;: weld
|
;: weld
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> `%already-booted
|
!> |+[%already-booted ~]
|
||||||
!> (veri:dawn sed pot `[1 |])
|
!> (veri:dawn ~zod sed pot `[1 |])
|
||||||
::
|
::
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> `%already-booted
|
!> |+[%already-booted ~]
|
||||||
!> (veri:dawn sed pot `[2 &])
|
!> (veri:dawn ~zod sed pot `[2 &])
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ test-veri-earl-good
|
++ test-veri-earl-good
|
||||||
@ -230,8 +246,8 @@
|
|||||||
(shaf %earl (sham who 1 pub:ex:cub))
|
(shaf %earl (sham who 1 pub:ex:cub))
|
||||||
[who 1 sec:ex:cub `sig]
|
[who 1 sec:ex:cub `sig]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> ~
|
!> &+sed
|
||||||
!> (veri:dawn sed pot ~)
|
!> (veri:dawn who sed pot ~)
|
||||||
::
|
::
|
||||||
++ test-veri-earl-parent-not-keyed
|
++ test-veri-earl-parent-not-keyed
|
||||||
=/ cub (pit:nu:crub:crypto 24 %foo)
|
=/ cub (pit:nu:crub:crypto 24 %foo)
|
||||||
@ -242,38 +258,38 @@
|
|||||||
(shaf %earl (sham who 1 pub:ex:cub))
|
(shaf %earl (sham who 1 pub:ex:cub))
|
||||||
[who 1 sec:ex:cub `sig]
|
[who 1 sec:ex:cub `sig]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> ~
|
!> &+sed
|
||||||
!> (veri:dawn sed =>(pot .(net ~)) ~)
|
!> (veri:dawn who sed =>(pot .(net ~)) ~)
|
||||||
::
|
::
|
||||||
++ test-veri-pawn-good
|
++ test-veri-pawn-good
|
||||||
=/ cub (pit:nu:crub:crypto 24 %foo)
|
=/ cub (pit:nu:crub:crypto 24 %foo)
|
||||||
=/ who=ship `@`fig:ex:cub
|
=/ who=ship `@`fig:ex:cub
|
||||||
=/ sed [who 1 sec:ex:cub ~]
|
=/ sed [who 1 sec:ex:cub ~]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> ~
|
!> &+sed
|
||||||
!> (veri:dawn sed *point:azimuth-types ~)
|
!> (veri:dawn who sed *point:azimuth-types ~)
|
||||||
::
|
::
|
||||||
++ test-veri-pawn-key-mismatch
|
++ test-veri-pawn-key-mismatch
|
||||||
=/ cub (pit:nu:crub:crypto 24 %foo)
|
=/ cub (pit:nu:crub:crypto 24 %foo)
|
||||||
=/ who=ship `@`fig:ex:cub
|
=/ who=ship `@`fig:ex:cub
|
||||||
=/ sed [who 1 sec:ex:(pit:nu:crub:crypto 24 %bar) ~]
|
=/ sed [who 1 sec:ex:(pit:nu:crub:crypto 24 %bar) ~]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> `%key-mismatch
|
!> |+[%key-mismatch ~]
|
||||||
!> (veri:dawn sed *point:azimuth-types ~)
|
!> (veri:dawn who sed *point:azimuth-types ~)
|
||||||
::
|
::
|
||||||
++ test-veri-pawn-invalid-life
|
++ test-veri-pawn-invalid-life
|
||||||
=/ cub (pit:nu:crub:crypto 24 %foo)
|
=/ cub (pit:nu:crub:crypto 24 %foo)
|
||||||
=/ who=ship `@`fig:ex:cub
|
=/ who=ship `@`fig:ex:cub
|
||||||
=/ sed [who 2 sec:ex:cub ~]
|
=/ sed [who 2 sec:ex:cub ~]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> `%invalid-life
|
!> |+[%invalid-life ~]
|
||||||
!> (veri:dawn sed *point:azimuth-types ~)
|
!> (veri:dawn who sed *point:azimuth-types ~)
|
||||||
::
|
::
|
||||||
++ test-veri-pawn-already-booted
|
++ test-veri-pawn-already-booted
|
||||||
=/ cub (pit:nu:crub:crypto 24 %foo)
|
=/ cub (pit:nu:crub:crypto 24 %foo)
|
||||||
=/ who=ship `@`fig:ex:cub
|
=/ who=ship `@`fig:ex:cub
|
||||||
=/ sed [who 1 sec:ex:cub ~]
|
=/ sed [who 1 sec:ex:cub ~]
|
||||||
%+ expect-eq
|
%+ expect-eq
|
||||||
!> `%already-booted
|
!> |+[%already-booted ~]
|
||||||
!> (veri:dawn sed *point:azimuth-types `[1 |])
|
!> (veri:dawn who sed *point:azimuth-types `[1 |])
|
||||||
--
|
--
|
||||||
|
@ -5,4 +5,4 @@ dojo:
|
|||||||
|
|
||||||
it should return with the following hash:
|
it should return with the following hash:
|
||||||
|
|
||||||
`0v7.v4dng.o33qi.kc497.5jc02.ke5es`
|
`0v2.ifoe4.fbv35.aigir.66su4.fbspu`
|
||||||
|
@ -241,11 +241,13 @@ export function uxToHex(ux: string) {
|
|||||||
|
|
||||||
export const hexToUx = (hex) => {
|
export const hexToUx = (hex) => {
|
||||||
const ux = f.flow(
|
const ux = f.flow(
|
||||||
|
f.reverse,
|
||||||
f.chunk(4),
|
f.chunk(4),
|
||||||
// eslint-disable-next-line prefer-arrow-callback
|
// eslint-disable-next-line prefer-arrow-callback
|
||||||
f.map(x => _.dropWhile(x, function(y: unknown) {
|
f.map(x => _.dropWhile(x, function(y: unknown) {
|
||||||
return y === 0;
|
return y === '0';
|
||||||
}).join('')),
|
}).reverse().join('')),
|
||||||
|
f.reverse,
|
||||||
f.join('.')
|
f.join('.')
|
||||||
)(hex.split(''));
|
)(hex.split(''));
|
||||||
return `0x${ux}`;
|
return `0x${ux}`;
|
||||||
|
@ -2,9 +2,9 @@ import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
|||||||
import { patp2dec } from 'urbit-ob';
|
import { patp2dec } from 'urbit-ob';
|
||||||
import shallow from 'zustand/shallow';
|
import shallow from 'zustand/shallow';
|
||||||
|
|
||||||
import { Association, deSig, GraphNode, Graphs, FlatGraphs, resourceFromPath, ThreadGraphs, getGraph, getShallowChildren } from '@urbit/api';
|
import { Association, deSig, GraphNode, Graphs, FlatGraphs, resourceFromPath, ThreadGraphs, getGraph, getShallowChildren, setScreen } from '@urbit/api';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { createState, createSubscription, reduceStateN } from './base';
|
import { createState, createSubscription, reduceStateN, pokeOptimisticallyN } from './base';
|
||||||
import airlock from '~/logic/api';
|
import airlock from '~/logic/api';
|
||||||
import { addDmMessage, addPost, Content, getDeepOlderThan, getFirstborn, getNewest, getNode, getOlderSiblings, getYoungerSiblings, markPending, Post, addNode, GraphNodePoke } from '@urbit/api/graph';
|
import { addDmMessage, addPost, Content, getDeepOlderThan, getFirstborn, getNewest, getNode, getOlderSiblings, getYoungerSiblings, markPending, Post, addNode, GraphNodePoke } from '@urbit/api/graph';
|
||||||
import { GraphReducer, reduceDm } from '../reducers/graph-update';
|
import { GraphReducer, reduceDm } from '../reducers/graph-update';
|
||||||
@ -35,8 +35,8 @@ export interface GraphState {
|
|||||||
getGraph: (ship: string, name: string) => Promise<void>;
|
getGraph: (ship: string, name: string) => Promise<void>;
|
||||||
addDmMessage: (ship: string, contents: Content[]) => Promise<void>;
|
addDmMessage: (ship: string, contents: Content[]) => Promise<void>;
|
||||||
addPost: (ship: string, name: string, post: Post) => Promise<void>;
|
addPost: (ship: string, name: string, post: Post) => Promise<void>;
|
||||||
|
|
||||||
addNode: (ship: string, name: string, post: GraphNodePoke) => Promise<void>;
|
addNode: (ship: string, name: string, post: GraphNodePoke) => Promise<void>;
|
||||||
|
setScreen: (screen: boolean) => void;
|
||||||
}
|
}
|
||||||
// @ts-ignore investigate zustand types
|
// @ts-ignore investigate zustand types
|
||||||
const useGraphState = createState<GraphState>('Graph', (set, get) => ({
|
const useGraphState = createState<GraphState>('Graph', (set, get) => ({
|
||||||
@ -145,6 +145,10 @@ const useGraphState = createState<GraphState>('Graph', (set, get) => ({
|
|||||||
const data = await airlock.scry(getShallowChildren(ship, name, index));
|
const data = await airlock.scry(getShallowChildren(ship, name, index));
|
||||||
data['graph-update'].fetch = true;
|
data['graph-update'].fetch = true;
|
||||||
GraphReducer(data);
|
GraphReducer(data);
|
||||||
|
},
|
||||||
|
setScreen: (screen: boolean) => {
|
||||||
|
const poke = setScreen(screen);
|
||||||
|
pokeOptimisticallyN(useGraphState, poke, reduceDm);
|
||||||
}
|
}
|
||||||
// getKeys: async () => {
|
// getKeys: async () => {
|
||||||
// const api = useApi();
|
// const api = useApi();
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
Timebox,
|
Timebox,
|
||||||
Unreads
|
Unreads
|
||||||
} from '@urbit/api';
|
} from '@urbit/api';
|
||||||
|
import { Poke } from '@urbit/http-api';
|
||||||
import { patp2dec } from 'urbit-ob';
|
import { patp2dec } from 'urbit-ob';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
||||||
@ -22,6 +23,7 @@ export const HARK_FETCH_MORE_COUNT = 3;
|
|||||||
export interface HarkState {
|
export interface HarkState {
|
||||||
archivedNotifications: BigIntOrderedMap<Timebox>;
|
archivedNotifications: BigIntOrderedMap<Timebox>;
|
||||||
doNotDisturb: boolean;
|
doNotDisturb: boolean;
|
||||||
|
poke: (poke: Poke<any>) => Promise<void>;
|
||||||
getMore: () => Promise<boolean>;
|
getMore: () => Promise<boolean>;
|
||||||
getSubset: (offset: number, count: number, isArchive: boolean) => Promise<void>;
|
getSubset: (offset: number, count: number, isArchive: boolean) => Promise<void>;
|
||||||
// getTimeSubset: (start?: Date, end?: Date) => Promise<void>;
|
// getTimeSubset: (start?: Date, end?: Date) => Promise<void>;
|
||||||
@ -42,6 +44,9 @@ const useHarkState = createState<HarkState>(
|
|||||||
archivedNotifications: new BigIntOrderedMap<Timebox>(),
|
archivedNotifications: new BigIntOrderedMap<Timebox>(),
|
||||||
doNotDisturb: false,
|
doNotDisturb: false,
|
||||||
unreadNotes: [],
|
unreadNotes: [],
|
||||||
|
poke: async (poke: Poke<any>) => {
|
||||||
|
await pokeOptimisticallyN(useHarkState, poke, [reduce]);
|
||||||
|
},
|
||||||
readCount: async (resource: string, index?: string) => {
|
readCount: async (resource: string, index?: string) => {
|
||||||
const poke = markCountAsRead(resource, index);
|
const poke = markCountAsRead(resource, index);
|
||||||
await pokeOptimisticallyN(useHarkState, poke, [reduce]);
|
await pokeOptimisticallyN(useHarkState, poke, [reduce]);
|
||||||
@ -68,7 +73,6 @@ const useHarkState = createState<HarkState>(
|
|||||||
});
|
});
|
||||||
reduceState(useHarkState, harkUpdate, [reduce]);
|
reduceState(useHarkState, harkUpdate, [reduce]);
|
||||||
},
|
},
|
||||||
|
|
||||||
notifications: new BigIntOrderedMap<Timebox>(),
|
notifications: new BigIntOrderedMap<Timebox>(),
|
||||||
notificationsCount: 0,
|
notificationsCount: 0,
|
||||||
notificationsGraphConfig: {
|
notificationsGraphConfig: {
|
||||||
|
@ -10,12 +10,14 @@ import {
|
|||||||
BaseState,
|
BaseState,
|
||||||
createState,
|
createState,
|
||||||
createSubscription,
|
createSubscription,
|
||||||
reduceStateN
|
reduceStateN,
|
||||||
|
pokeOptimisticallyN
|
||||||
} from '~/logic/state/base';
|
} from '~/logic/state/base';
|
||||||
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 } from '@urbit/api';
|
import { getAll, Value } from '@urbit/api';
|
||||||
|
import { putEntry } from '@urbit/api/settings';
|
||||||
|
|
||||||
export interface ShortcutMapping {
|
export interface ShortcutMapping {
|
||||||
cycleForward: string;
|
cycleForward: string;
|
||||||
@ -43,6 +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;
|
||||||
leap: {
|
leap: {
|
||||||
categories: LeapCategories[];
|
categories: LeapCategories[];
|
||||||
};
|
};
|
||||||
@ -102,6 +105,10 @@ const useSettingsState = createState<SettingsState>(
|
|||||||
get().set((s) => {
|
get().set((s) => {
|
||||||
Object.assign(s, all);
|
Object.assign(s, all);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
putEntry: (bucket: string, entry: string, value: Value) => {
|
||||||
|
const poke = putEntry(bucket, entry, value);
|
||||||
|
pokeOptimisticallyN(useSettingsState, poke, reduceUpdate);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
|
@ -6,7 +6,7 @@ import { Formik } from 'formik';
|
|||||||
import { ColorInput, ColorInputProps } from '~/views/components/ColorInput';
|
import { ColorInput, ColorInputProps } from '~/views/components/ColorInput';
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
color: '#33FF22'
|
color: '33FF22'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -136,7 +136,11 @@ const ChatEditor = React.forwardRef<CodeMirrorShim, ChatEditorProps>(({ inCodeMo
|
|||||||
setMessage
|
setMessage
|
||||||
} = useChatStore();
|
} = useChatStore();
|
||||||
|
|
||||||
function onKeyPress(e) {
|
const onKeyPress = (e: KeyboardEvent, editor: CodeMirrorShim) => {
|
||||||
|
if (!editor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const focusedTag = document.activeElement?.nodeName?.toLowerCase();
|
const focusedTag = document.activeElement?.nodeName?.toLowerCase();
|
||||||
const shouldCapture = !(focusedTag === 'textarea' || focusedTag === 'input' || e.metaKey || e.ctrlKey);
|
const shouldCapture = !(focusedTag === 'textarea' || focusedTag === 'input' || e.metaKey || e.ctrlKey);
|
||||||
if(/^[a-z]|[A-Z]$/.test(e.key) && shouldCapture) {
|
if(/^[a-z]|[A-Z]$/.test(e.key) && shouldCapture) {
|
||||||
@ -145,13 +149,14 @@ const ChatEditor = React.forwardRef<CodeMirrorShim, ChatEditorProps>(({ inCodeMo
|
|||||||
if(e.key === 'Escape') {
|
if(e.key === 'Escape') {
|
||||||
editor.getInputField().blur();
|
editor.getInputField().blur();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.addEventListener('keydown', onKeyPress);
|
const focusListener = (e: KeyboardEvent) => onKeyPress(e, editorRef.current);
|
||||||
|
document.addEventListener('keydown', focusListener);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('keydown', onKeyPress);
|
document.removeEventListener('keydown', focusListener);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -3,14 +3,12 @@ import {
|
|||||||
|
|
||||||
Text
|
Text
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { putEntry } from '@urbit/api/settings';
|
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { Form } from 'formik';
|
import { Form } from 'formik';
|
||||||
import useSettingsState, { SettingsState } from '~/logic/state/settings';
|
import useSettingsState, { SettingsState } from '~/logic/state/settings';
|
||||||
import { BackButton } from './BackButton';
|
import { BackButton } from './BackButton';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
|
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
|
||||||
import airlock from '~/logic/api';
|
|
||||||
|
|
||||||
interface FormSchema {
|
interface FormSchema {
|
||||||
hideAvatars: boolean;
|
hideAvatars: boolean;
|
||||||
@ -25,14 +23,14 @@ interface FormSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const settingsSel = (s: SettingsState): FormSchema => ({
|
const settingsSel = (s: SettingsState): FormSchema => ({
|
||||||
hideAvatars: s.calm.hideAvatars,
|
hideAvatars: s.calm.hideAvatars,
|
||||||
hideNicknames: s.calm.hideAvatars,
|
hideNicknames: s.calm.hideNicknames,
|
||||||
hideUnreads: s.calm.hideUnreads,
|
hideUnreads: s.calm.hideUnreads,
|
||||||
hideGroups: s.calm.hideGroups,
|
hideGroups: s.calm.hideGroups,
|
||||||
hideUtilities: s.calm.hideUtilities,
|
hideUtilities: s.calm.hideUtilities,
|
||||||
imageShown: !s.remoteContentPolicy.imageShown,
|
imageShown: !s.remoteContentPolicy.imageShown,
|
||||||
videoShown: !s.remoteContentPolicy.videoShown,
|
videoShown: !s.remoteContentPolicy.videoShown,
|
||||||
oembedShown: !s.remoteContentPolicy.oembedShown,
|
oembedShown: !s.remoteContentPolicy.oembedShown,
|
||||||
audioShown: !s.remoteContentPolicy.audioShown
|
audioShown: !s.remoteContentPolicy.audioShown
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -40,10 +38,11 @@ export function CalmPrefs() {
|
|||||||
const initialValues = useSettingsState(settingsSel);
|
const initialValues = useSettingsState(settingsSel);
|
||||||
|
|
||||||
const onSubmit = useCallback(async (v: FormSchema) => {
|
const onSubmit = useCallback(async (v: FormSchema) => {
|
||||||
|
const { putEntry } = useSettingsState.getState();
|
||||||
_.forEach(v, (bool, key) => {
|
_.forEach(v, (bool, key) => {
|
||||||
const bucket = ['imageShown', 'videoShown', 'audioShown', 'oembedShown'].includes(key) ? 'remoteContentPolicy' : 'calm';
|
const bucket = ['imageShown', 'videoShown', 'audioShown', 'oembedShown'].includes(key) ? 'remoteContentPolicy' : 'calm';
|
||||||
if(initialValues[key] !== bool) {
|
if(initialValues[key] !== bool) {
|
||||||
airlock.poke(putEntry(bucket, key, bool));
|
putEntry(bucket, key, bucket === 'calm' ? bool : !bool);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [initialValues]);
|
}, [initialValues]);
|
||||||
|
@ -5,15 +5,14 @@ import {
|
|||||||
Text
|
Text
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { Form } from 'formik';
|
import { Form } from 'formik';
|
||||||
import { putEntry } from '@urbit/api/settings';
|
import React, { useCallback } from 'react';
|
||||||
import React, { useMemo } from 'react';
|
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import { uxToHex } from '~/logic/lib/util';
|
import { uxToHex } from '~/logic/lib/util';
|
||||||
import useSettingsState, { selectSettingsState } from '~/logic/state/settings';
|
import useSettingsState, { SettingsState } from '~/logic/state/settings';
|
||||||
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
|
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
|
||||||
import { BackButton } from './BackButton';
|
import { BackButton } from './BackButton';
|
||||||
import airlock from '~/logic/api';
|
|
||||||
import { BackgroundPicker, BgType } from './BackgroundPicker';
|
import { BackgroundPicker, BgType } from './BackgroundPicker';
|
||||||
|
import shallow from 'zustand/shallow';
|
||||||
|
|
||||||
const formSchema = Yup.object().shape({
|
const formSchema = Yup.object().shape({
|
||||||
bgType: Yup.string()
|
bgType: Yup.string()
|
||||||
@ -30,59 +29,54 @@ interface FormSchema {
|
|||||||
bgUrl: string | undefined;
|
bgUrl: string | undefined;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
const emptyString = '';
|
||||||
|
|
||||||
const settingsSel = selectSettingsState(['display']);
|
const settingsSel = (s: SettingsState): FormSchema => {
|
||||||
|
const { display } = s;
|
||||||
|
let bgColor = emptyString;
|
||||||
|
let bgUrl = emptyString;
|
||||||
|
if (display.backgroundType === 'url') {
|
||||||
|
bgUrl = display.background;
|
||||||
|
}
|
||||||
|
if (display.backgroundType === 'color') {
|
||||||
|
bgColor = display.background;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
bgType: display.backgroundType,
|
||||||
|
bgColor,
|
||||||
|
bgUrl,
|
||||||
|
theme: display.theme
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default function DisplayForm() {
|
export default function DisplayForm() {
|
||||||
const {
|
const initialValues = useSettingsState(settingsSel, shallow);
|
||||||
display: { background, backgroundType, theme }
|
|
||||||
} = useSettingsState(settingsSel);
|
|
||||||
|
|
||||||
const initialValues: FormSchema = useMemo(() => {
|
const onSubmit = useCallback(async (values) => {
|
||||||
let bgColor, bgUrl;
|
const { putEntry } = useSettingsState.getState();
|
||||||
if (backgroundType === 'url') {
|
putEntry('display', 'backgroundType', values.bgType);
|
||||||
bgUrl = background;
|
putEntry(
|
||||||
}
|
'display',
|
||||||
if (backgroundType === 'color') {
|
'background',
|
||||||
bgColor = background;
|
values.bgType === 'color'
|
||||||
}
|
? `#${uxToHex(values.bgColor || '0x0')}`
|
||||||
return {
|
: values.bgType === 'url'
|
||||||
bgType: backgroundType,
|
? values.bgUrl || ''
|
||||||
bgColor: bgColor || '',
|
: false
|
||||||
bgUrl,
|
);
|
||||||
theme
|
putEntry('display', 'theme', values.theme);
|
||||||
};
|
}, []);
|
||||||
}, [backgroundType, background, theme]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormikOnBlur
|
<FormikOnBlur
|
||||||
validationSchema={formSchema}
|
validationSchema={formSchema}
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={async (values, actions) => {
|
onSubmit={onSubmit}
|
||||||
const promises = [] as Promise<any>[];
|
|
||||||
promises.push(
|
|
||||||
airlock.poke(putEntry('display', 'backgroundType', values.bgType))
|
|
||||||
);
|
|
||||||
promises.push(
|
|
||||||
airlock.poke(
|
|
||||||
putEntry(
|
|
||||||
'display',
|
|
||||||
'background',
|
|
||||||
values.bgType === 'color'
|
|
||||||
? `#${uxToHex(values.bgColor || '0x0')}`
|
|
||||||
: values.bgType === 'url'
|
|
||||||
? values.bgUrl || ''
|
|
||||||
: false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
promises.push(airlock.poke(putEntry('display', 'theme', values.theme)));
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Form>
|
<Form>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
<Col p={5} pt={4} gapY={5}>
|
<Col p={5} pt={4} gapY={5}>
|
||||||
<Col gapY={1} mt={0}>
|
<Col overflowY="auto" gapY={1} mt={0}>
|
||||||
<Text color="black" fontSize={2} fontWeight="medium">
|
<Text color="black" fontSize={2} fontWeight="medium">
|
||||||
Display Preferences
|
Display Preferences
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -4,22 +4,25 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
ManagedToggleSwitchField
|
ManagedToggleSwitchField
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { Form, Formik } from 'formik';
|
import { Form } from 'formik';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import useGraphState from '~/logic/state/graph';
|
import useGraphState, { GraphState } from '~/logic/state/graph';
|
||||||
import { AsyncButton } from '~/views/components/AsyncButton';
|
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
|
||||||
import airlock from '~/logic/api';
|
import shallow from 'zustand/shallow';
|
||||||
import { setScreen } from '@urbit/api/graph';
|
|
||||||
|
const selInit = (s: GraphState) => ({
|
||||||
|
accept: !s.screening
|
||||||
|
});
|
||||||
|
|
||||||
export function DmSettings() {
|
export function DmSettings() {
|
||||||
const screening = useGraphState(s => s.screening);
|
const initialValues = useGraphState(selInit, shallow);
|
||||||
const initialValues = { accept: !screening };
|
|
||||||
const onSubmit = useCallback(
|
const onSubmit = useCallback(
|
||||||
async (values, actions) => {
|
async (values, actions) => {
|
||||||
await airlock.poke(setScreen(!values.accept));
|
const { setScreen } = useGraphState.getState();
|
||||||
|
setScreen(!values.accept);
|
||||||
actions.setStatus({ success: null });
|
actions.setStatus({ success: null });
|
||||||
},
|
},
|
||||||
[screening]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -38,7 +41,7 @@ export function DmSettings() {
|
|||||||
<Box mb="4" fontWeight="medium" fontSize="1" color="gray">
|
<Box mb="4" fontWeight="medium" fontSize="1" color="gray">
|
||||||
Direct Messages
|
Direct Messages
|
||||||
</Box>
|
</Box>
|
||||||
<Formik initialValues={initialValues} onSubmit={onSubmit}>
|
<FormikOnBlur initialValues={initialValues} onSubmit={onSubmit}>
|
||||||
<Form>
|
<Form>
|
||||||
<Col gapY="4">
|
<Col gapY="4">
|
||||||
<ManagedToggleSwitchField
|
<ManagedToggleSwitchField
|
||||||
@ -46,12 +49,9 @@ export function DmSettings() {
|
|||||||
label="Auto-accept DM invites"
|
label="Auto-accept DM invites"
|
||||||
caption="Direct messages will be automatically joined, and you wil see any messages sent in notifications"
|
caption="Direct messages will be automatically joined, and you wil see any messages sent in notifications"
|
||||||
/>
|
/>
|
||||||
<AsyncButton width="fit-content" primary>
|
|
||||||
Save Changes
|
|
||||||
</AsyncButton>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Form>
|
</Form>
|
||||||
</Formik>
|
</FormikOnBlur>
|
||||||
</Col>
|
</Col>
|
||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
|
@ -101,20 +101,19 @@ function Channel(props: { association: Association }) {
|
|||||||
return isWatching(config, association.resource);
|
return isWatching(config, association.resource);
|
||||||
});
|
});
|
||||||
|
|
||||||
const [, , { setValue, setTouched }] = useField(
|
const [{ value }, , { setValue, setTouched }] = useField(
|
||||||
`graph["${association.resource}"]`
|
`graph["${association.resource}"]`
|
||||||
);
|
);
|
||||||
const [optValue, setOptValue] = useState(watching);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setValue(optValue);
|
|
||||||
setTouched(true);
|
|
||||||
}, [watching]);
|
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
setOptValue(v => !v);
|
setValue(!value);
|
||||||
|
setTouched(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setValue(watching);
|
||||||
|
}, [watching]);
|
||||||
|
|
||||||
const icon = getModuleIcon((metadata.config as GraphConfig)?.graph as GraphModule);
|
const icon = getModuleIcon((metadata.config as GraphConfig)?.graph as GraphModule);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -126,7 +125,7 @@ function Channel(props: { association: Association }) {
|
|||||||
<Text> {metadata.title}</Text>
|
<Text> {metadata.title}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box gridColumn={4}>
|
<Box gridColumn={4}>
|
||||||
<StatelessToggleSwitchField selected={optValue} onClick={onClick} />
|
<StatelessToggleSwitchField selected={value} onClick={onClick} />
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -11,9 +11,15 @@ import useHarkState from '~/logic/state/hark';
|
|||||||
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
|
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
|
||||||
import { BackButton } from './BackButton';
|
import { BackButton } from './BackButton';
|
||||||
import { GroupChannelPicker } from './GroupChannelPicker';
|
import { GroupChannelPicker } from './GroupChannelPicker';
|
||||||
import airlock from '~/logic/api';
|
import {
|
||||||
import { ignoreGraph, ignoreGroup, listenGraph, listenGroup, setDoNotDisturb, setMentions } from '@urbit/api';
|
setMentions,
|
||||||
import { setWatchOnSelf } from '@urbit/api';
|
setWatchOnSelf,
|
||||||
|
setDoNotDisturb,
|
||||||
|
listenGraph,
|
||||||
|
listenGroup,
|
||||||
|
ignoreGraph,
|
||||||
|
ignoreGroup
|
||||||
|
} from '@urbit/api';
|
||||||
|
|
||||||
interface FormSchema {
|
interface FormSchema {
|
||||||
mentions: boolean;
|
mentions: boolean;
|
||||||
@ -39,28 +45,26 @@ export function NotificationPreferences() {
|
|||||||
|
|
||||||
const onSubmit = useCallback(async (values: FormSchema, actions: FormikHelpers<FormSchema>) => {
|
const onSubmit = useCallback(async (values: FormSchema, actions: FormikHelpers<FormSchema>) => {
|
||||||
try {
|
try {
|
||||||
const promises: Promise<any>[] = [];
|
const { poke } = useHarkState.getState();
|
||||||
if (values.mentions !== graphConfig.mentions) {
|
if (values.mentions !== graphConfig.mentions) {
|
||||||
promises.push(airlock.poke(setMentions(values.mentions)));
|
poke(setMentions(values.mentions));
|
||||||
}
|
}
|
||||||
if (values.watchOnSelf !== graphConfig.watchOnSelf) {
|
if (values.watchOnSelf !== graphConfig.watchOnSelf) {
|
||||||
promises.push(airlock.poke(setWatchOnSelf(values.watchOnSelf)));
|
poke(setWatchOnSelf(values.watchOnSelf));
|
||||||
}
|
}
|
||||||
if (values.dnd !== dnd && !_.isUndefined(values.dnd)) {
|
if (values.dnd !== dnd && !_.isUndefined(values.dnd)) {
|
||||||
promises.push(airlock.poke(setDoNotDisturb(values.dnd)));
|
poke(setDoNotDisturb(values.dnd));
|
||||||
}
|
}
|
||||||
_.forEach(values.graph, (listen: boolean, graph: string) => {
|
_.forEach(values.graph, (listen: boolean, graph: string) => {
|
||||||
if(listen !== isWatching(graphConfig, graph)) {
|
if(listen !== isWatching(graphConfig, graph)) {
|
||||||
promises.push(airlock.poke((listen ? listenGraph : ignoreGraph)(graph, '/')));
|
poke((listen ? listenGraph : ignoreGraph)(graph, '/'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_.forEach(values.groups, (listen: boolean, group: string) => {
|
_.forEach(values.groups, (listen: boolean, group: string) => {
|
||||||
if(listen !== groupConfig.includes(group)) {
|
if(listen !== groupConfig.includes(group)) {
|
||||||
promises.push(airlock.poke((listen ? listenGroup : ignoreGroup)(group)));
|
poke((listen ? listenGroup : ignoreGroup)(group));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
actions.setStatus({ success: null });
|
actions.setStatus({ success: null });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
@ -7,8 +7,9 @@ import {
|
|||||||
StatelessTextInput as Input
|
StatelessTextInput as Input
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { useField } from 'formik';
|
import { useField } from 'formik';
|
||||||
import React, { FormEvent } from 'react';
|
import React, { FormEvent, useState, useEffect } from 'react';
|
||||||
import { hexToUx } from '~/logic/lib/util';
|
import { hexToUx } from '~/logic/lib/util';
|
||||||
|
import { uxToHex } from '@urbit/api/dist';
|
||||||
|
|
||||||
export type ColorInputProps = Parameters<typeof Col>[0] & {
|
export type ColorInputProps = Parameters<typeof Col>[0] & {
|
||||||
id: string;
|
id: string;
|
||||||
@ -17,24 +18,39 @@ export type ColorInputProps = Parameters<typeof Col>[0] & {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const COLOR_REGEX = /^(\d|[a-f]|[A-F]){6}$/;
|
||||||
|
|
||||||
|
function padHex(hex: string) {
|
||||||
|
if(hex.length === 0) {
|
||||||
|
return '000000';
|
||||||
|
}
|
||||||
|
const repeat = 6 / hex.length;
|
||||||
|
if(Math.floor(repeat) === repeat) {
|
||||||
|
return hex.repeat(repeat);
|
||||||
|
}
|
||||||
|
if(hex.length < 6) {
|
||||||
|
return hex.slice(0,3).repeat(2);
|
||||||
|
}
|
||||||
|
return hex.slice(0,6);
|
||||||
|
}
|
||||||
|
|
||||||
export function ColorInput(props: ColorInputProps) {
|
export function ColorInput(props: ColorInputProps) {
|
||||||
const { id, placeholder, label, caption, disabled, ...rest } = props;
|
const { id, placeholder, label, caption, disabled, ...rest } = props;
|
||||||
const [{ value, onBlur }, meta, { setValue }] = useField(id);
|
const [{ value, onBlur }, meta, { setValue, setTouched }] = useField(id);
|
||||||
|
const [field, setField] = useState(uxToHex(value));
|
||||||
|
|
||||||
const hex = value.replace('#', '').replace('0x', '').replace('.', '');
|
useEffect(() => {
|
||||||
const padded = hex.padStart(6, '0');
|
const newValue = hexToUx(padHex(field));
|
||||||
|
setValue(newValue);
|
||||||
|
setTouched(true);
|
||||||
|
}, [field]);
|
||||||
|
|
||||||
const onChange = (e: FormEvent<HTMLInputElement>) => {
|
const onChange = (e: FormEvent<HTMLInputElement>) => {
|
||||||
let { value: newValue } = e.target as HTMLInputElement;
|
const { value: newValue } = e.target as HTMLInputElement;
|
||||||
newValue = newValue.replace('#', '');
|
setField(newValue.slice(1));
|
||||||
const valid = newValue.match(/^(\d|[a-f]|[A-F]){0,6}$/);
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const result = hexToUx(newValue);
|
|
||||||
setValue(result);
|
|
||||||
};
|
};
|
||||||
|
const hex = uxToHex(value);
|
||||||
|
const isValid = COLOR_REGEX.test(hex);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box display='flex' flexDirection='column' {...rest}>
|
<Box display='flex' flexDirection='column' {...rest}>
|
||||||
@ -51,7 +67,7 @@ export function ColorInput(props: ColorInputProps) {
|
|||||||
borderBottomRightRadius={0}
|
borderBottomRightRadius={0}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
value={hex}
|
value={field}
|
||||||
disabled={disabled || false}
|
disabled={disabled || false}
|
||||||
borderRight={0}
|
borderRight={0}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
@ -64,18 +80,17 @@ export function ColorInput(props: ColorInputProps) {
|
|||||||
borderColor='lightGray'
|
borderColor='lightGray'
|
||||||
width='32px'
|
width='32px'
|
||||||
alignSelf='stretch'
|
alignSelf='stretch'
|
||||||
bg={`#${padded}`}
|
bg={isValid ? `#${hex}` : 'transparent'}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
width='100%'
|
width='100%'
|
||||||
height='100%'
|
height='100%'
|
||||||
alignSelf='stretch'
|
alignSelf='stretch'
|
||||||
onChange={onChange}
|
|
||||||
value={padded}
|
|
||||||
disabled={disabled || false}
|
disabled={disabled || false}
|
||||||
type='color'
|
type='color'
|
||||||
opacity={0}
|
opacity={0}
|
||||||
overflow='hidden'
|
overflow='hidden'
|
||||||
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -1,35 +1,28 @@
|
|||||||
import { FormikConfig, FormikProvider, FormikValues, useFormik } from 'formik';
|
import { FormikConfig, FormikProvider, FormikValues, useFormik } from 'formik';
|
||||||
import React, { useEffect, useImperativeHandle, useState } from 'react';
|
import React, { useEffect, useImperativeHandle, useCallback } from 'react';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
export function FormikOnBlur<
|
export function FormikOnBlur<
|
||||||
Values extends FormikValues = FormikValues,
|
Values extends FormikValues = FormikValues,
|
||||||
ExtraProps = {}
|
ExtraProps = {}
|
||||||
>(props: FormikConfig<Values> & ExtraProps) {
|
>(props: FormikConfig<Values> & ExtraProps) {
|
||||||
const formikBag = useFormik<Values>({ ...props, validateOnBlur: true });
|
const formikBag = useFormik<Values>({ ...props, validateOnBlur: true });
|
||||||
const [submitting, setSubmitting] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
const trySubmit = useCallback(_.debounce((formikBag) => {
|
||||||
if (
|
if (
|
||||||
Object.keys(formikBag.errors || {}).length === 0 &&
|
Object.keys(formikBag.errors || {}).length === 0 &&
|
||||||
formikBag.dirty &&
|
formikBag.dirty &&
|
||||||
!formikBag.isSubmitting &&
|
!formikBag.isSubmitting
|
||||||
!submitting
|
|
||||||
) {
|
) {
|
||||||
setSubmitting(true);
|
formikBag.submitForm();
|
||||||
const { values } = formikBag;
|
|
||||||
formikBag.validateForm(values)
|
|
||||||
.then(valid => valid ?
|
|
||||||
formikBag.submitForm().then(() => {
|
|
||||||
formikBag.resetForm({ values });
|
|
||||||
setSubmitting(false);
|
|
||||||
}) : null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}, 100), []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
trySubmit(formikBag);
|
||||||
}, [
|
}, [
|
||||||
formikBag.errors,
|
formikBag.values,
|
||||||
formikBag.dirty,
|
formikBag.errors
|
||||||
submitting,
|
|
||||||
formikBag.isSubmitting
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
BaseInput, Box,
|
BaseInput,
|
||||||
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Icon, Label, Row, StatelessTextInput as Input,
|
Icon,
|
||||||
Text
|
Label,
|
||||||
|
Row,
|
||||||
|
StatelessTextInput as Input,
|
||||||
|
Text,
|
||||||
|
ErrorLabel
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { useField } from 'formik';
|
import { useField } from 'formik';
|
||||||
import React, { ReactElement, useCallback, useRef, useState } from 'react';
|
import React, { ReactElement, useCallback, useRef, useState } from 'react';
|
||||||
@ -20,23 +25,19 @@ const prompt = (
|
|||||||
uploading,
|
uploading,
|
||||||
meta,
|
meta,
|
||||||
clickUploadButton,
|
clickUploadButton,
|
||||||
canUpload
|
canUpload,
|
||||||
|
error
|
||||||
) => {
|
) => {
|
||||||
if (
|
if (!focus && !field.value && !uploading && error === undefined) {
|
||||||
!focus &&
|
|
||||||
!field.value &&
|
|
||||||
!uploading &&
|
|
||||||
meta.error === undefined
|
|
||||||
) {
|
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
color='black'
|
color="black"
|
||||||
fontWeight='500'
|
fontWeight="500"
|
||||||
position='absolute'
|
position="absolute"
|
||||||
left={2}
|
left={2}
|
||||||
display='flex'
|
display="flex"
|
||||||
height='100%'
|
height="100%"
|
||||||
alignItems='center'
|
alignItems="center"
|
||||||
lineHeight={1}
|
lineHeight={1}
|
||||||
style={{ pointerEvents: 'none' }}
|
style={{ pointerEvents: 'none' }}
|
||||||
onSelect={e => e.preventDefault}
|
onSelect={e => e.preventDefault}
|
||||||
@ -50,7 +51,7 @@ const prompt = (
|
|||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
color="blue"
|
color="blue"
|
||||||
style={{ pointerEvents: 'all' }}
|
style={{ pointerEvents: 'all' }}
|
||||||
mx='0.5ch'
|
mx="0.5ch"
|
||||||
onClick={clickUploadButton}
|
onClick={clickUploadButton}
|
||||||
>
|
>
|
||||||
upload
|
upload
|
||||||
@ -70,9 +71,9 @@ const uploadingStatus = (uploading, meta) => {
|
|||||||
<Text
|
<Text
|
||||||
position="absolute"
|
position="absolute"
|
||||||
left={2}
|
left={2}
|
||||||
display='flex'
|
display="flex"
|
||||||
height='100%'
|
height="100%"
|
||||||
alignItems='center'
|
alignItems="center"
|
||||||
lineHeight={1}
|
lineHeight={1}
|
||||||
gray
|
gray
|
||||||
onSelect={e => e.preventDefault}
|
onSelect={e => e.preventDefault}
|
||||||
@ -84,27 +85,27 @@ const uploadingStatus = (uploading, meta) => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const errorRetry = (meta, focus, uploading, clickUploadButton) => {
|
const errorRetry = (meta, error, focus, uploading, clickUploadButton) => {
|
||||||
if (!focus && meta.error !== undefined) {
|
if (!focus && error !== undefined && meta.touched) {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
position="absolute"
|
position="absolute"
|
||||||
left={2}
|
left={2}
|
||||||
display='flex'
|
display="flex"
|
||||||
height='100%'
|
height="100%"
|
||||||
alignItems='center'
|
alignItems="center"
|
||||||
lineHeight={1}
|
lineHeight={1}
|
||||||
color='red'
|
color="red"
|
||||||
style={{ pointerEvents: 'none' }}
|
style={{ pointerEvents: 'none' }}
|
||||||
onSelect={e => e.preventDefault}
|
onSelect={e => e.preventDefault}
|
||||||
>
|
>
|
||||||
{meta.error}
|
{error}
|
||||||
{', '}please{' '}
|
{', '}please{' '}
|
||||||
<Text
|
<Text
|
||||||
fontWeight='500'
|
fontWeight="500"
|
||||||
cursor='pointer'
|
cursor="pointer"
|
||||||
color='blue'
|
color="blue"
|
||||||
mx='0.5ch'
|
mx="0.5ch"
|
||||||
style={{ pointerEvents: 'all' }}
|
style={{ pointerEvents: 'all' }}
|
||||||
onClick={clickUploadButton}
|
onClick={clickUploadButton}
|
||||||
>
|
>
|
||||||
@ -143,7 +144,8 @@ export const clearButton = (field, uploading, clearEvt) => {
|
|||||||
export function ImageInput(props: ImageInputProps): ReactElement {
|
export function ImageInput(props: ImageInputProps): ReactElement {
|
||||||
const { id, label, caption } = props;
|
const { id, label, caption } = props;
|
||||||
const { uploadDefault, canUpload, uploading } = useStorage();
|
const { uploadDefault, canUpload, uploading } = useStorage();
|
||||||
const [field, meta, { setValue, setError }] = useField(id);
|
const [field, meta, { setValue, setTouched }] = useField(id);
|
||||||
|
const [uploadError, setUploadError] = useState();
|
||||||
const [focus, setFocus] = useState(false);
|
const [focus, setFocus] = useState(false);
|
||||||
const ref = useRef<HTMLInputElement | null>(null);
|
const ref = useRef<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
@ -170,9 +172,10 @@ export function ImageInput(props: ImageInputProps): ReactElement {
|
|||||||
const url = await uploadDefault(file);
|
const url = await uploadDefault(file);
|
||||||
setFocus(false);
|
setFocus(false);
|
||||||
setValue(url);
|
setValue(url);
|
||||||
|
setTouched(true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setFocus(false);
|
setFocus(false);
|
||||||
setError(e.message);
|
setUploadError(e);
|
||||||
}
|
}
|
||||||
}, [ref.current, uploadDefault, canUpload, setValue]);
|
}, [ref.current, uploadDefault, canUpload, setValue]);
|
||||||
|
|
||||||
@ -184,19 +187,19 @@ export function ImageInput(props: ImageInputProps): ReactElement {
|
|||||||
{caption}
|
{caption}
|
||||||
</Label>
|
</Label>
|
||||||
) : null}
|
) : null}
|
||||||
<Row mt={2} alignItems="flex-end" position='relative' width='100%'>
|
<Row mt={2} alignItems="flex-end" position="relative" width="100%">
|
||||||
{prompt(field, focus, uploading, meta, clickUploadButton, canUpload)}
|
{prompt(field, focus, uploading, meta, clickUploadButton, canUpload, uploadError)}
|
||||||
{clearButton(field, uploading, clearEvt)}
|
{clearButton(field, uploading, clearEvt)}
|
||||||
{uploadingStatus(uploading, meta)}
|
{uploadingStatus(uploading, meta)}
|
||||||
{errorRetry(meta, focus, uploading, clickUploadButton)}
|
{errorRetry(meta, uploadError, focus, uploading, clickUploadButton)}
|
||||||
<Box background='white' borderRadius={2} width='100%'>
|
<Box background="white" borderRadius={2} width="100%">
|
||||||
<Input
|
<Input
|
||||||
{...field}
|
{...field}
|
||||||
width='100%'
|
width="100%"
|
||||||
type={'text'}
|
type={'text'}
|
||||||
onFocus={() => setFocus(true)}
|
onFocus={() => setFocus(true)}
|
||||||
onBlur={e => handleBlur(e)}
|
onBlur={e => handleBlur(e)}
|
||||||
hasError={meta.touched && meta.error !== undefined}
|
hasError={Boolean(uploadError)}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
{canUpload && (
|
{canUpload && (
|
||||||
@ -213,6 +216,9 @@ export function ImageInput(props: ImageInputProps): ReactElement {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
|
<ErrorLabel mt="2" hasError={Boolean(meta.touched && meta.error)}>
|
||||||
|
{meta.error}
|
||||||
|
</ErrorLabel>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
|
|
||||||
Text
|
Text
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { addTag, Association, Group, metadataUpdate, PermVariation, removeTag } from '@urbit/api';
|
import { addTag, Association, Group, PermVariation, removeTag, metadataEdit } from '@urbit/api';
|
||||||
import { Form, Formik } from 'formik';
|
import { Form, Formik } from 'formik';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -107,7 +107,7 @@ export function GraphPermissions(props: GraphPermissionsProps) {
|
|||||||
};
|
};
|
||||||
const allWriters = Array.from(writers).map(w => `~${w}`);
|
const allWriters = Array.from(writers).map(w => `~${w}`);
|
||||||
if (values.readerComments !== readerComments) {
|
if (values.readerComments !== readerComments) {
|
||||||
await airlock.poke(metadataUpdate(association, {
|
await airlock.poke(metadataEdit(association, {
|
||||||
vip: values.readerComments ? 'reader-comments' : ''
|
vip: values.readerComments ? 'reader-comments' : ''
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@ import {
|
|||||||
Label, ManagedTextInputField as Input,
|
Label, ManagedTextInputField as Input,
|
||||||
Text
|
Text
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { Association, metadataUpdate } from '@urbit/api';
|
import _ from 'lodash';
|
||||||
|
import { Association, metadataEdit } from '@urbit/api';
|
||||||
import { Form, Formik } from 'formik';
|
import { Form, Formik } from 'formik';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { uxToHex } from '~/logic/lib/util';
|
import { uxToHex } from '~/logic/lib/util';
|
||||||
@ -32,9 +33,13 @@ export function ChannelDetails(props: ChannelDetailsProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = async (values: FormSchema, actions) => {
|
const onSubmit = async (values: FormSchema, actions) => {
|
||||||
const { title, description } = values;
|
values.color = uxToHex(values.color);
|
||||||
const color = uxToHex(values.color);
|
const promises = _.compact(_.map(values, (value,k) => {
|
||||||
await airlock.poke(metadataUpdate(association, { title, color, description }));
|
return value !== initialValues[k]
|
||||||
|
? airlock.poke(metadataEdit(association, { [k]: value }))
|
||||||
|
: null;
|
||||||
|
}));
|
||||||
|
await Promise.all(promises);
|
||||||
actions.setStatus({ success: null });
|
actions.setStatus({ success: null });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
leaveGraph,
|
leaveGraph,
|
||||||
metadataRemove
|
metadataRemove
|
||||||
} from '@urbit/api';
|
} from '@urbit/api';
|
||||||
import React, { useCallback, useRef } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { isChannelAdmin, isHost } from '~/logic/lib/group';
|
import { isChannelAdmin, isHost } from '~/logic/lib/group';
|
||||||
import { useHashLink } from '~/logic/lib/useHashLink';
|
import { useHashLink } from '~/logic/lib/useHashLink';
|
||||||
@ -31,7 +31,6 @@ interface ChannelPopoverRoutesProps {
|
|||||||
export function ChannelPopoverRoutes(props: ChannelPopoverRoutesProps) {
|
export function ChannelPopoverRoutes(props: ChannelPopoverRoutesProps) {
|
||||||
const { association, group } = props;
|
const { association, group } = props;
|
||||||
useHashLink();
|
useHashLink();
|
||||||
const overlayRef = useRef<HTMLElement>();
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const onDismiss = useCallback(() => {
|
const onDismiss = useCallback(() => {
|
||||||
@ -63,7 +62,6 @@ export function ChannelPopoverRoutes(props: ChannelPopoverRoutesProps) {
|
|||||||
height="100%"
|
height="100%"
|
||||||
width="100%"
|
width="100%"
|
||||||
spacing={[3, 5, 7]}
|
spacing={[3, 5, 7]}
|
||||||
ref={overlayRef}
|
|
||||||
dismiss={onDismiss}
|
dismiss={onDismiss}
|
||||||
>
|
>
|
||||||
<Row
|
<Row
|
||||||
|
@ -4,9 +4,10 @@ import {
|
|||||||
ManagedToggleSwitchField as Checkbox,
|
ManagedToggleSwitchField as Checkbox,
|
||||||
Text
|
Text
|
||||||
} from '@tlon/indigo-react';
|
} from '@tlon/indigo-react';
|
||||||
import { changePolicy, Enc, metadataUpdate } from '@urbit/api';
|
import _ from 'lodash';
|
||||||
|
import { changePolicy, Enc } from '@urbit/api';
|
||||||
import { Group, GroupPolicy } from '@urbit/api/groups';
|
import { Group, GroupPolicy } from '@urbit/api/groups';
|
||||||
import { Association } from '@urbit/api/metadata';
|
import { Association, metadataEdit, MetadataEditField } from '@urbit/api/metadata';
|
||||||
import { Form, Formik, FormikHelpers } from 'formik';
|
import { Form, Formik, FormikHelpers } from 'formik';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
@ -58,16 +59,26 @@ export function GroupAdminSettings(props: GroupAdminSettingsProps) {
|
|||||||
actions: FormikHelpers<FormSchema>
|
actions: FormikHelpers<FormSchema>
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
const { title, description, picture, color, isPrivate, adminMetadata } = values;
|
const { color, isPrivate, adminMetadata } = values;
|
||||||
|
const update = (upd: MetadataEditField) =>
|
||||||
|
airlock.poke(metadataEdit(association, upd));
|
||||||
|
|
||||||
const uxColor = uxToHex(color);
|
const uxColor = uxToHex(color);
|
||||||
const vip = adminMetadata ? '' : 'member-metadata';
|
const vip = adminMetadata ? '' : 'member-metadata';
|
||||||
await airlock.poke(metadataUpdate(props.association, {
|
const promises = _.compact(_.map(['title', 'description', 'picture'] as const,
|
||||||
title,
|
(k) => {
|
||||||
description,
|
const edit: MetadataEditField = { [k]: values[k] };
|
||||||
picture,
|
return (values[k] !== initialValues[k])
|
||||||
color: uxColor,
|
? update(edit)
|
||||||
vip
|
: null;
|
||||||
}));
|
}));
|
||||||
|
if(vip !== metadata.vip) {
|
||||||
|
promises.push(update({ vip }));
|
||||||
|
}
|
||||||
|
if(uxColor !== metadata.color) {
|
||||||
|
promises.push(update({ color: uxColor }));
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
if (isPrivate !== currentPrivate) {
|
if (isPrivate !== currentPrivate) {
|
||||||
const resource = resourceFromPath(props.association.group);
|
const resource = resourceFromPath(props.association.group);
|
||||||
const newPolicy: Enc<GroupPolicy> = isPrivate
|
const newPolicy: Enc<GroupPolicy> = isPrivate
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Col, Icon, Row, Text } from '@tlon/indigo-react';
|
import { Col, Icon, Row, Text } from '@tlon/indigo-react';
|
||||||
import { Association, Group, metadataRemove, metadataUpdate } from '@urbit/api';
|
import { Association, Group, metadataRemove, metadataEdit } from '@urbit/api';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { resourceFromPath, roleForShip } from '~/logic/lib/group';
|
import { resourceFromPath, roleForShip } from '~/logic/lib/group';
|
||||||
import { getModuleIcon, GraphModule } from '~/logic/lib/util';
|
import { getModuleIcon, GraphModule } from '~/logic/lib/util';
|
||||||
@ -22,7 +22,8 @@ export function GroupChannelSettings(props: GroupChannelSettingsProps) {
|
|||||||
|
|
||||||
const onChange = useCallback(
|
const onChange = useCallback(
|
||||||
async (resource: string, preview: boolean) => {
|
async (resource: string, preview: boolean) => {
|
||||||
await airlock.poke(metadataUpdate(associations.graph[resource], { preview }));
|
const association = associations.graph[resource];
|
||||||
|
await airlock.poke(metadataEdit(association, { preview }));
|
||||||
},
|
},
|
||||||
[associations.graph]
|
[associations.graph]
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { BaseLabel, Col, Label, Text } from '@tlon/indigo-react';
|
import { BaseLabel, Col, Label, Text } from '@tlon/indigo-react';
|
||||||
import { Association, createGroupFeed, disableGroupFeed, Group, metadataUpdate, PermVariation, resourceFromPath } from '@urbit/api';
|
import { Association, createGroupFeed, disableGroupFeed, Group, metadataEdit, PermVariation, resourceFromPath } from '@urbit/api';
|
||||||
import { Form, Formik, FormikHelpers } from 'formik';
|
import { Form, Formik, FormikHelpers } from 'formik';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
@ -46,7 +46,11 @@ export function GroupFeedSettings(props: {
|
|||||||
values: FormSchema,
|
values: FormSchema,
|
||||||
actions: FormikHelpers<FormSchema>
|
actions: FormikHelpers<FormSchema>
|
||||||
) => {
|
) => {
|
||||||
await airlock.poke(metadataUpdate(feedAssoc, { vip: values.permissions.trim() as PermVariation }));
|
await airlock.poke(
|
||||||
|
metadataEdit(feedAssoc, {
|
||||||
|
vip: values.permissions.trim() as PermVariation
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
actions.setStatus({ success: null });
|
actions.setStatus({ success: null });
|
||||||
};
|
};
|
||||||
|
@ -400,7 +400,8 @@ export const getNewest = (
|
|||||||
index = ''
|
index = ''
|
||||||
): Scry => ({
|
): Scry => ({
|
||||||
app: 'graph-store',
|
app: 'graph-store',
|
||||||
path: `/newest/${ship}/${name}/${count}${encodeIndex(index)}`
|
path: `/graph/${ship}/${name}/node/siblings` +
|
||||||
|
`/newest/lone/${count}${encodeIndex(index)}`
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -419,7 +420,7 @@ export const getOlderSiblings = (
|
|||||||
index: string
|
index: string
|
||||||
): Scry => ({
|
): Scry => ({
|
||||||
app: 'graph-store',
|
app: 'graph-store',
|
||||||
path: `/node-siblings/older/${ship}/${name}/${count}${encodeIndex(index)}`
|
path: `/graph/${ship}/${name}/node/siblings/older/lone/${count}${encodeIndex(index)}`
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -438,7 +439,7 @@ export const getYoungerSiblings = (
|
|||||||
index: string
|
index: string
|
||||||
): Scry => ({
|
): Scry => ({
|
||||||
app: 'graph-store',
|
app: 'graph-store',
|
||||||
path: `/node-siblings/younger/${ship}/${name}/${count}${encodeIndex(index)}`
|
path: `/graph/${ship}/${name}/node/siblings/newer/lone/${count}${encodeIndex(index)}`
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -450,7 +451,7 @@ export const getYoungerSiblings = (
|
|||||||
*/
|
*/
|
||||||
export const getShallowChildren = (ship: string, name: string, index = '') => ({
|
export const getShallowChildren = (ship: string, name: string, index = '') => ({
|
||||||
app: 'graph-store',
|
app: 'graph-store',
|
||||||
path: `/shallow-children/${ship}/${name}${encodeIndex(index)}`
|
path: `/graph/${ship}/${name}/node/children/lone/~/~${encodeIndex(index)}`
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -467,10 +468,12 @@ export const getDeepOlderThan = (
|
|||||||
ship: string,
|
ship: string,
|
||||||
name: string,
|
name: string,
|
||||||
count: number,
|
count: number,
|
||||||
start?: string
|
start = ''
|
||||||
) => ({
|
) => ({
|
||||||
app: 'graph-store',
|
app: 'graph-store',
|
||||||
path: `/deep-nodes-older-than/${ship}/${name}/${count}/${start ? decToUd(start) : 'null'}`
|
path: `/graph/${ship}/${name}/node/siblings` +
|
||||||
|
`/${start.length > 0 ? 'older' : 'oldest'}` +
|
||||||
|
`/kith/${count}${encodeIndex(start)}`
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -487,7 +490,7 @@ export const getFirstborn = (
|
|||||||
index: string
|
index: string
|
||||||
): Scry => ({
|
): Scry => ({
|
||||||
app: 'graph-store',
|
app: 'graph-store',
|
||||||
path: `/firstborn/${ship}/${name}${encodeIndex(index)}`
|
path: `/graph/${ship}/${name}/node/firstborn${encodeIndex(index)}`
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -504,7 +507,7 @@ export const getNode = (
|
|||||||
index: string
|
index: string
|
||||||
): Scry => ({
|
): Scry => ({
|
||||||
app: 'graph-store',
|
app: 'graph-store',
|
||||||
path: `/node/${ship}/${name}${encodeIndex(index)}`
|
path: `/graph/${ship}/${name}/node/index/kith${encodeIndex(index)}`
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { AppName, Path, Poke, uxToHex, PatpNoSig } from '../lib';
|
import { AppName, Path, Poke, uxToHex, PatpNoSig } from '../lib';
|
||||||
import { Association, Metadata, MetadataUpdate, MetadataUpdateAdd, MetadataUpdateRemove } from './types';
|
import { Association, Metadata, MetadataUpdate, MetadataUpdateAdd, MetadataUpdateRemove, MetadataEditField, MetadataUpdateEdit } from './types';
|
||||||
|
|
||||||
export const METADATA_UPDATE_VERSION = 1;
|
export const METADATA_UPDATE_VERSION = 2;
|
||||||
|
|
||||||
export const metadataAction = <T extends MetadataUpdate>(data: T, version: number = METADATA_UPDATE_VERSION): Poke<T> => ({
|
export const metadataAction = <T extends MetadataUpdate>(data: T, version: number = METADATA_UPDATE_VERSION): Poke<T> => ({
|
||||||
app: 'metadata-push-hook',
|
app: 'metadata-push-hook',
|
||||||
@ -59,6 +59,25 @@ export const remove = (
|
|||||||
|
|
||||||
export { remove as metadataRemove };
|
export { remove as metadataRemove };
|
||||||
|
|
||||||
|
export const edit = (
|
||||||
|
association: Association,
|
||||||
|
edit: MetadataEditField
|
||||||
|
): Poke<MetadataUpdateEdit> => metadataAction({
|
||||||
|
edit: {
|
||||||
|
group: association.group,
|
||||||
|
resource: {
|
||||||
|
resource: association.resource,
|
||||||
|
'app-name': association['app-name']
|
||||||
|
},
|
||||||
|
edit
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export { edit as metadataEdit };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link edit} instead
|
||||||
|
*/
|
||||||
export const update = (
|
export const update = (
|
||||||
association: Association,
|
association: Association,
|
||||||
newMetadata: Partial<Metadata>
|
newMetadata: Partial<Metadata>
|
||||||
|
@ -4,7 +4,8 @@ export type MetadataUpdate =
|
|||||||
MetadataUpdateInitial
|
MetadataUpdateInitial
|
||||||
| MetadataUpdateAdd
|
| MetadataUpdateAdd
|
||||||
| MetadataUpdateUpdate
|
| MetadataUpdateUpdate
|
||||||
| MetadataUpdateRemove;
|
| MetadataUpdateRemove
|
||||||
|
| MetadataUpdateEdit;
|
||||||
|
|
||||||
export interface MetadataUpdateInitial {
|
export interface MetadataUpdateInitial {
|
||||||
associations: ResourceAssociations;
|
associations: ResourceAssociations;
|
||||||
@ -22,6 +23,15 @@ export type MetadataUpdateUpdate = {
|
|||||||
update: AssociationPoke;
|
update: AssociationPoke;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MetadataUpdateEdit {
|
||||||
|
edit: {
|
||||||
|
resource: MdResource;
|
||||||
|
edit: MetadataEditField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MetadataEditField = Partial<Omit<Metadata, 'config' | 'creator' | 'date-created'>>;
|
||||||
|
|
||||||
export type MetadataUpdateRemove = {
|
export type MetadataUpdateRemove = {
|
||||||
remove: {
|
remove: {
|
||||||
resource: MdResource;
|
resource: MdResource;
|
||||||
|
2
pkg/npm/api/package-lock.json
generated
2
pkg/npm/api/package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@urbit/api",
|
"name": "@urbit/api",
|
||||||
"version": "1.2.0",
|
"version": "1.4.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@urbit/api",
|
"name": "@urbit/api",
|
||||||
"version": "1.2.0",
|
"version": "1.4.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -21,7 +21,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@types/lodash": "^4.14.168",
|
"@types/lodash": "^4.14.168",
|
||||||
"@urbit/eslint-config": "^1.0.1",
|
"@urbit/eslint-config": "^1.0.3",
|
||||||
"big-integer": "^1.6.48",
|
"big-integer": "^1.6.48",
|
||||||
"immer": "^9.0.1",
|
"immer": "^9.0.1",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
|
2
pkg/npm/eslint-config/package-lock.json
generated
2
pkg/npm/eslint-config/package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@urbit/eslint-config",
|
"name": "@urbit/eslint-config",
|
||||||
"version": "1.0.1",
|
"version": "1.0.3",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@urbit/eslint-config",
|
"name": "@urbit/eslint-config",
|
||||||
"version": "1.0.1",
|
"version": "1.0.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
2
pkg/npm/http-api/package-lock.json
generated
2
pkg/npm/http-api/package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@urbit/http-api",
|
"name": "@urbit/http-api",
|
||||||
"version": "1.2.3",
|
"version": "1.3.1",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@urbit/http-api",
|
"name": "@urbit/http-api",
|
||||||
"version": "1.2.3",
|
"version": "1.3.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Library to interact with an Urbit ship over HTTP",
|
"description": "Library to interact with an Urbit ship over HTTP",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
Loading…
Reference in New Issue
Block a user