mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-24 15:34:10 +03:00
Merge remote-tracking branch 'origin/release/next-userspace' into lf/npm-typings
This commit is contained in:
commit
926da94604
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:61e583dd7db795dac4a7c31bfd3ee8b240e679bb882e35d4e7d1acb5f9f2f3d6
|
||||
size 8270131
|
||||
oid sha256:e0af91e5c51359719aaa943f37a1e953989c786412616b18fbaa0addb2cf0740
|
||||
size 10272514
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:185ea5e76dc48695e55efc543377e0682e485f81b16e3b443f9be881d026d4f2
|
||||
size 2616564
|
||||
oid sha256:23d8235b19a3404e0bfbed54aa56a018255beb1f33457e37f521bc0763b4d0eb
|
||||
size 6245506
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:28c1ce6409721365a8c24d77af767550bb6596260833af21fa96964b740b3cf8
|
||||
size 12381649
|
||||
oid sha256:64d7cd93dbdf650e390b9c5780ee8bee22cf925fa31f47a0a1a3b17ce7443302
|
||||
size 11566105
|
||||
|
@ -918,7 +918,7 @@
|
||||
^- (quip card _state)
|
||||
:_ state
|
||||
=- (turn - print:sh-out)
|
||||
:~ ";view ~host/chat to print messages for a chat you've already jonied."
|
||||
:~ ";view ~host/chat to print messages for a chat you've already joined."
|
||||
";flee ~host/chat to stop printing messages for a chat."
|
||||
"For more details:"
|
||||
"https://urbit.org/using/operations/using-your-ship/#messaging"
|
||||
|
@ -131,10 +131,9 @@
|
||||
=^ allowed cards (is-allowed-add:hc rid nodes.q.update)
|
||||
?. allowed
|
||||
[cards ~]
|
||||
=/ mark-cached (~(has by graph-to-mark) rid)
|
||||
=/ mark
|
||||
?: mark-cached
|
||||
(~(got by graph-to-mark) rid)
|
||||
%+ fall
|
||||
(~(get by graph-to-mark) rid)
|
||||
(get-mark:gra rid)
|
||||
?~ mark
|
||||
[cards `vas]
|
||||
@ -143,15 +142,12 @@
|
||||
|%
|
||||
++ $
|
||||
^- (quip card (unit vase))
|
||||
=/ transform-cached (~(has by transform-marks) u.mark)
|
||||
=/ transform=cached-transform
|
||||
?: transform-cached
|
||||
(~(got by transform-marks) u.mark)
|
||||
%+ fall
|
||||
(~(get by transform-marks) u.mark)
|
||||
=/ =tube:clay
|
||||
.^(tube:clay (scry:hc %cc %home /[u.mark]/transform-add-nodes))
|
||||
!< cached-transform
|
||||
%. !>(*indexed-post:store)
|
||||
tube
|
||||
!<(cached-transform (tube !>(*indexed-post:store)))
|
||||
=/ [* result=(list [index:store node:store])]
|
||||
%+ roll
|
||||
(flatten-node-map ~(tap by nodes.q.update))
|
||||
@ -164,13 +160,15 @@
|
||||
update
|
||||
%+ weld cards
|
||||
%- zing
|
||||
:~ ?: mark-cached ~
|
||||
:~ ?: (~(has by graph-to-mark) rid)
|
||||
~
|
||||
:_ ~
|
||||
%+ poke-self:pass:io %graph-cache-hook
|
||||
!> ^- cache-action
|
||||
[%graph-to-mark rid mark]
|
||||
::
|
||||
?: transform-cached ~
|
||||
?: (~(has by transform-marks) u.mark)
|
||||
~
|
||||
:_ ~
|
||||
%+ poke-self:pass:io %graph-cache-hook
|
||||
!> ^- cache-action
|
||||
@ -316,28 +314,27 @@
|
||||
|= [=resource:res perm=@t vip=vip-metadata:metadata =indexed-post:store]
|
||||
^- [permissions:store (list card)]
|
||||
|^
|
||||
=/ mark-cached (~(has by graph-to-mark.cache) resource)
|
||||
=/ mark
|
||||
?: mark-cached
|
||||
(~(got by graph-to-mark.cache) resource)
|
||||
%+ fall
|
||||
(~(get by graph-to-mark.cache) resource)
|
||||
(get-mark:gra resource)
|
||||
?~ mark
|
||||
[[%no %no %no] ~]
|
||||
=/ key [u.mark (perm-mark-name perm)]
|
||||
=/ perms-cached (~(has by perm-marks.cache) key)
|
||||
=/ convert
|
||||
?: perms-cached
|
||||
(~(got by perm-marks.cache) key)
|
||||
%+ fall
|
||||
(~(get by perm-marks.cache) key)
|
||||
.^(cached-permission (scry %cf %home /[u.mark]/(perm-mark-name perm)))
|
||||
:- ((convert indexed-post) vip)
|
||||
%- zing
|
||||
:~ ?: mark-cached ~
|
||||
:~ ?: (~(has by graph-to-mark.cache) resource)
|
||||
~
|
||||
:_ ~
|
||||
%+ poke-self:pass:io %graph-cache-hook
|
||||
!> ^- cache-action
|
||||
[%graph-to-mark resource mark]
|
||||
::
|
||||
?: perms-cached ~
|
||||
?: (~(has by perm-marks.cache) key) ~
|
||||
:_ ~
|
||||
%+ poke-self:pass:io %graph-cache-hook
|
||||
!> ^- cache-action
|
||||
|
@ -5,8 +5,8 @@
|
||||
|%
|
||||
+$ card card:agent:gall
|
||||
+$ versioned-state
|
||||
$% [%0 network:zero:store]
|
||||
[%1 network:zero:store]
|
||||
$% [%0 *]
|
||||
[%1 *]
|
||||
[%2 network:zero:store]
|
||||
[%3 network:one:store]
|
||||
[%4 network:store]
|
||||
@ -16,7 +16,6 @@
|
||||
+$ state-5 [%5 network:store]
|
||||
++ orm orm:store
|
||||
++ orm-log orm-log:store
|
||||
+$ debug-input [%validate-graph =resource:store]
|
||||
::
|
||||
+$ cache
|
||||
$: validators=(map mark $-(indexed-post:store indexed-post:store))
|
||||
@ -50,34 +49,8 @@
|
||||
=| cards=(list card)
|
||||
|-
|
||||
?- -.old
|
||||
%0
|
||||
=* zro zero-load:upgrade:store
|
||||
%_ $
|
||||
-.old %1
|
||||
::
|
||||
graphs.old
|
||||
%- ~(run by graphs.old)
|
||||
|= [=graph:zero:store q=(unit mark)]
|
||||
^- [graph:zero:store (unit mark)]
|
||||
:- (convert-unix-timestamped-graph:zro graph)
|
||||
?^ q q
|
||||
`%graph-validator-link
|
||||
::
|
||||
update-logs.old
|
||||
%- ~(run by update-logs.old)
|
||||
|=(a=* *update-log:zero:store)
|
||||
==
|
||||
::
|
||||
%1
|
||||
=* zro zero-load:upgrade:store
|
||||
%_ $
|
||||
-.old %2
|
||||
graphs.old (~(run by graphs.old) change-revision-graph:zro)
|
||||
::
|
||||
update-logs.old
|
||||
%- ~(run by update-logs.old)
|
||||
|=(a=* *update-log:zero:store)
|
||||
==
|
||||
%0 !!
|
||||
%1 !!
|
||||
::
|
||||
%2
|
||||
=* upg upgrade:store
|
||||
@ -138,7 +111,7 @@
|
||||
++ give
|
||||
|= =action:store
|
||||
^- (list card)
|
||||
[%give %fact ~ [%graph-update-2 !>([now.bowl action])]]~
|
||||
[%give %fact ~ [%graph-update-2 !>(`update:store`[now.bowl action])]]~
|
||||
--
|
||||
::
|
||||
++ on-poke
|
||||
@ -148,10 +121,9 @@
|
||||
|^
|
||||
?> (team:title our.bowl src.bowl)
|
||||
=^ cards state
|
||||
?+ mark (on-poke:def mark vase)
|
||||
%graph-update-2 (graph-update !<(update:store vase))
|
||||
%noun (debug !<(debug-input vase))
|
||||
%import (poke-import q.vase)
|
||||
?+ mark (on-poke:def mark vase)
|
||||
%graph-update-2 (graph-update !<(update:store vase))
|
||||
%import (poke-import q.vase)
|
||||
==
|
||||
[cards this]
|
||||
::
|
||||
@ -204,7 +176,7 @@
|
||||
==
|
||||
%- zing
|
||||
:~ (give [/keys ~] %keys (~(put in ~(key by graphs)) resource))
|
||||
(give [/updates ~] %add-graph resource *graph:store mark overwrite)
|
||||
(give [/updates ~] %add-graph resource ~ mark overwrite)
|
||||
==
|
||||
::
|
||||
++ remove-graph
|
||||
@ -274,7 +246,7 @@
|
||||
?~ index
|
||||
?=(^ node)
|
||||
?~ t.index
|
||||
?=(^ (get:orm graph i.index))
|
||||
(has:orm graph i.index)
|
||||
=. node (get:orm graph i.index)
|
||||
?~ node %.n
|
||||
?- -.children.u.node
|
||||
@ -330,7 +302,8 @@
|
||||
~| "cannot add deleted post"
|
||||
?> ?=(%& -.post.node)
|
||||
=* p p.post.node
|
||||
?~ hash.p node(signatures.p.post *signatures:store)
|
||||
?~ hash.p
|
||||
node(signatures.p.post ~)
|
||||
=/ =validated-portion:store
|
||||
[parent-hash author.p time-sent.p contents.p]
|
||||
=/ =hash:store `@ux`(sham validated-portion)
|
||||
@ -343,24 +316,23 @@
|
||||
::
|
||||
=/ parent=node:store
|
||||
~| "index does not exist to add a node to!"
|
||||
(need (get:orm graph atom))
|
||||
(got:orm graph atom)
|
||||
%_ parent
|
||||
children
|
||||
^- internal-graph:store
|
||||
:- %graph
|
||||
%_ $
|
||||
index t.index
|
||||
index t.index
|
||||
::
|
||||
parent-hash
|
||||
?- -.post.parent
|
||||
%| `p.post.parent
|
||||
%& hash.p.post.parent
|
||||
==
|
||||
?: ?=(%| -.post.parent)
|
||||
`p.post.parent
|
||||
hash.p.post.parent
|
||||
::
|
||||
graph
|
||||
?: ?=(%graph -.children.parent)
|
||||
p.children.parent
|
||||
(gas:orm ~ ~)
|
||||
?. ?=(%graph -.children.parent)
|
||||
~
|
||||
p.children.parent
|
||||
==
|
||||
==
|
||||
--
|
||||
@ -416,7 +388,7 @@
|
||||
?~ t.index
|
||||
=/ =node:store
|
||||
~| "cannot remove index that does not exist {<index>}"
|
||||
(need (get:orm graph atom))
|
||||
(got:orm graph atom)
|
||||
%_ node
|
||||
post
|
||||
~| "cannot remove post that has already been removed"
|
||||
@ -434,7 +406,7 @@
|
||||
::
|
||||
=/ parent=node:store
|
||||
~| "parent index does not exist to remove a node from!"
|
||||
(need (get:orm graph atom))
|
||||
(got:orm graph atom)
|
||||
~| "child index does not exist to remove a node from!"
|
||||
?> ?=(%graph -.children.parent)
|
||||
%_ parent
|
||||
@ -444,10 +416,9 @@
|
||||
graph p.children.parent
|
||||
::
|
||||
parent-hash
|
||||
?- -.post.parent
|
||||
%| `p.post.parent
|
||||
%& hash.p.post.parent
|
||||
==
|
||||
?: ?=(%| -.post.parent)
|
||||
`p.post.parent
|
||||
hash.p.post.parent
|
||||
==
|
||||
==
|
||||
--
|
||||
@ -478,7 +449,7 @@
|
||||
=* atom i.index
|
||||
=/ =node:store
|
||||
~| "node does not exist to add signatures to!"
|
||||
(need (get:orm graph atom))
|
||||
(got:orm graph atom)
|
||||
:: last index in list
|
||||
::
|
||||
%^ put:orm
|
||||
@ -490,7 +461,10 @@
|
||||
~| "cannot add signatures to a node missing a hash"
|
||||
?> ?=(^ hash.p.post.node)
|
||||
~| "signatures did not match public keys!"
|
||||
?> (are-signatures-valid:sigs our.bowl signatures u.hash.p.post.node now.bowl)
|
||||
?> %: are-signatures-valid:sigs
|
||||
our.bowl signatures
|
||||
u.hash.p.post.node now.bowl
|
||||
==
|
||||
node(signatures.p.post (~(uni in signatures) signatures.p.post.node))
|
||||
~| "child graph does not exist to add signatures to!"
|
||||
?> ?=(%graph -.children.node)
|
||||
@ -525,7 +499,7 @@
|
||||
=* atom i.index
|
||||
=/ =node:store
|
||||
~| "node does not exist to add signatures to!"
|
||||
(need (get:orm graph atom))
|
||||
(got:orm graph atom)
|
||||
:: last index in list
|
||||
::
|
||||
%^ put:orm
|
||||
@ -578,7 +552,7 @@
|
||||
%_ state
|
||||
archive (~(del by archive) resource)
|
||||
graphs (~(put by graphs) resource (~(got by archive) resource))
|
||||
update-logs (~(put by update-logs) resource (gas:orm-log ~ ~))
|
||||
update-logs (~(put by update-logs) resource ~)
|
||||
==
|
||||
::
|
||||
++ run-updates
|
||||
@ -599,38 +573,28 @@
|
||||
%- graph-update
|
||||
^- update:store
|
||||
?- -.q.update
|
||||
%add-graph update(resource.q resource)
|
||||
%add-nodes update(resource.q resource)
|
||||
%remove-posts update(resource.q resource)
|
||||
%add-signatures update(resource.uid.q resource)
|
||||
%remove-signatures update(resource.uid.q resource)
|
||||
%add-graph update(resource.q resource)
|
||||
%add-nodes update(resource.q resource)
|
||||
%remove-posts update(resource.q resource)
|
||||
%add-signatures update(resource.uid.q resource)
|
||||
%remove-signatures update(resource.uid.q resource)
|
||||
==
|
||||
$(cards (weld cards crds), updates t.updates)
|
||||
::
|
||||
++ give
|
||||
|= [paths=(list path) update=action:store]
|
||||
^- (list card)
|
||||
[%give %fact paths [%graph-update-2 !>([now.bowl update])]]~
|
||||
[%give %fact paths [%graph-update-2 !>(`update:store`[now.bowl update])]]~
|
||||
--
|
||||
::
|
||||
++ debug
|
||||
|= =debug-input
|
||||
^- (quip card _state)
|
||||
=/ [=graph:store mark=(unit mark:store)]
|
||||
(~(got by graphs) resource.debug-input)
|
||||
=^ is-valid state
|
||||
(validate-graph graph mark)
|
||||
?> is-valid
|
||||
[~ state]
|
||||
::
|
||||
++ validate-graph
|
||||
|= [=graph:store mark=(unit mark:store)]
|
||||
^- [? _state]
|
||||
?~ mark [%.y state]
|
||||
=/ has-validator (~(has by validators) u.mark)
|
||||
?~ mark
|
||||
[%.y state]
|
||||
=/ validate=$-(indexed-post:store indexed-post:store)
|
||||
?: has-validator
|
||||
(~(got by validators) u.mark)
|
||||
%+ fall
|
||||
(~(get by validators) u.mark)
|
||||
.^ $-(indexed-post:store indexed-post:store)
|
||||
%cf
|
||||
(scot %p our.bowl)
|
||||
@ -640,11 +604,13 @@
|
||||
%graph-indexed-post
|
||||
~
|
||||
==
|
||||
:_ state(validators (~(put by validators) u.mark validate))
|
||||
=? validators !(~(has by validators) u.mark)
|
||||
(~(put by validators) u.mark validate)
|
||||
:_ state
|
||||
|- ^- ?
|
||||
?~ graph %.y
|
||||
%+ roll (tap:orm graph)
|
||||
|= [[=atom =node:store] out=?]
|
||||
%+ all:orm graph
|
||||
|= [=atom =node:store]
|
||||
^- ?
|
||||
?& ?| ?=(%| -.post.node)
|
||||
?=(^ (validate [atom p.post.node]))
|
||||
@ -762,6 +728,7 @@
|
||||
(~(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
|
||||
@ -779,21 +746,28 @@
|
||||
:+ %add-nodes
|
||||
[ship term]
|
||||
%- ~(gas by *(map index:store node:store))
|
||||
:: TODO time complexity not desirable
|
||||
:: replace with custom ordered map functions
|
||||
%+ turn
|
||||
=- ?.(older (slag (safe-sub (lent -) count) -) (scag count -))
|
||||
?: older
|
||||
(tab:orm u.graph ~ count)
|
||||
:: TODO time complexity not desirable for %younger case
|
||||
::
|
||||
%+ slag (safe-sub (lent -) count)
|
||||
%- tap:orm
|
||||
%+ lot:orm u.graph
|
||||
=/ idx
|
||||
(snag (dec (lent index)) index)
|
||||
?:(older [`idx ~] [~ `idx])
|
||||
[~ `(snag (dec (lent index)) index)]
|
||||
|= [=atom =node:store]
|
||||
^- [index:store node:store]
|
||||
[(snoc parent atom) node]
|
||||
::
|
||||
++ safe-sub
|
||||
|= [a=@ b=@]
|
||||
^- @
|
||||
?: (gte b a)
|
||||
0
|
||||
(sub a b)
|
||||
--
|
||||
::
|
||||
[%x %shallow-children @ @ *]
|
||||
=/ newest ?=(%newest i.t.path)
|
||||
=/ =ship (slav %p i.t.t.path)
|
||||
=/ =term i.t.t.t.path
|
||||
=/ =index:store
|
||||
@ -831,8 +805,9 @@
|
||||
%- ~(gas by *(map index:store node:store))
|
||||
%+ turn
|
||||
%+ scag count
|
||||
%- ?:(newest same flop)
|
||||
(tap:orm u.children)
|
||||
?: newest
|
||||
(tap:orm u.children)
|
||||
(bap:orm u.children)
|
||||
|= [=atom =node:store]
|
||||
^- [index:store node:store]
|
||||
[(snoc index atom) node]
|
||||
@ -923,7 +898,8 @@
|
||||
::
|
||||
++ collect-parents
|
||||
|= [=graph:store =index:store =ship =term]
|
||||
^- (unit [node:store index:store (map index:store node: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
|
||||
@ -953,16 +929,16 @@
|
||||
==
|
||||
::
|
||||
++ collect-firstborn
|
||||
|= [=node:store =index:store map=(map index:store node:store) =ship =term]
|
||||
|= [=node:store =index:store mp=(map index:store node:store) =ship =term]
|
||||
^- (unit (unit cage))
|
||||
?: ?=(%empty -.children.node)
|
||||
:- ~ :- ~ :- %graph-update-2
|
||||
!> ^- update:store
|
||||
[now.bowl [%add-nodes [ship term] map]]
|
||||
[now.bowl [%add-nodes [ship term] mp]]
|
||||
=/ 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)
|
||||
$(mp (~(put by mp) index v.item(children empty+~)), node v.item)
|
||||
--
|
||||
::
|
||||
[%x %update-log-subset @ @ @ @ ~]
|
||||
@ -985,23 +961,17 @@
|
||||
[%x %peek-update-log @ @ ~]
|
||||
=/ =ship (slav %p i.t.t.path)
|
||||
=/ =term i.t.t.t.path
|
||||
=/ m-update-log=(unit update-log:store) (~(get by update-logs) [ship term])
|
||||
=/ m-update-log=(unit update-log:store)
|
||||
(~(get by update-logs) [ship term])
|
||||
:- ~ :- ~ :- %noun
|
||||
!> ^- (unit time)
|
||||
%+ biff m-update-log
|
||||
|= =update-log:store
|
||||
=/ result=(unit [=time =update:store])
|
||||
(pry:orm-log:store update-log)
|
||||
(bind result |=([=time update:store] time))
|
||||
(bind result head)
|
||||
==
|
||||
::
|
||||
++ safe-sub
|
||||
|= [a=@ b=@]
|
||||
^- @
|
||||
?: (gte b a)
|
||||
0
|
||||
(sub a b)
|
||||
::
|
||||
++ get-node-children
|
||||
|= [=ship =term =index:store]
|
||||
^- (unit graph:store)
|
||||
@ -1044,40 +1014,12 @@
|
||||
?+ wire (on-arvo:def wire sign-arvo)
|
||||
::
|
||||
:: old wire, do nothing
|
||||
[%graph *] [~ this]
|
||||
[%validator @ ~] [~ this]
|
||||
::
|
||||
[%try-rejoin @ *]
|
||||
=/ rid=resource:store (de-path:res t.t.wire)
|
||||
=/ nack-count (slav %ud i.t.wire)
|
||||
?> ?=([%behn %wake *] sign-arvo)
|
||||
~? ?=(^ error.sign-arvo)
|
||||
"behn errored in backoff timers, continuing anyway"
|
||||
=/ new=^wire [%try-rejoin (scot %ud +(nack-count)) t.t.wire]
|
||||
:_ this
|
||||
[%pass new %agent [entity.rid %graph-push-hook] %watch resource+t.t.wire]~
|
||||
[%graph *] [~ this]
|
||||
[%validator @ ~] [~ this]
|
||||
[%try-rejoin @ *] [~ this]
|
||||
==
|
||||
::
|
||||
++ on-agent
|
||||
|= [=wire =sign:agent:gall]
|
||||
^- (quip card _this)
|
||||
?. ?=([%try-rejoin @ *] wire)
|
||||
(on-agent:def wire sign)
|
||||
?. ?=(%watch-ack -.sign)
|
||||
[~ this]
|
||||
=/ rid=resource:store (de-path:res t.t.wire)
|
||||
?~ p.sign
|
||||
=/ =cage [%pull-hook-action !>([%add entity.rid rid])]
|
||||
:_ this
|
||||
:~ [%pass / %agent [our.bowl %graph-pull-hook] %poke cage]
|
||||
[%pass wire %agent [entity.rid %graph-push-hook] %leave ~]
|
||||
==
|
||||
=/ nack-count=@ud (slav %ud i.t.wire)
|
||||
=/ wakeup=@da
|
||||
(add now.bowl (mul ~s1 (bex (min 19 nack-count))))
|
||||
:_ this
|
||||
[%pass wire %arvo %b %wait wakeup]~
|
||||
::
|
||||
++ on-agent on-agent:def
|
||||
++ on-leave on-leave:def
|
||||
++ on-fail on-fail:def
|
||||
--
|
||||
|
@ -30,12 +30,12 @@
|
||||
?> ?=(^ t.p)
|
||||
.^(mold i.p (scot %p our) i.t.p (scot %da now) t.t.p)
|
||||
::
|
||||
++ scry-conversion
|
||||
++ scry-notif-conversion
|
||||
|= [[our=@p now=@da] desk=term =mark]
|
||||
~+
|
||||
^- $-(indexed-post:graph-store (unit notif-kind:hook))
|
||||
%^ scry [our now]
|
||||
tube:clay
|
||||
/cc/[desk]/[mark]/notification-kind
|
||||
$-(indexed-post:graph-store (unit notif-kind:hook))
|
||||
/cf/[desk]/[mark]/notification-kind
|
||||
--
|
||||
::
|
||||
=| state-1
|
||||
@ -87,7 +87,7 @@
|
||||
|= =mark
|
||||
^- card
|
||||
=/ =wire /validator/[mark]
|
||||
=/ =rave:clay [%sing %c [%da now.bowl] /[mark]/notification-kind]
|
||||
=/ =rave:clay [%sing %f [%da now.bowl] /[mark]/notification-kind]
|
||||
[%pass wire %arvo %c %warp our.bowl [%home `rave]]
|
||||
::
|
||||
++ on-watch
|
||||
@ -214,19 +214,18 @@
|
||||
%- ~(gas by *(set [resource index:graph-store]))
|
||||
(turn ~(tap in indices) (lead rid))
|
||||
:_ state(watching (~(dif in watching) to-remove))
|
||||
=/ =tube:clay
|
||||
(get-conversion:ha rid)
|
||||
=/ convert (get-conversion:ha rid)
|
||||
%+ roll
|
||||
~(tap in indices)
|
||||
|= [=index:graph-store out=(list card)]
|
||||
=| =indexed-post:graph-store
|
||||
=. index.p.indexed-post index
|
||||
=+ !<(u-notif-kind=(unit notif-kind:hook) (tube !>(indexed-post)))
|
||||
?~ u-notif-kind out
|
||||
=* notif-kind u.u-notif-kind
|
||||
=/ notif-kind=(unit notif-kind:hook)
|
||||
(convert indexed-post)
|
||||
?~ notif-kind out
|
||||
=/ =stats-index:store
|
||||
[%graph rid (scag parent.index-len.notif-kind index)]
|
||||
?. ?=(%each mode.notif-kind) out
|
||||
[%graph rid (scag parent.index-len.u.notif-kind index)]
|
||||
?. ?=(%each mode.u.notif-kind) out
|
||||
:_ out
|
||||
(poke-hark %read-each stats-index index)
|
||||
::
|
||||
@ -285,7 +284,7 @@
|
||||
[%validator @ ~]
|
||||
:_ this
|
||||
=* validator i.t.wire
|
||||
=/ =rave:clay [%next %c [%da now.bowl] /[validator]/notification-kind]
|
||||
=/ =rave:clay [%next %f [%da now.bowl] /[validator]/notification-kind]
|
||||
[%pass wire %arvo %c %warp our.bowl [%home `rave]]~
|
||||
==
|
||||
++ on-fail on-fail:def
|
||||
@ -298,13 +297,13 @@
|
||||
::
|
||||
++ get-conversion
|
||||
|= rid=resource
|
||||
^- tube:clay
|
||||
^- $-(indexed-post:graph-store (unit notif-kind:hook))
|
||||
=+ %^ scry [our now]:bowl
|
||||
,mark=(unit mark)
|
||||
/gx/graph-store/graph-mark/(scot %p entity.rid)/[name.rid]/noun
|
||||
?~ mark
|
||||
|=(v=vase !>(~))
|
||||
(scry-conversion [our now]:bowl q.byk.bowl u.mark)
|
||||
|=(=indexed-post:graph-store ~)
|
||||
(scry-notif-conversion [our now]:bowl q.byk.bowl u.mark)
|
||||
::
|
||||
++ give
|
||||
|= [paths=(list path) =update:hook]
|
||||
@ -355,8 +354,6 @@
|
||||
update-core(rid r, updates upds, mark m)
|
||||
::
|
||||
++ get-conversion
|
||||
:: LA: this tube should be cached in %hark-graph-hook state
|
||||
:: instead of just trying to keep it warm, as the scry overhead is large
|
||||
~+ (^get-conversion rid)
|
||||
::
|
||||
++ abet
|
||||
@ -410,9 +407,8 @@
|
||||
?: ?=(%| -.post.node)
|
||||
update-core
|
||||
=* pos p.post.node
|
||||
=+ !< notif-kind=(unit notif-kind:hook)
|
||||
%- get-conversion
|
||||
!>(`indexed-post:graph-store`[0 pos])
|
||||
=/ notif-kind=(unit notif-kind:hook)
|
||||
(get-conversion [0 pos])
|
||||
?~ notif-kind
|
||||
update-core
|
||||
=/ desc=@t
|
||||
|
@ -422,7 +422,11 @@
|
||||
%read-note (read-note +.in)
|
||||
::
|
||||
%seen-index (seen-index +.in)
|
||||
::
|
||||
%remove-graph (remove-graph +.in)
|
||||
%read-graph (read-graph +.in)
|
||||
%read-group (read-group +.in)
|
||||
::
|
||||
%set-dnd (set-dnd +.in)
|
||||
%seen seen
|
||||
%read-all read-all
|
||||
@ -566,10 +570,53 @@
|
||||
(~(put by last-seen) stats-index new-time)
|
||||
(give %seen-index new-time stats-index)
|
||||
::
|
||||
++ get-stats-indices
|
||||
|= rid=resource
|
||||
%- ~(gas ^in *(set stats-index:store))
|
||||
%+ skim
|
||||
;: weld
|
||||
~(tap ^in ~(key by unreads-count))
|
||||
~(tap ^in ~(key by last-seen))
|
||||
~(tap ^in ~(key by unreads-each))
|
||||
==
|
||||
|= =stats-index:store
|
||||
?. ?=(%graph -.stats-index) %.n
|
||||
=(graph.stats-index rid)
|
||||
::
|
||||
++ read-all-each
|
||||
|= =stats-index:store
|
||||
=/ refs=(list index:graph-store)
|
||||
~(tap ^in (~(get ju unreads-each) stats-index))
|
||||
|-
|
||||
?~ refs poke-core
|
||||
$(refs t.refs, poke-core (read-each stats-index i.refs))
|
||||
::
|
||||
++ read-graph
|
||||
|= rid=resource
|
||||
=/ indices=(list stats-index:store)
|
||||
~(tap ^in (get-stats-indices rid))
|
||||
|-
|
||||
?~ indices poke-core
|
||||
=* index i.indices
|
||||
=? poke-core (~(has by unreads-count) index)
|
||||
(read-count i.indices)
|
||||
=? poke-core (~(has by unreads-each) index)
|
||||
(read-all-each i.indices)
|
||||
$(indices t.indices)
|
||||
::
|
||||
++ read-group
|
||||
|= rid=resource
|
||||
=/ graphs=(list resource)
|
||||
(graphs-of-group:met rid)
|
||||
|-
|
||||
?~ graphs poke-core
|
||||
=/ core=_poke-core (read-graph i.graphs)
|
||||
$(graphs t.graphs, poke-core core)
|
||||
::
|
||||
++ remove-graph
|
||||
|= rid=resource
|
||||
|^
|
||||
=/ indices get-stats-indices
|
||||
=/ indices (get-stats-indices rid)
|
||||
=. poke-core
|
||||
(give %remove-graph rid)
|
||||
=. poke-core
|
||||
@ -583,18 +630,6 @@
|
||||
((dif-map-by-key ,@da) last-seen indices)
|
||||
poke-core
|
||||
::
|
||||
++ get-stats-indices
|
||||
%- ~(gas ^in *(set stats-index:store))
|
||||
%+ skim
|
||||
;: weld
|
||||
~(tap ^in ~(key by unreads-count))
|
||||
~(tap ^in ~(key by last-seen))
|
||||
~(tap ^in ~(key by unreads-each))
|
||||
==
|
||||
|= =stats-index:store
|
||||
?. ?=(%graph -.stats-index) %.n
|
||||
=(graph.stats-index rid)
|
||||
::
|
||||
++ dif-map-by-key
|
||||
|* value=mold
|
||||
|= [=(map stats-index:store value) =(set stats-index:store)]
|
||||
|
@ -28,8 +28,8 @@
|
||||
rose+(ot style+(ot mid+sa open+sa close+sa ~) lines+(ar dank) ~)
|
||||
==
|
||||
::
|
||||
++ orm ((ordered-map atom node) gth)
|
||||
++ orm-log ((ordered-map time logged-update) gth)
|
||||
++ orm ((on atom node) gth)
|
||||
++ orm-log ((on time logged-update) gth)
|
||||
::
|
||||
++ enjs
|
||||
=, enjs:format
|
||||
@ -311,7 +311,7 @@
|
||||
++ graph
|
||||
|= a=json
|
||||
^- ^graph
|
||||
=/ or-mp ((ordered-map atom ^node) gth)
|
||||
=/ or-mp ((on atom ^node) gth)
|
||||
%+ gas:or-mp ~
|
||||
%+ turn ~(tap by ((om node) a))
|
||||
|* [b=cord c=*]
|
||||
@ -559,7 +559,7 @@
|
||||
=>
|
||||
|%
|
||||
++ in-orm
|
||||
((ordered-map atom in-node) gth)
|
||||
((on atom in-node) gth)
|
||||
+$ in-node
|
||||
[post=in-pst children=in-internal-graph]
|
||||
+$ in-graph
|
||||
@ -571,7 +571,7 @@
|
||||
==
|
||||
::
|
||||
++ out-orm
|
||||
((ordered-map atom out-node) gth)
|
||||
((on atom out-node) gth)
|
||||
+$ out-node
|
||||
[post=out-pst children=out-internal-graph]
|
||||
+$ out-graph
|
||||
@ -823,7 +823,7 @@
|
||||
++ remake-update-log
|
||||
|= t=tree-update-log
|
||||
^- update-log
|
||||
=/ ulm ((ordered-map time logged-update) gth)
|
||||
=/ ulm ((on time logged-update) gth)
|
||||
%+ gas:ulm *update-log
|
||||
%+ turn ~(tap by t)
|
||||
|= [=time tlu=tree-logged-update]
|
||||
|
@ -314,6 +314,8 @@
|
||||
add-note+add
|
||||
set-dnd+bo
|
||||
read-count+stats-index
|
||||
read-graph+dejs-path:resource
|
||||
read-group+dejs-path:resource
|
||||
read-each+read-graph-index
|
||||
read-all+ul
|
||||
==
|
||||
|
@ -100,4 +100,13 @@
|
||||
^- (unit resource)
|
||||
%+ bind (peek-association md-resource)
|
||||
|=(association:store group)
|
||||
::
|
||||
++ graphs-of-group
|
||||
|= group=resource
|
||||
=/ =associations:store
|
||||
(metadata-for-group group)
|
||||
%+ murn ~(tap in ~(key by associations))
|
||||
|= [=app-name:store rid=resource]
|
||||
?.(=(%graph app-name) ~ `rid)
|
||||
|
||||
--
|
||||
|
@ -73,8 +73,8 @@
|
||||
::
|
||||
++ one
|
||||
|%
|
||||
++ orm ((ordered-map atom node) gth)
|
||||
++ orm-log ((ordered-map time logged-update) gth)
|
||||
++ orm ((on atom node) gth)
|
||||
++ orm-log ((on time logged-update) gth)
|
||||
::
|
||||
+$ graph ((mop atom node) gth)
|
||||
+$ marked-graph [p=graph q=(unit mark)]
|
||||
|
@ -44,6 +44,9 @@
|
||||
[%read-note =index]
|
||||
::
|
||||
[%seen-index time=@da =stats-index]
|
||||
::
|
||||
[%read-graph =resource]
|
||||
[%read-group =resource]
|
||||
[%remove-graph =resource]
|
||||
::
|
||||
[%read-all ~]
|
||||
@ -281,6 +284,7 @@
|
||||
[%unread-note time=@da index]
|
||||
::
|
||||
[%seen-index time=@da =stats-index]
|
||||
::
|
||||
[%remove-graph =resource]
|
||||
::
|
||||
[%read-all ~]
|
||||
|
@ -252,11 +252,13 @@
|
||||
:: %what: update from files
|
||||
:: %whey: produce $mass :: XX remove, scry
|
||||
:: %verb: toggle laconicity
|
||||
:: %whiz: prime vane caches
|
||||
::
|
||||
$% [%trim p=@ud]
|
||||
[%what p=(list (pair path (cask)))]
|
||||
[%whey ~]
|
||||
[%verb p=(unit ?)]
|
||||
[%whiz ~]
|
||||
==
|
||||
+$ wasp
|
||||
:: %crud: reroute $ovum with $goof
|
||||
@ -291,14 +293,23 @@
|
||||
|=(b=beam =*(s scot `path`[(s %p p.b) q.b (s r.b) s.b]))
|
||||
::
|
||||
++ de-beam
|
||||
~/ %de-beam
|
||||
|= p=path
|
||||
^- (unit beam)
|
||||
?. ?=([@ @ @ *] p) ~
|
||||
?~ who=(slaw %p i.p) ~
|
||||
?~ des=?~(i.t.p (some %$) (slaw %tas i.t.p)) ~ :: XX +sym ;~(pose low (easy %$))
|
||||
?~ ved=(slay i.t.t.p) ~
|
||||
?. ?=([%$ case] u.ved) ~
|
||||
`(unit beam)`[~ [`ship`u.who `desk`u.des `case`p.u.ved] t.t.t.p]
|
||||
?~ ved=(de-case i.t.t.p) ~
|
||||
`[[`ship`u.who `desk`u.des u.ved] t.t.t.p]
|
||||
::
|
||||
++ de-case
|
||||
~/ %de-case
|
||||
|= =knot
|
||||
^- (unit case)
|
||||
?^ num=(slaw %ud knot) `[%ud u.num]
|
||||
?^ wen=(slaw %da knot) `[%da u.wen]
|
||||
?~ lab=(slaw %tas knot) ~
|
||||
`[%tas u.lab]
|
||||
::
|
||||
++ en-omen
|
||||
|= [vis=view bem=beam]
|
||||
@ -308,6 +319,7 @@
|
||||
~(rent co [%many $/tas/way.vis $/tas/car.vis ~])
|
||||
::
|
||||
++ de-omen
|
||||
~/ %de-omen
|
||||
|= pax=path
|
||||
^- (unit [vis=view bem=beam])
|
||||
?~ pax ~
|
||||
@ -1000,8 +1012,11 @@
|
||||
++ settle
|
||||
|= van=vase
|
||||
^- (pair vase worm)
|
||||
=/ [rig=vase wor=worm] (~(slym wa *worm) van *vane-sample)
|
||||
[van +:(~(slap wa wor) rig [%limb %scry])]
|
||||
=| sac=worm
|
||||
=^ rig=vase sac (~(slym wa sac) van *vane-sample)
|
||||
=^ gat=vase sac (~(slap wa sac) rig [%limb %scry])
|
||||
=^ pro=vase sac (~(slap wa sac) gat [%limb %$])
|
||||
[van +:(~(mint wa sac) p.pro [%$ 7])]
|
||||
::
|
||||
:: XX pass identity to preserve behavior?
|
||||
::
|
||||
@ -1470,6 +1485,9 @@
|
||||
%verb ..pith(lac.fad ?~(p.waif !lac.fad u.p.waif))
|
||||
%what ~(kel what p.waif)
|
||||
%whey ..pith(out [[//arvo mass/whey] out])
|
||||
::
|
||||
%whiz
|
||||
..pith(van.mod (~(run by van.mod) |=(vane (settle:va:part vase))))
|
||||
==
|
||||
::
|
||||
++ peek
|
||||
|
@ -259,6 +259,8 @@
|
||||
++ head |*(^ ,:+<-) :: get head
|
||||
++ same |*(* +<) :: identity
|
||||
::
|
||||
++ succ |=(@ +(+<)) :: successor
|
||||
::
|
||||
++ tail |*(^ ,:+<+) :: get tail
|
||||
++ test |=(^ =(+<- +<+)) :: equality
|
||||
::
|
||||
@ -8764,6 +8766,7 @@
|
||||
%peek peek
|
||||
%repo repo
|
||||
%rest rest
|
||||
%sink sink
|
||||
%tack tack
|
||||
%toss toss
|
||||
%wrap wrap
|
||||
@ -10838,7 +10841,7 @@
|
||||
|- ^- type
|
||||
?~ lov sut
|
||||
$(lov t.lov, sut (face i.lov sut))
|
||||
:: ::
|
||||
::
|
||||
++ sint :: reduce by reference
|
||||
|= $: :: hod: expand holds
|
||||
::
|
||||
@ -10911,6 +10914,39 @@
|
||||
%- ~(gas in *(set type))
|
||||
(turn leg |=([p=type q=hoon] (play(sut p) q)))
|
||||
::
|
||||
++ sink
|
||||
~/ %sink
|
||||
|^ ^- cord
|
||||
?- sut
|
||||
%void 'void'
|
||||
%noun 'noun'
|
||||
[%atom *] (rap 3 'atom ' p.sut ' ' ?~(q.sut '~' u.q.sut) ~)
|
||||
[%cell *] (rap 3 'cell ' (mup p.sut) ' ' (mup q.sut) ~)
|
||||
[%face *] (rap 3 'face ' ?@(p.sut p.sut (mup p.sut)) ' ' (mup q.sut) ~)
|
||||
[%fork *] (rap 3 'fork ' (mup p.sut) ~)
|
||||
[%hint *] (rap 3 'hint ' (mup p.sut) ' ' (mup q.sut) ~)
|
||||
[%hold *] (rap 3 'hold ' (mup p.sut) ' ' (mup q.sut) ~)
|
||||
::
|
||||
[%core *]
|
||||
%+ rap 3
|
||||
:~ 'core '
|
||||
(mup p.sut)
|
||||
' '
|
||||
?~(p.p.q.sut '~' u.p.p.q.sut)
|
||||
' '
|
||||
q.p.q.sut
|
||||
' '
|
||||
r.p.q.sut
|
||||
' '
|
||||
(mup q.q.sut)
|
||||
' '
|
||||
(mup p.r.q.sut)
|
||||
==
|
||||
==
|
||||
::
|
||||
++ mup |=(* (scot %p (mug +<)))
|
||||
--
|
||||
::
|
||||
++ take
|
||||
|= [vit=vein duz=$-(type type)]
|
||||
^- (pair axis type)
|
||||
|
@ -1069,14 +1069,23 @@
|
||||
:::: :: (1d2)
|
||||
::
|
||||
+$ blew [p=@ud q=@ud] :: columns rows
|
||||
+$ belt :: old belt
|
||||
+$ belt :: client input
|
||||
$? bolt :: simple input
|
||||
$% [%mod mod=?(%ctl %met %hyp) key=bolt] :: w/ modifier
|
||||
[%txt p=(list @c)] :: utf32 text
|
||||
::TODO consider moving %hey, %rez, %yow here ::
|
||||
::TMP forward backwards-compatibility ::
|
||||
:: ::
|
||||
[%ctl p=@c] ::
|
||||
[%met p=@c] ::
|
||||
== == ::
|
||||
+$ bolt :: simple input
|
||||
$@ @c :: simple keystroke
|
||||
$% [%aro p=?(%d %l %r %u)] :: arrow key
|
||||
[%bac ~] :: true backspace
|
||||
[%ctl p=@c] :: control-key
|
||||
[%del ~] :: true delete
|
||||
[%met p=@c] :: meta-key
|
||||
[%hit r=@ud c=@ud] :: mouse click
|
||||
[%ret ~] :: return
|
||||
[%txt p=(list @c)] :: utf32 text
|
||||
== ::
|
||||
+$ blit :: old blit
|
||||
$% [%bel ~] :: make a noise
|
||||
@ -2102,6 +2111,7 @@
|
||||
[%g task:gall]
|
||||
[%i task:iris]
|
||||
[%j task:jael]
|
||||
[%$ %whiz ~]
|
||||
[@tas %meta vase]
|
||||
==
|
||||
:: full vane names are required in vanes
|
||||
|
@ -3660,7 +3660,7 @@
|
||||
=/ lower=@ud 1
|
||||
|-
|
||||
:: a should be excluded, so wait until we're past it
|
||||
?: =(lower +(a))
|
||||
?: (gte lower +(a))
|
||||
acc
|
||||
=/ res=(set tako) (reachable-takos (~(got by hit.dom) lower))
|
||||
$(acc (~(uni in acc) res), lower +(lower))
|
||||
@ -3668,7 +3668,7 @@
|
||||
=| acc=(set tako)
|
||||
=/ upper=@ud b
|
||||
|-
|
||||
?: =(upper a)
|
||||
?: (lte upper a)
|
||||
acc
|
||||
=/ res=(set tako) (reachable-takos (~(got by hit.dom) upper))
|
||||
$(acc (~(uni in acc) res), upper (dec upper))
|
||||
|
@ -106,7 +106,6 @@
|
||||
%flow +>
|
||||
%harm +>
|
||||
%hail (send %hey ~)
|
||||
%belt (send `dill-belt`p.kyz)
|
||||
%text (from %out (tuba p.kyz))
|
||||
%crud :: (send `dill-belt`[%cru p.kyz q.kyz])
|
||||
(crud p.kyz q.kyz)
|
||||
@ -116,6 +115,18 @@
|
||||
%pack (dump kyz)
|
||||
%crop (dump trim+p.kyz)
|
||||
%verb (pass /verb %$ kyz)
|
||||
::
|
||||
%belt
|
||||
%- send
|
||||
::TMP forwards compatibility with next-dill
|
||||
::
|
||||
?@ p.kyz [%txt p.kyz ~]
|
||||
?: ?=(%hit -.p.kyz) [%txt ~]
|
||||
?. ?=(%mod -.p.kyz) p.kyz
|
||||
=/ =@c
|
||||
?@ key.p.kyz key.p.kyz
|
||||
?:(?=(?(%bac %del %ret) -.key.p.kyz) `@`-.key.p.kyz ~-)
|
||||
?:(?=(%met mod.p.kyz) [%met c] [%ctl c])
|
||||
==
|
||||
::
|
||||
++ crud
|
||||
|
@ -30,6 +30,9 @@
|
||||
$% [%rest p=@da]
|
||||
[%wait p=@da]
|
||||
== ==
|
||||
$: %c
|
||||
$>(%warp task:clay)
|
||||
==
|
||||
:: %d: to dill
|
||||
::
|
||||
$: %d
|
||||
@ -53,6 +56,12 @@
|
||||
$: %gall
|
||||
gift:gall
|
||||
:: $>(%unto gift:gall)
|
||||
::
|
||||
==
|
||||
$: %clay
|
||||
gift:clay
|
||||
:: $>(%writ gift:clay)
|
||||
::
|
||||
== ==
|
||||
--
|
||||
:: more structures
|
||||
@ -1231,9 +1240,9 @@
|
||||
::NOTE these will only fail if the mark and/or json types changed,
|
||||
:: since conversion failure also gets caught during first receive.
|
||||
:: we can't do anything about this, so consider it unsupported.
|
||||
?~ sign=(channel-event-to-sign channel-event) $
|
||||
?~ json=(sign-to-json request-id u.sign) $
|
||||
$(events [(event-json-to-wall id u.json) events])
|
||||
?~ sign=(channel-event-to-sign channel-event) $
|
||||
?~ jive=(sign-to-json request-id u.sign) $
|
||||
$(events [(event-json-to-wall id +.u.jive) events])
|
||||
:: send the start event to the client
|
||||
::
|
||||
=^ http-moves state
|
||||
@ -1499,8 +1508,12 @@
|
||||
:: if conversion succeeds, we *can* send it. if the client is actually
|
||||
:: connected, we *will* send it immediately.
|
||||
::
|
||||
=/ json=(unit json)
|
||||
=/ jive=(unit (quip move json))
|
||||
(sign-to-json request-id sign)
|
||||
=/ json=(unit json)
|
||||
?~(jive ~ `+.u.jive)
|
||||
=? moves ?=(^ jive)
|
||||
(weld moves -.u.jive)
|
||||
=* sending &(?=([%| *] state.u.channel) ?=(^ json))
|
||||
::
|
||||
=/ next-id next-id.u.channel
|
||||
@ -1578,7 +1591,7 @@
|
||||
^= data
|
||||
%- wall-to-octs
|
||||
%+ event-json-to-wall next-id
|
||||
(need (sign-to-json request-id %kick ~))
|
||||
+:(need (sign-to-json request-id %kick ~))
|
||||
::
|
||||
complete=%.n
|
||||
==
|
||||
@ -1619,32 +1632,33 @@
|
||||
:: +sign-to-json: render sign from request-id as json channel event
|
||||
::
|
||||
++ sign-to-json
|
||||
~% %sign-to-json ..part ~
|
||||
|= [request-id=@ud =sign:agent:gall]
|
||||
^- (unit json)
|
||||
^- (unit (quip move json))
|
||||
:: for facts, we try to convert the result to json
|
||||
::
|
||||
=/ jsyn=(unit sign:agent:gall)
|
||||
?. ?=(%fact -.sign) `sign
|
||||
?: ?=(%json p.cage.sign) `sign
|
||||
=/ [from=(unit mark) jsyn=(unit sign:agent:gall)]
|
||||
?. ?=(%fact -.sign) [~ `sign]
|
||||
?: ?=(%json p.cage.sign) [~ `sign]
|
||||
:: find and use tube from fact mark to json
|
||||
::
|
||||
=* have=mark p.cage.sign
|
||||
=* desc=tape "from {(trip have)} to json"
|
||||
=/ tube=(unit tube:clay)
|
||||
=/ tuc=(unit (unit cage))
|
||||
(rof ~ %cc [our %home da+now] /[have]/json)
|
||||
?. ?=([~ ~ *] tuc) ~
|
||||
`!<(tube:clay q.u.u.tuc)
|
||||
?~ tube
|
||||
((slog leaf+"eyre: no tube {desc}" ~) ~)
|
||||
::
|
||||
=/ res (mule |.((u.tube q.cage.sign)))
|
||||
?: ?=(%& -.res)
|
||||
`[%fact %json p.res]
|
||||
((slog leaf+"eyre: failed tube {desc}" ~) ~)
|
||||
::
|
||||
=/ convert=(unit vase)
|
||||
=/ cag=(unit (unit cage))
|
||||
(rof ~ %cf [our %home da+now] /[have]/json)
|
||||
?. ?=([~ ~ *] cag) ~
|
||||
`q.u.u.cag
|
||||
?~ convert
|
||||
((slog leaf+"eyre: no convert {desc}" ~) [~ ~])
|
||||
~| "conversion failed {desc}"
|
||||
[`have `[%fact %json (slym u.convert q.q.cage.sign)]]
|
||||
?~ jsyn ~
|
||||
%- some
|
||||
:- ?~ from ~
|
||||
:_ ~
|
||||
:^ duct %pass /conversion-cache/[u.from]
|
||||
[%c %warp our %home `[%sing %f da+now /[u.from]/json]]
|
||||
=* sign u.jsyn
|
||||
=, enjs:format
|
||||
%- pairs
|
||||
@ -1665,7 +1679,7 @@
|
||||
:- 'json'
|
||||
~| [%unexpected-fact-mark p.cage.sign]
|
||||
?> =(%json p.cage.sign)
|
||||
;;(json q.q.cage.sign)
|
||||
!<(json q.cage.sign)
|
||||
==
|
||||
::
|
||||
%kick
|
||||
@ -2320,14 +2334,15 @@
|
||||
::
|
||||
|^ ^- [(list move) _http-server-gate]
|
||||
::
|
||||
?+ i.wire
|
||||
~|([%bad-take-wire wire] !!)
|
||||
?+ i.wire
|
||||
~|([%bad-take-wire wire] !!)
|
||||
::
|
||||
%run-app-request run-app-request
|
||||
%watch-response watch-response
|
||||
%sessions sessions
|
||||
%channel channel
|
||||
%acme acme-ack
|
||||
%run-app-request run-app-request
|
||||
%watch-response watch-response
|
||||
%sessions sessions
|
||||
%channel channel
|
||||
%acme acme-ack
|
||||
%conversion-cache `http-server-gate
|
||||
==
|
||||
::
|
||||
++ run-app-request
|
||||
|
@ -159,7 +159,10 @@
|
||||
~< %slog.[0 leaf+"gall: molted"]
|
||||
:: +molt should never notify its client about agent changes
|
||||
::
|
||||
=- [(skip -< |=(move ?=([* %give %onto *] +<))) ->]
|
||||
=- :_ ->
|
||||
%+ welp
|
||||
(skip -< |=(move ?=([* %give %onto *] +<)))
|
||||
[^duct %pass /whiz/gall %$ %whiz ~]~
|
||||
=/ adult adult-core
|
||||
=. state.adult
|
||||
[%7 system-duct outstanding contacts yokes=~ blocked]:spore
|
||||
|
@ -3391,6 +3391,11 @@
|
||||
:: :: ++no:dejs:format
|
||||
++ no :: number as cord
|
||||
|=(jon=json ?>(?=([%n *] jon) p.jon))
|
||||
:: :: ++nu:dejs:format
|
||||
++ nu :: parse number as hex
|
||||
|= jon=json
|
||||
?> ?=([%s *] jon)
|
||||
(rash p.jon hex)
|
||||
:: :: ++of:dejs:format
|
||||
++ of :: object as frond
|
||||
|* wer=(pole [cord fist])
|
||||
@ -3440,6 +3445,11 @@
|
||||
=/ ten ~|(key+key.wer (wit.wer (~(get by jom) key.wer)))
|
||||
?~(t.wer ten [ten ((ou-raw t.wer) jom)])
|
||||
==
|
||||
:: :: ++oj:dejs:format
|
||||
++ oj :: object as jug
|
||||
|* =fist
|
||||
^- $-(json (jug cord _(fist *json)))
|
||||
(om (as fist))
|
||||
:: :: ++om:dejs:format
|
||||
++ om :: object as map
|
||||
|* wit=fist
|
||||
@ -3466,6 +3476,12 @@
|
||||
:: :: ++sa:dejs:format
|
||||
++ sa :: string as tape
|
||||
|=(jon=json ?>(?=([%s *] jon) (trip p.jon)))
|
||||
:: :: ++sd:dejs:format
|
||||
++ sd :: string @ud as date
|
||||
|= jon=json
|
||||
^- @da
|
||||
?> ?=(%s -.jon)
|
||||
`@da`(rash p.jon dem:ag)
|
||||
:: :: ++se:dejs:format
|
||||
++ se :: string as aura
|
||||
|= aur=@tas
|
||||
@ -3580,6 +3596,15 @@
|
||||
?. ?=([%s *] jon) ~
|
||||
(bind (stud:chrono:userlib p.jon) |=(a=date (year a)))
|
||||
::
|
||||
++ dank :: tank
|
||||
^- $-(json (unit tank))
|
||||
%+ re *tank |. ~+
|
||||
%- of :~
|
||||
leaf+sa
|
||||
palm+(ot style+(ot mid+sa cap+sa open+sa close+sa ~) lines+(ar dank) ~)
|
||||
rose+(ot style+(ot mid+sa open+sa close+sa ~) lines+(ar dank) ~)
|
||||
==
|
||||
::
|
||||
++ di :: millisecond date
|
||||
(cu from-unix-ms:chrono:userlib ni)
|
||||
::
|
||||
@ -3653,6 +3678,12 @@
|
||||
|* [pre=* wit=fist]
|
||||
(cu |*(* [pre +<]) wit)
|
||||
::
|
||||
++ re :: recursive reparsers
|
||||
|* [gar=* sef=_|.(fist)]
|
||||
|= jon=json
|
||||
^- (unit _gar)
|
||||
((sef) jon)
|
||||
::
|
||||
++ sa :: string as tape
|
||||
|= jon=json
|
||||
?.(?=([%s *] jon) ~ (some (trip p.jon)))
|
||||
|
@ -49,7 +49,7 @@
|
||||
^- hexb:bc
|
||||
%- flip:byt:bc
|
||||
%- sha256:bc
|
||||
(script-pubkey:bc a)
|
||||
(to-script-pubkey:adr:bc a)
|
||||
::
|
||||
++ parse-json-rpc
|
||||
|= =json
|
||||
|
@ -48,7 +48,7 @@ export default class Send extends Component {
|
||||
showModal: false,
|
||||
note: '',
|
||||
choosingSignMethod: false,
|
||||
signMethod: 'Sign Transaction',
|
||||
signMethod: 'bridge',
|
||||
};
|
||||
|
||||
this.initPayment = this.initPayment.bind(this);
|
||||
@ -86,7 +86,7 @@ export default class Send extends Component {
|
||||
}
|
||||
|
||||
setSignMethod(signMethod) {
|
||||
this.setState({signMethod});
|
||||
this.setState({signMethod, choosingSignMethod: false});
|
||||
}
|
||||
|
||||
checkPayee(e){
|
||||
@ -204,7 +204,7 @@ export default class Send extends Component {
|
||||
const signReady = (this.state.ready && (parseInt(this.state.satsAmount) > 0)) && !signing;
|
||||
|
||||
let invoice = null;
|
||||
if (signMethod === 'Sign Transaction') {
|
||||
if (signMethod === 'masterTicket') {
|
||||
invoice =
|
||||
<Invoice
|
||||
network={network}
|
||||
@ -218,7 +218,7 @@ export default class Send extends Component {
|
||||
satsAmount={satsAmount}
|
||||
state={this.props.state}
|
||||
/>
|
||||
} else if (signMethod === 'Sign with Bridge') {
|
||||
} else if (signMethod === 'bridge') {
|
||||
invoice =
|
||||
<BridgeInvoice
|
||||
state={this.props.state}
|
||||
@ -439,6 +439,17 @@ export default class Send extends Component {
|
||||
border='none'
|
||||
style={{cursor: signReady ? 'pointer' : 'default'}} />
|
||||
</Row>
|
||||
{signMethod === 'masterTicket' &&
|
||||
<Row
|
||||
mt={4}
|
||||
alignItems='center'
|
||||
>
|
||||
<Icon icon='Info' color='yellow' height={4} width={4}/>
|
||||
<Text fontSize="14px" fontWeight="regular" color="gray" ml={2}>
|
||||
We recommend that you sign transactions using Bridge to protect your master ticket.
|
||||
</Text>
|
||||
</Row>
|
||||
}
|
||||
</Col>
|
||||
}
|
||||
</>
|
||||
|
@ -19,26 +19,26 @@ export default function Signer(props) {
|
||||
backgroundColor='transparent'
|
||||
fontWeight='bold'
|
||||
cursor='pointer'
|
||||
color={(signMethod === 'Sign Transaction') ? 'blue' : 'lightBlue'}
|
||||
color={(signMethod === 'masterTicket') ? 'blue' : 'lightBlue'}
|
||||
py='24px'
|
||||
px='24px'
|
||||
onClick={() => setSignMethod('Sign Transaction')}
|
||||
children='Sign Transaction' />
|
||||
onClick={() => setSignMethod('masterTicket')}
|
||||
children='Sign with Master Ticket' />
|
||||
<Button
|
||||
border='none'
|
||||
backgroundColor='transparent'
|
||||
fontWeight='bold'
|
||||
cursor='pointer'
|
||||
color={(signMethod === 'Sign with Bridge') ? 'blue' : 'lightBlue'}
|
||||
color={(signMethod === 'bridge') ? 'blue' : 'lightBlue'}
|
||||
py='24px'
|
||||
px='24px'
|
||||
onClick={() => setSignMethod('Sign with Bridge')}
|
||||
onClick={() => setSignMethod('bridge')}
|
||||
children='Sign with Bridge' />
|
||||
</Box>
|
||||
:
|
||||
<Button
|
||||
primary
|
||||
children={signMethod}
|
||||
children={signMethod === 'bridge' ? 'Sign with Bridge' : 'Sign with Master Ticket'}
|
||||
fontSize={1}
|
||||
fontWeight='bold'
|
||||
borderRadius='24px'
|
||||
|
@ -22,7 +22,7 @@ export default class WalletModal extends Component {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
mode: 'masterTicket',
|
||||
mode: 'xpub',
|
||||
masterTicket: '',
|
||||
confirmedMasterTicket: '',
|
||||
xpub: '',
|
||||
@ -103,13 +103,15 @@ export default class WalletModal extends Component {
|
||||
Step 2 of 2: Import your extended public key
|
||||
</Text>
|
||||
</Row>
|
||||
<Box mt={3}>
|
||||
<Text fontSize="14px" fontWeight="regular" color="gray">
|
||||
To begin, you'll need to derive an XPub Bitcoin address using your
|
||||
master ticket.
|
||||
<a fontSize="14px" target="_blank" href="https://urbit.org/bitcoin-wallet"> Learn More</a>
|
||||
<Row
|
||||
mt={3}
|
||||
alignItems='center'
|
||||
>
|
||||
<Icon icon='Info' color='yellow' height={4} width={4}/>
|
||||
<Text fontSize="14px" fontWeight="regular" color="gray" ml={2}>
|
||||
We recommend that you import your wallet using Bridge to protect your master ticket.
|
||||
</Text>
|
||||
</Box>
|
||||
</Row>
|
||||
<Box
|
||||
display='flex'
|
||||
alignItems='center'
|
||||
@ -126,7 +128,7 @@ export default class WalletModal extends Component {
|
||||
error: false
|
||||
})}/>}
|
||||
<Text fontSize="14px" fontWeight="500">
|
||||
{this.state.confirmingMasterTicket ? 'Confirm Master Key' : 'Master Key'}
|
||||
{this.state.confirmingMasterTicket ? 'Confirm Master Ticket' : 'Master Ticket'}
|
||||
</Text>
|
||||
</Box>
|
||||
<Row alignItems="center">
|
||||
@ -155,37 +157,38 @@ export default class WalletModal extends Component {
|
||||
</Text>
|
||||
</Row>
|
||||
}
|
||||
<Box mt={3} mb={3}>
|
||||
<Text fontSize="14px" fontWeight="regular"
|
||||
color={(inputDisabled) ? "lighterGray" : "gray"}
|
||||
style={{cursor: (inputDisabled) ? "default" : "pointer"}}
|
||||
<Row mt={3}>
|
||||
<Button
|
||||
primary
|
||||
color="black"
|
||||
backgroundColor="veryLightGray"
|
||||
borderColor="veryLightGray"
|
||||
children="Cancel"
|
||||
fontSize="14px"
|
||||
mr={2}
|
||||
style={{cursor: "pointer"}}
|
||||
onClick={() => {this.setState({mode: 'xpub', masterTicket: '', xpub: '', readyToSubmit: false})}}
|
||||
/>
|
||||
<Button
|
||||
primary
|
||||
disabled={buttonDisabled}
|
||||
children="Next Step"
|
||||
fontSize="14px"
|
||||
style={{cursor: buttonDisabled ? "default" : "pointer"}}
|
||||
onClick={() => {
|
||||
if (inputDisabled) return;
|
||||
this.setState({mode: 'xpub', xpub: '', masterTicket: '', readyToSubmit: false})
|
||||
}}
|
||||
>
|
||||
Manually import your extended public key ->
|
||||
</Text>
|
||||
</Box>
|
||||
<Button
|
||||
primary
|
||||
disabled={buttonDisabled}
|
||||
children="Next Step"
|
||||
fontSize="14px"
|
||||
style={{cursor: buttonDisabled ? "default" : "pointer"}}
|
||||
onClick={() => {
|
||||
if (!this.state.confirmingMasterTicket) {
|
||||
this.setState({confirmingMasterTicket: true});
|
||||
} else {
|
||||
if (this.state.masterTicket === this.state.confirmedMasterTicket) {
|
||||
this.setState({error: false});
|
||||
this.submitMasterTicket(this.state.masterTicket);
|
||||
if (!this.state.confirmingMasterTicket) {
|
||||
this.setState({confirmingMasterTicket: true});
|
||||
} else {
|
||||
this.setState({error: true});
|
||||
if (this.state.masterTicket === this.state.confirmedMasterTicket) {
|
||||
this.setState({error: false});
|
||||
this.submitMasterTicket(this.state.masterTicket);
|
||||
} else {
|
||||
this.setState({error: true});
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
}}
|
||||
/>
|
||||
</Row>
|
||||
</Box>
|
||||
);
|
||||
} else if (this.state.mode === 'xpub') {
|
||||
@ -203,7 +206,7 @@ export default class WalletModal extends Component {
|
||||
</Row>
|
||||
<Box mt={3}>
|
||||
<Text fontSize="14px" fontWeight="regular" color="gray">
|
||||
Visit bridge.urbit.org to obtain your key
|
||||
Visit <a href='https://bridge.urbit.org/?kind=xpub' target='_blank' style={{color: 'black'}} >bridge.urbit.org</a> to obtain your key
|
||||
</Text>
|
||||
</Box>
|
||||
<Box mt={3} mb={2}>
|
||||
@ -221,27 +224,27 @@ export default class WalletModal extends Component {
|
||||
autoCorrect="off"
|
||||
onChange={this.checkXPub}
|
||||
/>
|
||||
<Row mt={3}>
|
||||
<Button
|
||||
primary
|
||||
color="black"
|
||||
backgroundColor="veryLightGray"
|
||||
borderColor="veryLightGray"
|
||||
children="Cancel"
|
||||
fontSize="14px"
|
||||
mr={2}
|
||||
style={{cursor: "pointer"}}
|
||||
onClick={() => {this.setState({mode: 'masterTicket', masterTicket: '', xpub: '', readyToSubmit: false})}}
|
||||
/>
|
||||
<Button
|
||||
primary
|
||||
disabled={buttonDisabled}
|
||||
children="Next Step"
|
||||
fontSize="14px"
|
||||
style={{cursor: this.state.ready ? "pointer" : "default"}}
|
||||
onClick={() => { this.submitXPub(this.state.xpub) }}
|
||||
/>
|
||||
</Row>
|
||||
<Box mt={3} mb={3}>
|
||||
<Text fontSize="14px" fontWeight="regular"
|
||||
color={(inputDisabled) ? "lighterGray" : "gray"}
|
||||
style={{cursor: (inputDisabled) ? "default" : "pointer"}}
|
||||
onClick={() => {
|
||||
if (inputDisabled) return;
|
||||
this.setState({mode: 'masterTicket', xpub: '', masterTicket: '', readyToSubmit: false})
|
||||
}}
|
||||
>
|
||||
Import using master ticket ->
|
||||
</Text>
|
||||
</Box>
|
||||
<Button
|
||||
primary
|
||||
mt={3}
|
||||
disabled={buttonDisabled}
|
||||
children="Next Step"
|
||||
fontSize="14px"
|
||||
style={{cursor: this.state.ready ? "pointer" : "default"}}
|
||||
onClick={() => { this.submitXPub(this.state.xpub) }}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { Association, GraphNotifDescription, IndexedNotification, NotifIndex } from '@urbit/api';
|
||||
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
||||
import { BigInteger } from 'big-integer';
|
||||
import { getParentIndex } from '../lib/notification';
|
||||
import { dateToDa, decToUd } from '../lib/util';
|
||||
import {reduce} from '../reducers/hark-update';
|
||||
import {doOptimistically, optReduceState} from '../state/base';
|
||||
import { reduce } from '../reducers/hark-update';
|
||||
import { doOptimistically } from '../state/base';
|
||||
import useHarkState from '../state/hark';
|
||||
import { StoreState } from '../store/type';
|
||||
import BaseApi from './base';
|
||||
@ -62,7 +61,7 @@ export class HarkApi extends BaseApi<StoreState> {
|
||||
index
|
||||
}
|
||||
};
|
||||
await doOptimistically(useHarkState, action, this.harkAction.bind(this), [reduce])
|
||||
await doOptimistically(useHarkState, action, this.harkAction.bind(this), [reduce]);
|
||||
}
|
||||
|
||||
read(time: BigInteger, index: NotifIndex) {
|
||||
@ -81,6 +80,18 @@ export class HarkApi extends BaseApi<StoreState> {
|
||||
return this.actOnNotification('unread-note', time, index);
|
||||
}
|
||||
|
||||
readGroup(group: string) {
|
||||
return this.harkAction({
|
||||
'read-group': group
|
||||
});
|
||||
}
|
||||
|
||||
readGraph(graph: string) {
|
||||
return this.harkAction({
|
||||
'read-graph': graph
|
||||
});
|
||||
}
|
||||
|
||||
dismissReadCount(graph: string, index: string) {
|
||||
return this.harkAction({
|
||||
'read-count': {
|
||||
|
@ -5,7 +5,7 @@ import React, {
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useState
|
||||
} from 'react';
|
||||
import _ from 'lodash';
|
||||
import { getChord } from '~/logic/lib/util';
|
||||
@ -13,10 +13,9 @@ import { getChord } from '~/logic/lib/util';
|
||||
type Handler = (e: KeyboardEvent) => void;
|
||||
const fallback: ShortcutContextProps = {
|
||||
add: () => {},
|
||||
remove: () => {},
|
||||
remove: () => {}
|
||||
};
|
||||
|
||||
|
||||
export const ShortcutContext = createContext(fallback);
|
||||
export interface ShortcutContextProps {
|
||||
add: (cb: (e: KeyboardEvent) => void, key: string) => void;
|
||||
@ -27,19 +26,19 @@ export function ShortcutContextProvider({ children }) {
|
||||
const handlerRef = useRef<Handler>(() => {});
|
||||
|
||||
const add = useCallback((cb: Handler, key: string) => {
|
||||
setShortcuts((s) => ({ ...s, [key]: cb }));
|
||||
setShortcuts(s => ({ ...s, [key]: cb }));
|
||||
}, []);
|
||||
const remove = useCallback((cb: Handler, key: string) => {
|
||||
setShortcuts((s) => (key in s ? _.omit(s, key) : s));
|
||||
setShortcuts(s => (key in s ? _.omit(s, key) : s));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
function onKeypress(e: KeyboardEvent) {
|
||||
handlerRef.current(e);
|
||||
}
|
||||
document.addEventListener('keypress', onKeypress);
|
||||
document.addEventListener('keydown', onKeypress);
|
||||
return () => {
|
||||
document.removeEventListener('keypress', onKeypress);
|
||||
document.removeEventListener('keydown', onKeypress);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@ -50,7 +49,7 @@ export function ShortcutContextProvider({ children }) {
|
||||
};
|
||||
}, [shortcuts]);
|
||||
|
||||
const value = useMemo(() => ({ add, remove }), [add, remove])
|
||||
const value = useMemo(() => ({ add, remove }), [add, remove]);
|
||||
|
||||
return (
|
||||
<ShortcutContext.Provider value={value}>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import urbitOb from 'urbit-ob';
|
||||
import { parsePermalink, permalinkToReference } from '~/logic/lib/permalinks';
|
||||
|
||||
const URL_REGEX = new RegExp(String(/^([^[\]]*?)(([\w\-\+]+:\/\/)[-a-zA-Z0-9:@;?&=\/%\+\.\*!'\(\),\$_\{\}\^~\[\]`#|]+[\w/])([\s\S]*)/.source));
|
||||
const URL_REGEX = new RegExp(String(/^([^[\]]*?)(([\w\-\+]+:\/\/)[-a-zA-Z0-9:@;?&=\/%\+\.\*!'\(\),\$_\{\}\^~\[\]`#|]+[-a-zA-Z0-9:@;?&=\/%\+\*!'\(\)\$_\{\}\^~\[\]`#|])([\s\S]*)/.source));
|
||||
|
||||
const PATP_REGEX = /^([\s\S]*?)(~[a-z_-]+)([\s\S]*)/;
|
||||
|
||||
|
@ -93,4 +93,24 @@ describe('tokenizeMessage', () => {
|
||||
expect(three).toEqual(' test ');
|
||||
expect(hastuc).toEqual('~hastuc-dibtux');
|
||||
});
|
||||
it('should tokenize a url with a par', () => {
|
||||
const example = 'test https://en.wikipedia.org/wiki/Turbo_(gastropod)';
|
||||
|
||||
const [{ text }, { url }] = tokenizeMessage(example);
|
||||
expect(text).toBe('test ');
|
||||
expect(url).toBe('https://en.wikipedia.org/wiki/Turbo_(gastropod)');
|
||||
});
|
||||
it('should ignore ending commas', () => {
|
||||
const example = 'https://tlon.io/test, foo';
|
||||
const [{ url }, { text }] = tokenizeMessage(example);
|
||||
expect(text).toBe(', foo');
|
||||
expect(url).toBe('https://tlon.io/test');
|
||||
});
|
||||
|
||||
it('should ignore ending dots', () => {
|
||||
const example = 'https://tlon.io/test. foo';
|
||||
const [{ url }, { text }] = tokenizeMessage(example);
|
||||
expect(text).toBe('. foo');
|
||||
expect(url).toBe('https://tlon.io/test');
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { DragEvent, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
function validateDragEvent(e: DragEvent): FileList | File[] | true | null {
|
||||
const files: File[] = [];
|
||||
@ -37,7 +37,7 @@ export function useFileDrag(dragged: (f: FileList | File[], e: DragEvent) => voi
|
||||
const [dragging, setDragging] = useState(false);
|
||||
|
||||
const onDragEnter = useCallback(
|
||||
(e: DragEvent) => {
|
||||
(e: DragEvent<HTMLDivElement>) => {
|
||||
if (!validateDragEvent(e)) {
|
||||
return;
|
||||
}
|
||||
@ -47,7 +47,7 @@ export function useFileDrag(dragged: (f: FileList | File[], e: DragEvent) => voi
|
||||
);
|
||||
|
||||
const onDrop = useCallback(
|
||||
(e: DragEvent) => {
|
||||
(e: DragEvent<HTMLDivElement>) => {
|
||||
setDragging(false);
|
||||
const files = validateDragEvent(e);
|
||||
if (!files || files === true) {
|
||||
@ -60,7 +60,7 @@ export function useFileDrag(dragged: (f: FileList | File[], e: DragEvent) => voi
|
||||
);
|
||||
|
||||
const onDragOver = useCallback(
|
||||
(e: DragEvent) => {
|
||||
(e: DragEvent<HTMLDivElement>) => {
|
||||
if (!validateDragEvent(e)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import _ from 'lodash';
|
||||
import { patp2dec } from 'urbit-ob';
|
||||
import f, { compose, memoize } from 'lodash/fp';
|
||||
import f from 'lodash/fp';
|
||||
import { Association, Contact, Patp } from '@urbit/api';
|
||||
import produce, { enableMapSet } from 'immer';
|
||||
import { enableMapSet } from 'immer';
|
||||
import useSettingsState from '../state/settings';
|
||||
/* eslint-disable max-lines */
|
||||
import anyAscii from 'any-ascii';
|
||||
@ -50,7 +50,7 @@ export function parentPath(path: string) {
|
||||
return _.dropRight(path.split('/'), 1).join('/');
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* undefined -> initial
|
||||
* null -> disabled feed
|
||||
* string -> enabled feed
|
||||
@ -67,23 +67,26 @@ export function getFeedPath(association: Association): string | null | undefined
|
||||
}
|
||||
|
||||
export const getChord = (e: KeyboardEvent) => {
|
||||
let chord = [e.key];
|
||||
const chord = [e.key];
|
||||
if(e.metaKey) {
|
||||
chord.unshift('meta');
|
||||
}
|
||||
if(e.ctrlKey) {
|
||||
chord.unshift('ctrl');
|
||||
}
|
||||
if(e.shiftKey) {
|
||||
chord.unshift('shift');
|
||||
}
|
||||
return chord.join('+');
|
||||
}
|
||||
};
|
||||
|
||||
export function getResourcePath(workspace: Workspace, path: string, joined: boolean, mod: string) {
|
||||
const base = workspace.type === 'group'
|
||||
? `/~landscape${workspace.group}`
|
||||
: workspace.type === 'home'
|
||||
? `/~landscape/home`
|
||||
: `/~landscape/messages`;
|
||||
return `${base}/${joined ? 'resource' : 'join'}/${mod}${path}`
|
||||
? '/~landscape/home'
|
||||
: '/~landscape/messages';
|
||||
return `${base}/${joined ? 'resource' : 'join'}/${mod}${path}`;
|
||||
}
|
||||
|
||||
const DA_UNIX_EPOCH = bigInt('170141184475152167957503069145530368000'); // `@ud` ~1970.1.1
|
||||
@ -135,14 +138,14 @@ export function decToUd(str: string): string {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Clamp a number between a min and max
|
||||
*/
|
||||
export function clamp(x: number, min: number, max: number) {
|
||||
return Math.max(min, Math.min(max, x));
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Euclidean modulo
|
||||
*/
|
||||
export function modulo(x: number, mod: number) {
|
||||
@ -355,6 +358,7 @@ export function stringToTa(str: string) {
|
||||
add = '~~';
|
||||
break;
|
||||
default:
|
||||
// eslint-disable-next-line
|
||||
const charCode = str.charCodeAt(i);
|
||||
if (
|
||||
(charCode >= 97 && charCode <= 122) || // a-z
|
||||
@ -413,7 +417,7 @@ export function stringToSymbol(str: string) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
/*
|
||||
* Formats a numbers as a `@ud` inserting dot where needed
|
||||
*/
|
||||
export function numToUd(num: number) {
|
||||
@ -428,7 +432,7 @@ export function numToUd(num: number) {
|
||||
}
|
||||
|
||||
export function patpToUd(patp: Patp) {
|
||||
return numToUd(patp2dec(patp))
|
||||
return numToUd(patp2dec(patp));
|
||||
}
|
||||
|
||||
export function usePreventWindowUnload(shouldPreventDefault: boolean, message = 'You have unsaved changes. Are you sure you want to exit?') {
|
||||
@ -443,7 +447,7 @@ export function usePreventWindowUnload(shouldPreventDefault: boolean, message =
|
||||
window.onbeforeunload = handleBeforeUnload;
|
||||
return () => {
|
||||
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||
// @ts-ignore
|
||||
// @ts-ignore need better window typings
|
||||
window.onbeforeunload = undefined;
|
||||
};
|
||||
}, [shouldPreventDefault]);
|
||||
@ -484,8 +488,8 @@ export function withHovering<T>(Component: React.ComponentType<T>) {
|
||||
return React.forwardRef((props, ref) => {
|
||||
const { hovering, bind } = useHovering();
|
||||
// @ts-ignore needs type signature on return?
|
||||
return <Component ref={ref} hovering={hovering} bind={bind} {...props} />
|
||||
})
|
||||
return <Component ref={ref} hovering={hovering} bind={bind} {...props} />;
|
||||
});
|
||||
}
|
||||
|
||||
const DM_REGEX = /ship\/~([a-z]|-)*\/dm--/;
|
||||
@ -500,14 +504,14 @@ export function getItemTitle(association: Association): string {
|
||||
return association.metadata.title ?? association.resource ?? '';
|
||||
}
|
||||
|
||||
export const svgDataURL = (svg) => 'data:image/svg+xml;base64,' + btoa(svg);
|
||||
export const svgDataURL = svg => 'data:image/svg+xml;base64,' + btoa(svg);
|
||||
|
||||
export const svgBlobURL = (svg) => URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));
|
||||
export const svgBlobURL = svg => URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));
|
||||
|
||||
export const favicon = () => {
|
||||
let background = '#ffffff';
|
||||
const contacts = useContactState.getState().contacts;
|
||||
if (contacts.hasOwnProperty(`~${window.ship}`)) {
|
||||
if (Object.prototype.hasOwnProperty.call(contacts, `~${window.ship}`)) {
|
||||
background = `#${uxToHex(contacts[`~${window.ship}`].color)}`;
|
||||
}
|
||||
const foreground = foregroundFromBackground(background);
|
||||
@ -518,4 +522,4 @@ export const favicon = () => {
|
||||
colors: [background, foreground]
|
||||
});
|
||||
return svg;
|
||||
}
|
||||
};
|
||||
|
@ -23,6 +23,7 @@ export interface ShortcutMapping {
|
||||
navForward: string;
|
||||
navBack: string;
|
||||
hideSidebar: string;
|
||||
readGroup: string;
|
||||
}
|
||||
|
||||
export interface SettingsState {
|
||||
@ -93,7 +94,8 @@ const useSettingsState = createState<SettingsState>(
|
||||
cycleBack: 'ctrl+;',
|
||||
navForward: 'ctrl+]',
|
||||
navBack: 'ctrl+[',
|
||||
hideSidebar: 'ctrl+\\'
|
||||
hideSidebar: 'ctrl+\\',
|
||||
readGroup: 'shift+Escape'
|
||||
},
|
||||
getAll: async () => {
|
||||
const { all } = await airlock.scry(getAll);
|
||||
|
@ -75,8 +75,6 @@ class App extends React.Component {
|
||||
super(props);
|
||||
this.ship = window.ship;
|
||||
|
||||
// eslint-disable-next-line
|
||||
|
||||
this.updateTheme = this.updateTheme.bind(this);
|
||||
this.updateMobile = this.updateMobile.bind(this);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BaseInput, Box, Button, LoadingSpinner, Text } from '@tlon/indigo-react';
|
||||
import { hasProvider } from 'oembed-parser';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { useCallback, useState, DragEvent, useEffect } from 'react';
|
||||
import { createPost } from '~/logic/api/graph';
|
||||
import { parsePermalink, permalinkToReference } from '~/logic/lib/permalinks';
|
||||
import { useFileDrag } from '~/logic/lib/useDrag';
|
||||
@ -94,6 +94,10 @@ const LinkSubmit = (props: LinkSubmitProps) => {
|
||||
return link;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setLinkValid(validateLink(linkValue));
|
||||
}, [linkValue]);
|
||||
|
||||
const onFileDrag = useCallback(
|
||||
(files: FileList | File[], e: DragEvent): void => {
|
||||
if (!canUpload) {
|
||||
|
@ -5,7 +5,7 @@ import 'codemirror/addon/edit/continuelist';
|
||||
import 'codemirror/lib/codemirror.css';
|
||||
import 'codemirror/mode/markdown/markdown';
|
||||
import { useFormikContext } from 'formik';
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import React, { useCallback, useRef, DragEvent } from 'react';
|
||||
import { UnControlled as CodeEditor } from 'react-codemirror2';
|
||||
import { Prompt } from 'react-router-dom';
|
||||
import { useFileDrag } from '~/logic/lib/useDrag';
|
||||
@ -61,13 +61,6 @@ export function MarkdownEditor(
|
||||
[onChange]
|
||||
);
|
||||
|
||||
const handleBlur = useCallback(
|
||||
(_i, e: any) => {
|
||||
onBlur && onBlur(e);
|
||||
},
|
||||
[onBlur]
|
||||
);
|
||||
|
||||
const { uploadDefault, canUpload } = useStorage();
|
||||
|
||||
const onFileDrag = useCallback(
|
||||
@ -110,10 +103,10 @@ export function MarkdownEditor(
|
||||
value={value}
|
||||
options={options}
|
||||
onChange={handleChange}
|
||||
onDragLeave={(editor, e: DragEvent) => bind.onDragLeave(e)}
|
||||
onDragOver={(editor, e: DragEvent) => bind.onDragOver(e)}
|
||||
onDrop={(editor, e: DragEvent) => bind.onDrop(e)}
|
||||
onDragEnter={(editor, e: DragEvent) => bind.onDragEnter(e)}
|
||||
onDragLeave={(editor, e: any) => bind.onDragLeave(e)}
|
||||
onDragOver={(editor, e: any) => bind.onDragOver(e)}
|
||||
onDrop={(editor, e: any) => bind.onDrop(e)}
|
||||
onDragEnter={(editor, e: any) => bind.onDragEnter(e)}
|
||||
/>
|
||||
{dragging && <SubmitDragger />}
|
||||
</Box>
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Box, Col, Row, Text } from '@tlon/indigo-react';
|
||||
import { Association, Graph } from '@urbit/api';
|
||||
import React, { ReactElement } from 'react';
|
||||
import { Box, Button, Col, Row, Text } from '@tlon/indigo-react';
|
||||
import { Association, Graph, readGraph } from '@urbit/api';
|
||||
import React, { ReactElement, useCallback } from 'react';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { useShowNickname } from '~/logic/lib/util';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import airlock from '~/logic/api';
|
||||
import { NotebookPosts } from './NotebookPosts';
|
||||
|
||||
interface NotebookProps {
|
||||
@ -28,12 +29,15 @@ export function Notebook(props: NotebookProps & RouteComponentProps): ReactEleme
|
||||
const contacts = useContactState(state => state.contacts);
|
||||
|
||||
const group = groups[association?.group];
|
||||
const relativePath = (p: string) => props.baseUrl + p;
|
||||
|
||||
const contact = contacts?.[`~${ship}`];
|
||||
|
||||
const showNickname = useShowNickname(contact);
|
||||
|
||||
const readBook = useCallback(() => {
|
||||
airlock.poke(readGraph(association.resource));
|
||||
}, [association.resource]);
|
||||
|
||||
if (!group) {
|
||||
return null; // Waiting on groups to populate
|
||||
}
|
||||
@ -48,6 +52,7 @@ export function Notebook(props: NotebookProps & RouteComponentProps): ReactEleme
|
||||
{showNickname ? contact?.nickname : ship}
|
||||
</Text>
|
||||
</Box>
|
||||
<Button onClick={readBook}>Mark all as Read</Button>
|
||||
</Row>
|
||||
<Box borderBottom={1} borderBottomColor="lightGray" />
|
||||
<NotebookPosts
|
||||
|
@ -32,7 +32,9 @@ const StoreDebugger = (props: StoreDebuggerProps) => {
|
||||
let output: any = false;
|
||||
try {
|
||||
output = _.get(state, filterToTry, undefined);
|
||||
} catch (e) { }
|
||||
} catch (e) {
|
||||
console.log('filter failed');
|
||||
}
|
||||
if (output) {
|
||||
console.log(output);
|
||||
setText(objectToString(output));
|
||||
|
@ -103,6 +103,7 @@ export default function ShortcutSettings() {
|
||||
label="Cycle backward through channel list"
|
||||
/>
|
||||
<ChordInput id="hideSidebar" label="Show/hide group sidebar" />
|
||||
<ChordInput id="readGroup" label="Read all in a group" />
|
||||
</Box>
|
||||
<AsyncButton primary width="fit-content">Save Changes</AsyncButton>
|
||||
</Col>
|
||||
|
@ -244,7 +244,7 @@ const renderers = {
|
||||
return (
|
||||
<Text
|
||||
mono
|
||||
fontWeight='inherit'
|
||||
fontWeight="inherit"
|
||||
p={1}
|
||||
backgroundColor="washedGray"
|
||||
fontSize={0}
|
||||
@ -284,7 +284,11 @@ const renderers = {
|
||||
paragraph: ({ children }) => {
|
||||
return (
|
||||
<Box display="block">
|
||||
<Text fontSize={1} lineHeight="tall" style={{ 'overflowWrap': 'break-word' }}>
|
||||
<Text
|
||||
fontSize={1}
|
||||
lineHeight="tall"
|
||||
style={{ overflowWrap: 'break-word' }}
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
</Box>
|
||||
@ -309,7 +313,7 @@ const renderers = {
|
||||
className="clamp-message"
|
||||
display="block"
|
||||
borderRadius={1}
|
||||
fontWeight='inherit'
|
||||
fontWeight="inherit"
|
||||
mono
|
||||
fontSize={0}
|
||||
backgroundColor="washedGray"
|
||||
@ -342,20 +346,12 @@ const renderers = {
|
||||
'graph-mention': ({ ship }) => <Mention ship={ship} />,
|
||||
image: ({ url, tall }) => (
|
||||
<Box mt="1" mb="2" flexShrink={0}>
|
||||
<RemoteContent
|
||||
key={url}
|
||||
url={url}
|
||||
tall={tall}
|
||||
/>
|
||||
<RemoteContent key={url} url={url} tall={tall} />
|
||||
</Box>
|
||||
),
|
||||
'graph-url': ({ url, tall }) => (
|
||||
<Box mt={1} mb={2} flexShrink={0}>
|
||||
<RemoteContent
|
||||
key={url}
|
||||
url={url}
|
||||
tall={tall}
|
||||
/>
|
||||
<RemoteContent key={url} url={url} tall={tall} />
|
||||
</Box>
|
||||
),
|
||||
'graph-reference': ({ reference, transcluded }) => {
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { AppName } from '@urbit/api';
|
||||
import { AppName, readGroup } from '@urbit/api';
|
||||
import _ from 'lodash';
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import {
|
||||
Route,
|
||||
RouteComponentProps, Switch
|
||||
} from 'react-router-dom';
|
||||
import { useShortcut } from '~/logic/state/settings';
|
||||
import { useLocalStorageState } from '~/logic/lib/useLocalStorageState';
|
||||
import { getGroupFromWorkspace } from '~/logic/lib/workspace';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
@ -25,6 +26,7 @@ import { NewChannel } from './NewChannel';
|
||||
import { PopoverRoutes } from './PopoverRoutes';
|
||||
import { Resource } from './Resource';
|
||||
import { Skeleton } from './Skeleton';
|
||||
import airlock from '~/logic/api';
|
||||
|
||||
type GroupsPaneProps = StoreState & {
|
||||
baseUrl: string;
|
||||
@ -40,6 +42,12 @@ export function GroupsPane(props: GroupsPaneProps) {
|
||||
const groupPath = getGroupFromWorkspace(workspace);
|
||||
const groups = useGroupState(state => state.groups);
|
||||
|
||||
useShortcut('readGroup', useCallback(() => {
|
||||
if(groupPath) {
|
||||
airlock.poke(readGroup(groupPath));
|
||||
}
|
||||
}, [groupPath]));
|
||||
|
||||
const groupAssociation =
|
||||
(groupPath && associations.groups[groupPath]) || undefined;
|
||||
const group = (groupPath && groups[groupPath]) || undefined;
|
||||
|
@ -102,8 +102,10 @@ export function SidebarDmItem(props: {
|
||||
}) {
|
||||
const { ship, selected = false } = props;
|
||||
const contact = useContact(ship);
|
||||
const title = contact?.nickname || (cite(ship) ?? ship);
|
||||
const hideAvatars = false;
|
||||
const { hideAvatars, hideNicknames } = useSettingsState(s => s.calm);
|
||||
const title = (!hideNicknames && contact?.nickname)
|
||||
? contact?.nickname
|
||||
: (cite(ship) ?? ship);
|
||||
const { unreads } = useHarkDm(ship) || { unreads: 0 };
|
||||
const img =
|
||||
contact?.avatar && !hideAvatars ? (
|
||||
@ -131,7 +133,7 @@ export function SidebarDmItem(props: {
|
||||
hasUnread={(unreads as number) > 0}
|
||||
to={`/~landscape/messages/dm/${ship}`}
|
||||
title={title}
|
||||
mono={!contact?.nickname}
|
||||
mono={hideAvatars || !contact?.nickname}
|
||||
isSynced
|
||||
>
|
||||
{img}
|
||||
|
@ -20,7 +20,7 @@ function sidebarSort(
|
||||
const alphabetical = (a: string, b: string) => {
|
||||
const aAssoc = associations[a];
|
||||
const bAssoc = associations[b];
|
||||
const aTitle = aAssoc?.metadata?.title || b;
|
||||
const aTitle = aAssoc?.metadata?.title || a;
|
||||
const bTitle = bAssoc?.metadata?.title || b;
|
||||
|
||||
return alphabeticalOrder(aTitle, bTitle);
|
||||
@ -33,8 +33,9 @@ function sidebarSort(
|
||||
const bAppName = bAssoc?.['app-name'];
|
||||
|
||||
const aUpdated = a.startsWith('~')
|
||||
? (inboxUnreads?.[`/${patp2dec(a)}`]?.last)
|
||||
? (inboxUnreads?.[`/${patp2dec(a)}`]?.last || 0)
|
||||
: (apps[aAppName]?.lastUpdated(a) || 0);
|
||||
|
||||
const bUpdated = b.startsWith('~')
|
||||
? (inboxUnreads?.[`/${patp2dec(b)}`]?.last || 0)
|
||||
: (apps[bAppName]?.lastUpdated(b) || 0);
|
||||
@ -108,14 +109,19 @@ export function SidebarList(props: {
|
||||
const offset = backward ? -1 : 1;
|
||||
|
||||
const newIdx = modulo(idx+offset, ordered.length - 1);
|
||||
const { metadata, resource } = associations[ordered[newIdx]];
|
||||
const joined = graphKeys.has(resource.slice(7));
|
||||
let path = '/~landscape/home';
|
||||
if ('graph' in metadata.config) {
|
||||
path = getResourcePath(workspace, resource, joined, metadata.config.graph);
|
||||
const newChannel = ordered[newIdx];
|
||||
let path = '';
|
||||
if(newChannel.startsWith('~')) {
|
||||
path = `/~landscape/messages/dm/${newChannel}`;
|
||||
} else {
|
||||
const { metadata, resource } = associations.graph[ordered[newIdx]];
|
||||
const joined = graphKeys.has(resource.slice(7));
|
||||
if ('graph' in metadata.config) {
|
||||
path = getResourcePath(workspace, resource, joined, metadata.config.graph);
|
||||
}
|
||||
}
|
||||
history.push(path);
|
||||
}, [selected, history.push]);
|
||||
}, [ordered, selected, history.push]);
|
||||
|
||||
useShortcut('cycleForward', useCallback((e: KeyboardEvent) => {
|
||||
cycleChannels(false);
|
||||
|
@ -243,3 +243,20 @@ export const getNotificationCount = (
|
||||
.map(index => unread[index]?.notifications as number || 0)
|
||||
.reduce(f.add, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all graphs belonging to a particular group
|
||||
*/
|
||||
export const readGroup = (group: string) =>
|
||||
harkAction({
|
||||
'read-group': group
|
||||
});
|
||||
|
||||
/**
|
||||
* Read all unreads in a graph
|
||||
*/
|
||||
export const readGraph = (graph: string) =>
|
||||
harkAction({
|
||||
'read-graph': graph
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user