mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-21 05:41:43 +03:00
Merge branch 'master' into release/next-vere
* master: (151 commits) build: check subdirs on tsc meta: auto-deploy release/next-userspace glob: update to 0v4.vrvkt.4gcnm.dgg5o.e73d6.kqnaq OmniboxResult: fix arg order glob: update to 0v3.p4se6.4k5i0.8v0le.v5vn4.mdotq hooks: reset diplomacy interface: package audit interface: stringify number prop graph: added comments links: remove stray semicolon graph-push-hook: only cache marks, do not cache metadata for a graph graph-push-hook: code style cleaning push-hook: clean-up code style graph-store: internally cache all scried daises graph-push-hook: rename mark for cache action demo-push-hook: update for new push-hook interface hover permalinks: add group peer space notifications: key notifications correctly DeleteGroup: fix copy ...
This commit is contained in:
commit
68a19287ab
2
.github/workflows/glob.yml
vendored
2
.github/workflows/glob.yml
vendored
@ -2,7 +2,7 @@ name: glob
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'release/next-js'
|
- 'release/next-userspace'
|
||||||
jobs:
|
jobs:
|
||||||
glob:
|
glob:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
4
.github/workflows/merge-master.yml
vendored
4
.github/workflows/merge-master.yml
vendored
@ -6,13 +6,13 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
merge-to-next-js:
|
merge-to-next-js:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: "Merge master to release/next-js"
|
name: "Merge master to release/next-userspace"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: devmasx/merge-branch@v1.3.1
|
- uses: devmasx/merge-branch@v1.3.1
|
||||||
with:
|
with:
|
||||||
type: now
|
type: now
|
||||||
target_branch: release/next-js
|
target_branch: release/next-userspace
|
||||||
github_token: ${{ secrets.JANEWAY_BOT_TOKEN }}
|
github_token: ${{ secrets.JANEWAY_BOT_TOKEN }}
|
||||||
|
|
||||||
merge-to-group-timer:
|
merge-to-group-timer:
|
||||||
|
14
.github/workflows/typescript-check.yml
vendored
Normal file
14
.github/workflows/typescript-check.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
name: typescript-check
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'pkg/interface/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
typescript-check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: "Check pkg/interface types"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: cd 'pkg/interface' && npm i && npm run tsc
|
@ -309,9 +309,9 @@ the new binary, and restarting the pier with it.
|
|||||||
#### Continuous deployment
|
#### Continuous deployment
|
||||||
|
|
||||||
A subset of release branches are deployed continuously to the network. Thus far
|
A subset of release branches are deployed continuously to the network. Thus far
|
||||||
this only includes `release/next-js`, which deploys livenet-compatible
|
this only includes `release/next-userspace`, which deploys livenet-compatible
|
||||||
JavaScript changes to select QA ships. Any push to master will automatically
|
changes to select QA ships. Any push to master will automatically
|
||||||
merge master into `release/next-js` to keep the streams at parity.
|
merge master into `release/next-userspace` to keep the streams at parity.
|
||||||
|
|
||||||
### Announce the update
|
### Announce the update
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:e1656cbfd472430c463db4e968c1dd4c8894a5219a27cd301a70ad262f5999f1
|
oid sha256:d7b7cf24e56ab078cf1dcb82e4e7744f188c5221c08772d6cfb15f59ce81aaa5
|
||||||
size 10610939
|
size 11198219
|
||||||
|
@ -1394,8 +1394,6 @@
|
|||||||
^+ this
|
^+ this
|
||||||
?: =(~ dom)
|
?: =(~ dom)
|
||||||
~|(%acme-empty-certificate-order !!)
|
~|(%acme-empty-certificate-order !!)
|
||||||
?: ?=(?(%earl %pawn) (clan:title our.bow))
|
|
||||||
this
|
|
||||||
=. ..emit (queue-next-order 1 | dom)
|
=. ..emit (queue-next-order 1 | dom)
|
||||||
=. ..emit cancel-current-order
|
=. ..emit cancel-current-order
|
||||||
:: notify %dill
|
:: notify %dill
|
||||||
|
@ -738,6 +738,7 @@
|
|||||||
::
|
::
|
||||||
?. (is-chat-graph target)
|
?. (is-chat-graph target)
|
||||||
[[(note:sh-out "no such chat")]~ put-ses]
|
[[(note:sh-out "no such chat")]~ put-ses]
|
||||||
|
=. audience target
|
||||||
=. viewing (~(put in viewing) target)
|
=. viewing (~(put in viewing) target)
|
||||||
=^ cards state
|
=^ cards state
|
||||||
?: (~(has by bound) target)
|
?: (~(has by bound) target)
|
||||||
|
@ -70,10 +70,11 @@
|
|||||||
::
|
::
|
||||||
++ transform-proxy-update
|
++ transform-proxy-update
|
||||||
|= vas=vase
|
|= vas=vase
|
||||||
^- (unit vase)
|
^- (quip card (unit vase))
|
||||||
:: TODO: should check if user is allowed to %add, %remove, %edit
|
:: TODO: should check if user is allowed to %add, %remove, %edit
|
||||||
:: contact
|
:: contact
|
||||||
=/ =update:store !<(update:store vas)
|
=/ =update:store !<(update:store vas)
|
||||||
|
:- ~
|
||||||
?- -.update
|
?- -.update
|
||||||
%initial ~
|
%initial ~
|
||||||
%add `vas
|
%add `vas
|
||||||
|
@ -43,8 +43,8 @@
|
|||||||
::
|
::
|
||||||
++ transform-proxy-update
|
++ transform-proxy-update
|
||||||
|= vas=vase
|
|= vas=vase
|
||||||
^- (unit vase)
|
^- (quip card (unit vase))
|
||||||
`vas
|
``vas
|
||||||
::
|
::
|
||||||
++ resource-for-update
|
++ resource-for-update
|
||||||
|= =vase
|
|= =vase
|
||||||
|
@ -188,8 +188,11 @@
|
|||||||
?: ?=([%'~landscape' %js %session ~] site.req-line)
|
?: ?=([%'~landscape' %js %session ~] site.req-line)
|
||||||
%+ require-authorization-simple:app
|
%+ require-authorization-simple:app
|
||||||
inbound-request
|
inbound-request
|
||||||
%- js-response:gen
|
%. %- as-octs:mimes:html
|
||||||
(as-octt:mimes:html "window.ship = '{+:(scow %p our.bowl)}';")
|
(rap 3 'window.ship = "' (rsh 3 (scot %p our.bowl)) '";' ~)
|
||||||
|
%* . js-response:gen
|
||||||
|
cache %.n
|
||||||
|
==
|
||||||
::
|
::
|
||||||
=/ [payload=simple-payload:http public=?] (get-file req-line is-file)
|
=/ [payload=simple-payload:http public=?] (get-file req-line is-file)
|
||||||
?: public payload
|
?: public payload
|
||||||
@ -222,6 +225,7 @@
|
|||||||
[~ %js] (js-response:gen file)
|
[~ %js] (js-response:gen file)
|
||||||
[~ %css] (css-response:gen file)
|
[~ %css] (css-response:gen file)
|
||||||
[~ %png] (png-response:gen file)
|
[~ %png] (png-response:gen file)
|
||||||
|
[~ %ico] (ico-response:gen file)
|
||||||
::
|
::
|
||||||
[~ %html]
|
[~ %html]
|
||||||
%. file
|
%. file
|
||||||
@ -238,11 +242,9 @@
|
|||||||
[not-found:gen %.n]
|
[not-found:gen %.n]
|
||||||
:_ public.u.content
|
:_ public.u.content
|
||||||
=/ mime-type=@t (rsh 3 (crip <p.u.data>))
|
=/ mime-type=@t (rsh 3 (crip <p.u.data>))
|
||||||
:: Should maybe inspect to see how long cache should hold
|
|
||||||
::
|
|
||||||
=/ headers
|
=/ headers
|
||||||
:~ content-type+mime-type
|
:~ content-type+mime-type
|
||||||
max-1-da:gen
|
max-1-wk:gen
|
||||||
'service-worker-allowed'^'/'
|
'service-worker-allowed'^'/'
|
||||||
==
|
==
|
||||||
[[200 headers] `q.u.data]
|
[[200 headers] `q.u.data]
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/- glob
|
/- glob
|
||||||
/+ default-agent, verb, dbug
|
/+ default-agent, verb, dbug
|
||||||
|%
|
|%
|
||||||
++ hash 0v7.dmf2h.884m6.b2p1b.l1and.uv1lv
|
++ hash 0v4.vrvkt.4gcnm.dgg5o.e73d6.kqnaq
|
||||||
+$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))]
|
+$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))]
|
||||||
+$ all-states
|
+$ all-states
|
||||||
$% state-0
|
$% state-0
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/- *group, metadata=metadata-store
|
/- *group, metadata=metadata-store
|
||||||
/+ store=graph-store, mdl=metadata, res=resource, graph, group, default-agent,
|
/+ store=graph-store, mdl=metadata, res=resource, graph, group, default-agent,
|
||||||
dbug, verb, push-hook
|
dbug, verb, push-hook, agentio
|
||||||
::
|
::
|
||||||
~% %graph-push-hook-top ..part ~
|
~% %graph-push-hook-top ..part ~
|
||||||
|%
|
|%
|
||||||
@ -25,6 +25,25 @@
|
|||||||
$% state-zero
|
$% state-zero
|
||||||
state-one
|
state-one
|
||||||
==
|
==
|
||||||
|
::
|
||||||
|
:: TODO: come back to this and potentially use send a %t
|
||||||
|
:: to be notified of validator changes
|
||||||
|
+$ cache
|
||||||
|
$: graph-to-mark=(map resource:res (unit mark))
|
||||||
|
perm-marks=(map [mark @tas] tube:clay)
|
||||||
|
transform-marks=(map mark tube:clay)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ inflated-state
|
||||||
|
$: state-one
|
||||||
|
cache
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ cache-action
|
||||||
|
$% [%graph-to-mark (pair resource:res (unit mark))]
|
||||||
|
[%perm-marks (pair (pair mark @tas) tube:clay)]
|
||||||
|
[%transform-marks (pair mark tube:clay)]
|
||||||
|
==
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
%- agent:dbug
|
%- agent:dbug
|
||||||
@ -33,7 +52,8 @@
|
|||||||
%- (agent:push-hook config)
|
%- (agent:push-hook config)
|
||||||
^- agent
|
^- agent
|
||||||
=-
|
=-
|
||||||
=| state-one
|
~% %graph-push-hook-agent ..scry.hook-core ~
|
||||||
|
=| inflated-state
|
||||||
=* state -
|
=* state -
|
||||||
|_ =bowl:gall
|
|_ =bowl:gall
|
||||||
+* this .
|
+* this .
|
||||||
@ -41,10 +61,11 @@
|
|||||||
grp ~(. group bowl)
|
grp ~(. group bowl)
|
||||||
gra ~(. graph bowl)
|
gra ~(. graph bowl)
|
||||||
met ~(. mdl bowl)
|
met ~(. mdl bowl)
|
||||||
hc ~(. hook-core bowl)
|
hc ~(. hook-core bowl +.state)
|
||||||
|
io ~(. agentio bowl)
|
||||||
::
|
::
|
||||||
++ on-init on-init:def
|
++ on-init on-init:def
|
||||||
++ on-save !>(state)
|
++ on-save !>(-.state)
|
||||||
++ on-load
|
++ on-load
|
||||||
|= =vase
|
|= =vase
|
||||||
=+ !<(old=versioned-state vase)
|
=+ !<(old=versioned-state vase)
|
||||||
@ -53,9 +74,26 @@
|
|||||||
=? old ?=(%0 -.old)
|
=? old ?=(%0 -.old)
|
||||||
[%1 ~]
|
[%1 ~]
|
||||||
?> ?=(%1 -.old)
|
?> ?=(%1 -.old)
|
||||||
`this(state old)
|
`this(-.state old, +.state *cache)
|
||||||
|
::
|
||||||
|
++ on-poke
|
||||||
|
|= [=mark =vase]
|
||||||
|
^- (quip card _this)
|
||||||
|
?. =(mark %graph-cache-hook)
|
||||||
|
[~ this]
|
||||||
|
=/ a=cache-action !<(cache-action vase)
|
||||||
|
=* c +.state
|
||||||
|
=* graph-to-mark graph-to-mark.c
|
||||||
|
=* perm-marks perm-marks.c
|
||||||
|
=* transform-marks transform-marks.c
|
||||||
|
=. c
|
||||||
|
?- -.a
|
||||||
|
%graph-to-mark c(graph-to-mark (~(put by graph-to-mark) p.a q.a))
|
||||||
|
%perm-marks c(perm-marks (~(put by perm-marks) p.a q.a))
|
||||||
|
%transform-marks c(transform-marks (~(put by transform-marks) p.a q.a))
|
||||||
|
==
|
||||||
|
[~ this(+.state c)]
|
||||||
::
|
::
|
||||||
++ on-poke on-poke:def
|
|
||||||
++ on-agent on-agent:def
|
++ on-agent on-agent:def
|
||||||
++ on-watch on-watch:def
|
++ on-watch on-watch:def
|
||||||
++ on-leave on-leave:def
|
++ on-leave on-leave:def
|
||||||
@ -72,22 +110,39 @@
|
|||||||
::
|
::
|
||||||
++ on-fail on-fail:def
|
++ on-fail on-fail:def
|
||||||
++ transform-proxy-update
|
++ transform-proxy-update
|
||||||
|
~/ %transform-proxy-update
|
||||||
|= vas=vase
|
|= vas=vase
|
||||||
^- (unit vase)
|
^- (quip card (unit vase))
|
||||||
=/ =update:store !<(update:store vas)
|
=/ =update:store !<(update:store vas)
|
||||||
=* rid resource.q.update
|
=* rid resource.q.update
|
||||||
=. p.update now.bowl
|
=. p.update now.bowl
|
||||||
?- -.q.update
|
?- -.q.update
|
||||||
%add-nodes
|
%add-nodes
|
||||||
?. (is-allowed-add:hc rid nodes.q.update)
|
=| cards=(list card)
|
||||||
~
|
=^ allowed cards (is-allowed-add:hc rid nodes.q.update)
|
||||||
=/ mark (get-mark:gra rid)
|
?. allowed
|
||||||
?~ mark `vas
|
[cards ~]
|
||||||
|^
|
=/ mark-cached (~(has by graph-to-mark) rid)
|
||||||
|
=/ mark
|
||||||
|
?: mark-cached
|
||||||
|
(~(got by graph-to-mark) rid)
|
||||||
|
(get-mark:gra rid)
|
||||||
|
?~ mark
|
||||||
|
[cards `vas]
|
||||||
|
=< $
|
||||||
|
~% %transform-add-nodes ..transform-proxy-update ~
|
||||||
|
|%
|
||||||
|
++ $
|
||||||
|
^- (quip card (unit vase))
|
||||||
|
=/ transform-cached (~(has by transform-marks) u.mark)
|
||||||
|
=/ =tube:clay
|
||||||
|
?: transform-cached
|
||||||
|
(~(got by transform-marks) u.mark)
|
||||||
|
.^(tube:clay (scry:hc %cc %home /[u.mark]/transform-add-nodes))
|
||||||
=/ transform
|
=/ transform
|
||||||
!< $-([index:store post:store atom ?] [index:store post:store])
|
!< $-([index:store post:store atom ?] [index:store post:store])
|
||||||
%. !>(*indexed-post:store)
|
%. !>(*indexed-post:store)
|
||||||
.^(tube:clay (scry:hc %cc %home /[u.mark]/transform-add-nodes))
|
tube
|
||||||
=/ [* result=(list [index:store node:store])]
|
=/ [* result=(list [index:store node:store])]
|
||||||
%+ roll
|
%+ roll
|
||||||
(flatten-node-map ~(tap by nodes.q.update))
|
(flatten-node-map ~(tap by nodes.q.update))
|
||||||
@ -95,9 +150,24 @@
|
|||||||
=. nodes.q.update
|
=. nodes.q.update
|
||||||
%- ~(gas by *(map index:store node:store))
|
%- ~(gas by *(map index:store node:store))
|
||||||
result
|
result
|
||||||
[~ !>(update)]
|
:_ [~ !>(update)]
|
||||||
|
%+ weld cards
|
||||||
|
%- zing
|
||||||
|
:~ ?: mark-cached ~
|
||||||
|
:_ ~
|
||||||
|
%+ poke-self:pass:io %graph-cache-hook
|
||||||
|
!> ^- cache-action
|
||||||
|
[%graph-to-mark rid mark]
|
||||||
|
::
|
||||||
|
?: transform-cached ~
|
||||||
|
:_ ~
|
||||||
|
%+ poke-self:pass:io %graph-cache-hook
|
||||||
|
!> ^- cache-action
|
||||||
|
[%transform-marks u.mark tube]
|
||||||
|
==
|
||||||
::
|
::
|
||||||
++ flatten-node-map
|
++ flatten-node-map
|
||||||
|
~/ %flatten-node-map
|
||||||
|= lis=(list [index:store node:store])
|
|= lis=(list [index:store node:store])
|
||||||
^- (list [index:store node:store])
|
^- (list [index:store node:store])
|
||||||
|^
|
|^
|
||||||
@ -129,6 +199,7 @@
|
|||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ transform-list
|
++ transform-list
|
||||||
|
~/ %transform-list
|
||||||
|= transform=$-([index:store post:store atom ?] [index:store post:store])
|
|= transform=$-([index:store post:store atom ?] [index:store post:store])
|
||||||
|= $: [=index:store =node:store]
|
|= $: [=index:store =node:store]
|
||||||
[indices=(set index:store) lis=(list [index:store node:store])]
|
[indices=(set index:store) lis=(list [index:store node:store])]
|
||||||
@ -151,27 +222,32 @@
|
|||||||
--
|
--
|
||||||
::
|
::
|
||||||
%remove-posts
|
%remove-posts
|
||||||
?. (is-allowed-remove:hc resource.q.update indices.q.update)
|
=| cards=(list card)
|
||||||
|
=^ allowed cards
|
||||||
|
(is-allowed-remove:hc rid indices.q.update)
|
||||||
|
:- cards
|
||||||
|
?. allowed
|
||||||
~
|
~
|
||||||
`vas
|
`vas
|
||||||
::
|
::
|
||||||
%add-graph ~
|
%add-graph [~ ~]
|
||||||
%remove-graph ~
|
%remove-graph [~ ~]
|
||||||
%add-signatures ~
|
%add-signatures [~ ~]
|
||||||
%remove-signatures ~
|
%remove-signatures [~ ~]
|
||||||
%archive-graph ~
|
%archive-graph [~ ~]
|
||||||
%unarchive-graph ~
|
%unarchive-graph [~ ~]
|
||||||
%add-tag ~
|
%add-tag [~ ~]
|
||||||
%remove-tag ~
|
%remove-tag [~ ~]
|
||||||
%keys ~
|
%keys [~ ~]
|
||||||
%tags ~
|
%tags [~ ~]
|
||||||
%tag-queries ~
|
%tag-queries [~ ~]
|
||||||
%run-updates ~
|
%run-updates [~ ~]
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ resource-for-update resource-for-update:gra
|
++ resource-for-update resource-for-update:gra
|
||||||
::
|
::
|
||||||
++ initial-watch
|
++ initial-watch
|
||||||
|
~/ %initial-watch
|
||||||
|= [=path =resource:res]
|
|= [=path =resource:res]
|
||||||
^- vase
|
^- vase
|
||||||
|^
|
|^
|
||||||
@ -211,11 +287,13 @@
|
|||||||
==
|
==
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
^| ^= hook-core
|
~% %graph-push-hook-helper ..card.hook-core ~
|
||||||
|_ =bowl:gall
|
^= hook-core
|
||||||
|
|_ [=bowl:gall =cache]
|
||||||
+* grp ~(. group bowl)
|
+* grp ~(. group bowl)
|
||||||
met ~(. mdl bowl)
|
met ~(. mdl bowl)
|
||||||
gra ~(. graph bowl)
|
gra ~(. graph bowl)
|
||||||
|
io ~(. agentio bowl)
|
||||||
::
|
::
|
||||||
++ scry
|
++ scry
|
||||||
|= [care=@t desk=@t =path]
|
|= [care=@t desk=@t =path]
|
||||||
@ -225,14 +303,38 @@
|
|||||||
::
|
::
|
||||||
++ perm-mark
|
++ perm-mark
|
||||||
|= [=resource:res perm=@t vip=vip-metadata:metadata =indexed-post:store]
|
|= [=resource:res perm=@t vip=vip-metadata:metadata =indexed-post:store]
|
||||||
^- permissions:store
|
^- [permissions:store (list card)]
|
||||||
|^
|
|^
|
||||||
=- (check vip)
|
=/ mark-cached (~(has by graph-to-mark.cache) resource)
|
||||||
!< check=$-(vip-metadata:metadata permissions:store)
|
=/ mark
|
||||||
%. !>(indexed-post)
|
?: mark-cached
|
||||||
=/ mark (get-mark:gra resource)
|
(~(got by graph-to-mark.cache) resource)
|
||||||
?~ mark |=(=vase !>([%no %no %no]))
|
(get-mark:gra resource)
|
||||||
|
?~ mark
|
||||||
|
[[%no %no %no] ~]
|
||||||
|
=/ key [u.mark (perm-mark-name perm)]
|
||||||
|
=/ perms-cached (~(has by perm-marks.cache) key)
|
||||||
|
=/ =tube:clay
|
||||||
|
?: perms-cached
|
||||||
|
(~(got by perm-marks.cache) key)
|
||||||
.^(tube:clay (scry %cc %home /[u.mark]/(perm-mark-name perm)))
|
.^(tube:clay (scry %cc %home /[u.mark]/(perm-mark-name perm)))
|
||||||
|
=/ check
|
||||||
|
!< $-(vip-metadata:metadata permissions:store)
|
||||||
|
(tube !>(indexed-post))
|
||||||
|
:- (check vip)
|
||||||
|
%- zing
|
||||||
|
:~ ?: mark-cached ~
|
||||||
|
:_ ~
|
||||||
|
%+ poke-self:pass:io %graph-cache-hook
|
||||||
|
!> ^- cache-action
|
||||||
|
[%graph-to-mark resource mark]
|
||||||
|
::
|
||||||
|
?: perms-cached ~
|
||||||
|
:_ ~
|
||||||
|
%+ poke-self:pass:io %graph-cache-hook
|
||||||
|
!> ^- cache-action
|
||||||
|
[%perm-marks [u.mark (perm-mark-name perm)] tube]
|
||||||
|
==
|
||||||
::
|
::
|
||||||
++ perm-mark-name
|
++ perm-mark-name
|
||||||
|= perm=@t
|
|= perm=@t
|
||||||
@ -252,15 +354,22 @@
|
|||||||
reader.permissions
|
reader.permissions
|
||||||
::
|
::
|
||||||
++ get-roles-writers-variation
|
++ get-roles-writers-variation
|
||||||
|
~/ %get-roles-writers-variation
|
||||||
|= =resource:res
|
|= =resource:res
|
||||||
^- (unit [is-admin=? writers=(set ship) vip=vip-metadata:metadata])
|
^- (unit [is-admin=? writers=(set ship) vip=vip-metadata:metadata])
|
||||||
=/ assoc=(unit association:metadata)
|
=/ assoc=(unit association:metadata)
|
||||||
(peek-association:met %graph resource)
|
(peek-association:met %graph resource)
|
||||||
?~ assoc ~
|
?~ assoc ~
|
||||||
|
=/ group=(unit group:grp)
|
||||||
|
(scry-group:grp group.u.assoc)
|
||||||
|
?~ group ~
|
||||||
=/ role=(unit (unit role-tag))
|
=/ role=(unit (unit role-tag))
|
||||||
(role-for-ship:grp group.u.assoc src.bowl)
|
(role-for-ship-with-group:grp u.group group.u.assoc src.bowl)
|
||||||
=/ writers=(set ship)
|
=/ writers=(set ship)
|
||||||
(get-tagged-ships:grp group.u.assoc [%graph resource %writers])
|
%^ get-tagged-ships-with-group:grp
|
||||||
|
u.group
|
||||||
|
group.u.assoc
|
||||||
|
[%graph resource %writers]
|
||||||
?~ role ~
|
?~ role ~
|
||||||
=/ is-admin=?
|
=/ is-admin=?
|
||||||
?=(?([~ %admin] [~ %moderator]) u.role)
|
?=(?([~ %admin] [~ %moderator]) u.role)
|
||||||
@ -274,28 +383,47 @@
|
|||||||
[(snag (dec (lent index)) index) p.post.node]
|
[(snag (dec (lent index)) index) p.post.node]
|
||||||
::
|
::
|
||||||
++ is-allowed-add
|
++ is-allowed-add
|
||||||
|
~/ %is-allowed-add
|
||||||
|= [=resource:res nodes=(map index:store node:store)]
|
|= [=resource:res nodes=(map index:store node:store)]
|
||||||
^- ?
|
^- [? (list card)]
|
||||||
|^
|
|^
|
||||||
%- (bond |.(%.n))
|
%- (bond |.([%.n ~]))
|
||||||
%+ biff (get-roles-writers-variation resource)
|
%+ biff (get-roles-writers-variation resource)
|
||||||
|= [is-admin=? writers=(set ship) vip=vip-metadata:metadata]
|
|= [is-admin=? writers=(set ship) vip=vip-metadata:metadata]
|
||||||
^- (unit ?)
|
^- (unit [? (list card)])
|
||||||
%- some
|
%- some
|
||||||
%+ levy ~(tap by nodes)
|
=/ a ~(tap by nodes)
|
||||||
|= [=index:store =node:store]
|
=| cards=(list card)
|
||||||
|
|- ^- [? (list card)]
|
||||||
|
?~ a [& cards]
|
||||||
|
=/ c (check i.a is-admin writers vip)
|
||||||
|
?. -.c
|
||||||
|
[| (weld cards +.c)]
|
||||||
|
$(a t.a, cards (weld cards +.c))
|
||||||
|
::
|
||||||
|
++ check
|
||||||
|
|= $: [=index:store =node:store]
|
||||||
|
is-admin=?
|
||||||
|
writers=(set ship)
|
||||||
|
vip=vip-metadata:metadata
|
||||||
|
==
|
||||||
|
^- [? (list card)]
|
||||||
=/ parent-index=index:store
|
=/ parent-index=index:store
|
||||||
(scag (dec (lent index)) index)
|
(scag (dec (lent index)) index)
|
||||||
?: (~(has by nodes) parent-index) %.y
|
?: (~(has by nodes) parent-index)
|
||||||
|
[%.y ~]
|
||||||
?: ?=(%| -.post.node)
|
?: ?=(%| -.post.node)
|
||||||
%.n
|
[%.n ~]
|
||||||
?. =(author.p.post.node src.bowl)
|
?. =(author.p.post.node src.bowl)
|
||||||
%.n
|
[%.n ~]
|
||||||
=/ =permissions:store
|
=/ added
|
||||||
%^ add-mark resource vip
|
%^ add-mark resource vip
|
||||||
(node-to-indexed-post node)
|
(node-to-indexed-post node)
|
||||||
|
=* permissions -.added
|
||||||
|
=* cards +.added
|
||||||
=/ =permission-level:store
|
=/ =permission-level:store
|
||||||
(get-permission permissions is-admin writers)
|
(get-permission permissions is-admin writers)
|
||||||
|
:_ cards
|
||||||
?- permission-level
|
?- permission-level
|
||||||
%yes %.y
|
%yes %.y
|
||||||
%no %.n
|
%no %.n
|
||||||
@ -314,24 +442,38 @@
|
|||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ is-allowed-remove
|
++ is-allowed-remove
|
||||||
|
~/ %is-allowed-remove
|
||||||
|= [=resource:res indices=(set index:store)]
|
|= [=resource:res indices=(set index:store)]
|
||||||
^- ?
|
^- [? (list card)]
|
||||||
|^
|
|^
|
||||||
%- (bond |.(%.n))
|
%- (bond |.([%.n ~]))
|
||||||
%+ biff (get-roles-writers-variation resource)
|
%+ biff (get-roles-writers-variation resource)
|
||||||
|= [is-admin=? writers=(set ship) vip=vip-metadata:metadata]
|
|= [is-admin=? writers=(set ship) vip=vip-metadata:metadata]
|
||||||
%- some
|
%- some
|
||||||
%+ levy ~(tap by indices)
|
=/ a ~(tap by indices)
|
||||||
|= =index:store
|
=| cards=(list card)
|
||||||
^- ?
|
|- ^- [? (list card)]
|
||||||
|
?~ a [& cards]
|
||||||
|
=/ c (check i.a is-admin writers vip)
|
||||||
|
?. -.c
|
||||||
|
[| (weld cards +.c)]
|
||||||
|
$(a t.a, cards (weld cards +.c))
|
||||||
|
::
|
||||||
|
++ check
|
||||||
|
|= [=index:store is-admin=? writers=(set ship) vip=vip-metadata:metadata]
|
||||||
|
^- [? (list card)]
|
||||||
=/ =node:store
|
=/ =node:store
|
||||||
(got-node:gra resource index)
|
(got-node:gra resource index)
|
||||||
?: ?=(%| -.post.node) %.n
|
?: ?=(%| -.post.node)
|
||||||
=/ =permissions:store
|
[%.n ~]
|
||||||
|
=/ removed
|
||||||
%^ remove-mark resource vip
|
%^ remove-mark resource vip
|
||||||
(node-to-indexed-post node)
|
(node-to-indexed-post node)
|
||||||
|
=* permissions -.removed
|
||||||
|
=* cards +.removed
|
||||||
=/ =permission-level:store
|
=/ =permission-level:store
|
||||||
(get-permission permissions is-admin writers)
|
(get-permission permissions is-admin writers)
|
||||||
|
:_ cards
|
||||||
?- permission-level
|
?- permission-level
|
||||||
%yes %.y
|
%yes %.y
|
||||||
%no %.n
|
%no %.n
|
||||||
|
@ -10,16 +10,28 @@
|
|||||||
[%1 network:zero:store]
|
[%1 network:zero:store]
|
||||||
[%2 network:zero:store]
|
[%2 network:zero:store]
|
||||||
[%3 network:one:store]
|
[%3 network:one:store]
|
||||||
state-4
|
[%4 network:store]
|
||||||
|
state-5
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
+$ state-4 [%4 network:store]
|
+$ state-5 [%5 network:store]
|
||||||
++ orm orm:store
|
++ orm orm:store
|
||||||
++ orm-log orm-log:store
|
++ orm-log orm-log:store
|
||||||
+$ debug-input [%validate-graph =resource:store]
|
+$ debug-input [%validate-graph =resource:store]
|
||||||
|
::
|
||||||
|
+$ cache
|
||||||
|
$: validators=(map mark dais:clay)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
:: TODO: come back to this and potentially use ford runes or otherwise
|
||||||
|
:: send a %t to be notified of validator changes
|
||||||
|
+$ inflated-state
|
||||||
|
$: state-5
|
||||||
|
cache
|
||||||
|
==
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
=| state-4
|
=| inflated-state
|
||||||
=* state -
|
=* state -
|
||||||
::
|
::
|
||||||
%- agent:dbug
|
%- agent:dbug
|
||||||
@ -31,7 +43,7 @@
|
|||||||
def ~(. (default-agent this %|) bowl)
|
def ~(. (default-agent this %|) bowl)
|
||||||
::
|
::
|
||||||
++ on-init [~ this]
|
++ on-init [~ this]
|
||||||
++ on-save !>(state)
|
++ on-save !>(-.state)
|
||||||
++ on-load
|
++ on-load
|
||||||
|= =old=vase
|
|= =old=vase
|
||||||
^- (quip card _this)
|
^- (quip card _this)
|
||||||
@ -91,7 +103,23 @@
|
|||||||
|=(a=* *update-log:store)
|
|=(a=* *update-log:store)
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
%4 [cards this(state old)]
|
%4
|
||||||
|
%_ $
|
||||||
|
-.old %5
|
||||||
|
::
|
||||||
|
update-logs.old
|
||||||
|
%- ~(gas by *update-logs:store)
|
||||||
|
%+ turn ~(tap by graphs.old)
|
||||||
|
|= [=resource:store =graph:store mar=(unit mark)]
|
||||||
|
:- resource
|
||||||
|
=/ log (~(got by update-logs.old) resource)
|
||||||
|
?. =(~ log) log
|
||||||
|
=/ =logged-update:store
|
||||||
|
[now.bowl %add-graph resource graph mar %.y]
|
||||||
|
(gas:orm-log ~ [now.bowl logged-update] ~)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
%5 [cards this(-.state old, +.state *cache)]
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ on-watch
|
++ on-watch
|
||||||
@ -163,7 +191,9 @@
|
|||||||
!(~(has by graphs) resource)
|
!(~(has by graphs) resource)
|
||||||
== ==
|
== ==
|
||||||
~| "validation of graph {<resource>} failed using mark {<mark>}"
|
~| "validation of graph {<resource>} failed using mark {<mark>}"
|
||||||
?> (validate-graph graph mark)
|
=^ is-valid state
|
||||||
|
(validate-graph graph mark)
|
||||||
|
?> is-valid
|
||||||
=/ =logged-update:store
|
=/ =logged-update:store
|
||||||
[time %add-graph resource graph mark overwrite]
|
[time %add-graph resource graph mark overwrite]
|
||||||
=/ =update-log:store
|
=/ =update-log:store
|
||||||
@ -200,6 +230,10 @@
|
|||||||
(~(got by graphs) resource)
|
(~(got by graphs) resource)
|
||||||
~| "cannot add duplicate nodes to {<resource>}"
|
~| "cannot add duplicate nodes to {<resource>}"
|
||||||
?< (check-for-duplicates graph ~(key by nodes))
|
?< (check-for-duplicates graph ~(key by nodes))
|
||||||
|
~| "validation of nodes failed using mark {<mark>}"
|
||||||
|
=^ is-valid state
|
||||||
|
(check-validity ~(tap by nodes) mark)
|
||||||
|
?> is-valid
|
||||||
=/ =update-log:store (~(got by update-logs) resource)
|
=/ =update-log:store (~(got by update-logs) resource)
|
||||||
=. update-log
|
=. update-log
|
||||||
(put:orm-log update-log time [time [%add-nodes resource nodes]])
|
(put:orm-log update-log time [time [%add-nodes resource nodes]])
|
||||||
@ -214,6 +248,17 @@
|
|||||||
(add-node-list resource graph mark (sort-nodes nodes))
|
(add-node-list resource graph mark (sort-nodes nodes))
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
|
++ check-validity
|
||||||
|
|= [lis=(list (pair index:store node:store)) mark=(unit ^mark)]
|
||||||
|
^- [? _state]
|
||||||
|
|-
|
||||||
|
?~ lis [& state]
|
||||||
|
=^ is-valid state
|
||||||
|
(validate-graph (gas:orm ~ [(rear p.i.lis) q.i.lis]~) mark)
|
||||||
|
?. is-valid
|
||||||
|
[| state]
|
||||||
|
$(lis t.lis)
|
||||||
|
::
|
||||||
++ check-for-duplicates
|
++ check-for-duplicates
|
||||||
|= [=graph:store nodes=(set index:store)]
|
|= [=graph:store nodes=(set index:store)]
|
||||||
^- ?
|
^- ?
|
||||||
@ -271,8 +316,6 @@
|
|||||||
==
|
==
|
||||||
^- graph:store
|
^- graph:store
|
||||||
?< ?=(~ index)
|
?< ?=(~ index)
|
||||||
~| "validation of node failed using mark {<mark>}"
|
|
||||||
?> (validate-graph (gas:orm ~ [i.index node]~) mark)
|
|
||||||
=* atom i.index
|
=* atom i.index
|
||||||
%^ put:orm
|
%^ put:orm
|
||||||
graph
|
graph
|
||||||
@ -571,18 +614,24 @@
|
|||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
=/ [=graph:store mark=(unit mark:store)]
|
=/ [=graph:store mark=(unit mark:store)]
|
||||||
(~(got by graphs) resource.debug-input)
|
(~(got by graphs) resource.debug-input)
|
||||||
?> (validate-graph graph mark)
|
=^ is-valid state
|
||||||
|
(validate-graph graph mark)
|
||||||
|
?> is-valid
|
||||||
[~ state]
|
[~ state]
|
||||||
::
|
::
|
||||||
++ validate-graph
|
++ validate-graph
|
||||||
|= [=graph:store mark=(unit mark:store)]
|
|= [=graph:store mark=(unit mark:store)]
|
||||||
^- ?
|
^- [? _state]
|
||||||
?~ mark %.y
|
?~ mark [%.y state]
|
||||||
|
=/ has-dais (~(has by validators) u.mark)
|
||||||
=/ =dais:clay
|
=/ =dais:clay
|
||||||
|
?: has-dais
|
||||||
|
(~(got by validators) u.mark)
|
||||||
.^ =dais:clay
|
.^ =dais:clay
|
||||||
%cb
|
%cb
|
||||||
/(scot %p our.bowl)/[q.byk.bowl]/(scot %da now.bowl)/[u.mark]
|
/(scot %p our.bowl)/[q.byk.bowl]/(scot %da now.bowl)/[u.mark]
|
||||||
==
|
==
|
||||||
|
:_ state(validators (~(put by validators) u.mark dais))
|
||||||
|- ^- ?
|
|- ^- ?
|
||||||
?~ graph %.y
|
?~ graph %.y
|
||||||
%+ roll (tap:orm graph)
|
%+ roll (tap:orm graph)
|
||||||
@ -600,7 +649,9 @@
|
|||||||
++ poke-import
|
++ poke-import
|
||||||
|= arc=*
|
|= arc=*
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
|
=^ cards -.state
|
||||||
(import:store arc our.bowl)
|
(import:store arc our.bowl)
|
||||||
|
[cards state]
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ on-peek
|
++ on-peek
|
||||||
|
@ -47,8 +47,9 @@
|
|||||||
::
|
::
|
||||||
++ transform-proxy-update
|
++ transform-proxy-update
|
||||||
|= vas=vase
|
|= vas=vase
|
||||||
^- (unit vase)
|
^- (quip card (unit vase))
|
||||||
=/ =update:store !<(update:store vas)
|
=/ =update:store !<(update:store vas)
|
||||||
|
:- ~
|
||||||
?: ?=(%initial -.update)
|
?: ?=(%initial -.update)
|
||||||
~
|
~
|
||||||
|^
|
|^
|
||||||
|
@ -124,15 +124,15 @@
|
|||||||
::
|
::
|
||||||
++ poke-noun
|
++ poke-noun
|
||||||
|= non=*
|
|= non=*
|
||||||
?> ?=(%rewatch-dms non)
|
[~ state]
|
||||||
=/ graphs=(list resource)
|
:: ?> ?=(%rewatch-dms non)
|
||||||
~(tap in get-keys:gra)
|
:: =/ graphs=(list resource)
|
||||||
:- ~
|
:: ~(tap in get-keys:gra)
|
||||||
%_ state
|
:: %_ state
|
||||||
watching
|
:: watching
|
||||||
%- ~(gas in watching)
|
:: %- ~(gas in watching)
|
||||||
(murn graphs |=(rid=resource ?:((should-watch:ha rid) `[rid ~] ~)))
|
:: (murn graphs |=(rid=resource ?:((should-watch:ha rid) `[rid ~] ~)))
|
||||||
==
|
:: ==
|
||||||
::
|
::
|
||||||
++ hark-graph-hook-action
|
++ hark-graph-hook-action
|
||||||
|= =action:hook
|
|= =action:hook
|
||||||
@ -201,7 +201,9 @@
|
|||||||
::
|
::
|
||||||
%add-nodes
|
%add-nodes
|
||||||
=* rid resource.q.update
|
=* rid resource.q.update
|
||||||
(check-nodes ~(val by nodes.q.update) rid)
|
=/ assoc=(unit association:metadata)
|
||||||
|
(peek-association:met %graph rid)
|
||||||
|
(check-nodes ~(val by nodes.q.update) rid assoc)
|
||||||
==
|
==
|
||||||
:: this is awful, but notification kind should always switch
|
:: this is awful, but notification kind should always switch
|
||||||
:: on the index, so hopefully doesn't matter
|
:: on the index, so hopefully doesn't matter
|
||||||
@ -255,9 +257,11 @@
|
|||||||
(get-graph-mop:gra rid)
|
(get-graph-mop:gra rid)
|
||||||
=/ node=(unit node:graph-store)
|
=/ node=(unit node:graph-store)
|
||||||
(bind (peek:orm:graph-store graph) |=([@ =node:graph-store] node))
|
(bind (peek:orm:graph-store graph) |=([@ =node:graph-store] node))
|
||||||
|
=/ assoc=(unit association:metadata)
|
||||||
|
(peek-association:met %graph rid)
|
||||||
=^ cards state
|
=^ cards state
|
||||||
(check-nodes (drop node) rid)
|
(check-nodes (drop node) rid assoc)
|
||||||
?. (should-watch:ha rid)
|
?. (should-watch:ha rid assoc)
|
||||||
[cards state]
|
[cards state]
|
||||||
:_ state(watching (~(put in watching) [rid ~]))
|
:_ state(watching (~(put in watching) [rid ~]))
|
||||||
(weld cards (give:ha ~[/updates] %listen [rid ~]))
|
(weld cards (give:ha ~[/updates] %listen [rid ~]))
|
||||||
@ -265,20 +269,18 @@
|
|||||||
++ check-nodes
|
++ check-nodes
|
||||||
|= $: nodes=(list node:graph-store)
|
|= $: nodes=(list node:graph-store)
|
||||||
rid=resource
|
rid=resource
|
||||||
|
assoc=(unit association:metadata)
|
||||||
==
|
==
|
||||||
=/ group=(unit resource)
|
?~ assoc
|
||||||
(peek-group:met %graph rid)
|
~& no-assoc+rid
|
||||||
?~ group
|
|
||||||
~& no-group+rid
|
|
||||||
`state
|
`state
|
||||||
=/ metadatum=(unit metadatum:metadata)
|
=* group group.u.assoc
|
||||||
(peek-metadatum:met %graph rid)
|
=* metadatum metadatum.u.assoc
|
||||||
?~ metadatum `state
|
|
||||||
=/ module=term
|
=/ module=term
|
||||||
?: ?=(%empty -.config.u.metadatum) %$
|
?: ?=(%empty -.config.metadatum) %$
|
||||||
?: ?=(%group -.config.u.metadatum) %$
|
?: ?=(%group -.config.metadatum) %$
|
||||||
module.config.u.metadatum
|
module.config.metadatum
|
||||||
abet:check:(abed:handle-update:ha rid nodes u.group module)
|
abet:check:(abed:handle-update:ha rid nodes group module)
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ on-peek on-peek:def
|
++ on-peek on-peek:def
|
||||||
@ -340,12 +342,11 @@
|
|||||||
$(contents t.contents)
|
$(contents t.contents)
|
||||||
::
|
::
|
||||||
++ should-watch
|
++ should-watch
|
||||||
|= rid=resource
|
|= [rid=resource assoc=(unit association:metadata)]
|
||||||
^- ?
|
^- ?
|
||||||
=/ group-rid=(unit resource)
|
?~ assoc
|
||||||
(peek-group:met %graph rid)
|
%.n
|
||||||
?~ group-rid %.n
|
?| !(is-managed:grp group.u.assoc)
|
||||||
?| !(is-managed:grp u.group-rid)
|
|
||||||
&(watch-on-self =(our.bowl entity.rid))
|
&(watch-on-self =(our.bowl entity.rid))
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
@ -364,7 +365,9 @@
|
|||||||
update-core(rid r, updates upds, group grp, module mod)
|
update-core(rid r, updates upds, group grp, module mod)
|
||||||
::
|
::
|
||||||
++ get-conversion
|
++ get-conversion
|
||||||
(^get-conversion rid)
|
:: 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
|
++ abet
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
@ -418,7 +421,8 @@
|
|||||||
update-core
|
update-core
|
||||||
=* pos p.post.node
|
=* pos p.post.node
|
||||||
=+ !< notif-kind=(unit notif-kind:hook)
|
=+ !< notif-kind=(unit notif-kind:hook)
|
||||||
(get-conversion !>([0 pos]))
|
%- get-conversion
|
||||||
|
!>(`indexed-post:graph-store`[0 pos])
|
||||||
?~ notif-kind
|
?~ notif-kind
|
||||||
update-core
|
update-core
|
||||||
=/ desc=@t
|
=/ desc=@t
|
||||||
|
@ -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.eb051d816171fb1d0caf.js"></script>
|
<script src="/~landscape/js/bundle/index.f252a9afb6e952de19c9.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -194,6 +194,11 @@
|
|||||||
[%x %tiles ~] ``noun+!>([tiles tile-ordering])
|
[%x %tiles ~] ``noun+!>([tiles tile-ordering])
|
||||||
[%x %first-time ~] ``noun+!>(first-time)
|
[%x %first-time ~] ``noun+!>(first-time)
|
||||||
[%x %keys ~] ``noun+!>(~(key by tiles))
|
[%x %keys ~] ``noun+!>(~(key by tiles))
|
||||||
|
::
|
||||||
|
[%x %runtime-lag ~]
|
||||||
|
:^ ~ ~ %json
|
||||||
|
!> ^- json
|
||||||
|
b+.^(? //(scot %p our.bowl)//(scot %da now.bowl)/zen/lag)
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ on-arvo
|
++ on-arvo
|
||||||
|
@ -59,8 +59,9 @@
|
|||||||
::
|
::
|
||||||
++ transform-proxy-update
|
++ transform-proxy-update
|
||||||
|= vas=vase
|
|= vas=vase
|
||||||
^- (unit vase)
|
^- (quip card (unit vase))
|
||||||
=/ =update:store !<(update:store vas)
|
=/ =update:store !<(update:store vas)
|
||||||
|
:- ~
|
||||||
?. ?=(?(%add %remove) -.update)
|
?. ?=(?(%add %remove) -.update)
|
||||||
~
|
~
|
||||||
=/ role=(unit (unit role-tag))
|
=/ role=(unit (unit role-tag))
|
||||||
|
@ -3,15 +3,14 @@
|
|||||||
:::: /hoon/code/hood/gen
|
:::: /hoon/code/hood/gen
|
||||||
::
|
::
|
||||||
/? 310
|
/? 310
|
||||||
::
|
/- *sole
|
||||||
::::
|
/+ *generators
|
||||||
::
|
:- %ask
|
||||||
:- %say
|
|
||||||
|= $: [now=@da eny=@uvJ bec=beak]
|
|= $: [now=@da eny=@uvJ bec=beak]
|
||||||
[arg=?(~ [%reset ~]) ~]
|
[arg=?(~ [%reset ~]) ~]
|
||||||
==
|
==
|
||||||
=* our p.bec
|
=* our p.bec
|
||||||
:- %helm-code
|
^- (sole-result [%helm-code ?(~ %reset)])
|
||||||
?~ arg
|
?~ arg
|
||||||
=/ code=tape
|
=/ code=tape
|
||||||
%+ slag 1
|
%+ slag 1
|
||||||
@ -20,11 +19,23 @@
|
|||||||
=/ step=tape
|
=/ step=tape
|
||||||
%+ scow %ud
|
%+ scow %ud
|
||||||
.^(@ud %j /(scot %p our)/step/(scot %da now)/(scot %p our))
|
.^(@ud %j /(scot %p our)/step/(scot %da now)/(scot %p our))
|
||||||
%- %- slog
|
::
|
||||||
:~ [%leaf code]
|
%+ print 'use |code %reset to invalidate this and generate a new code'
|
||||||
[%leaf (weld "current step=" step)]
|
%+ print leaf+(weld "current step=" step)
|
||||||
[%leaf "use |code %reset to invalidate this and generate a new code"]
|
%+ print leaf+code
|
||||||
==
|
(produce [%helm-code ~])
|
||||||
~
|
::
|
||||||
?> =(%reset -.arg)
|
?> =(%reset -.arg)
|
||||||
%reset
|
%+ print 'continue?'
|
||||||
|
%+ print 'warning: resetting your code closes all web sessions'
|
||||||
|
%+ prompt
|
||||||
|
[%& %project "y/n: "]
|
||||||
|
%+ parse
|
||||||
|
;~ pose
|
||||||
|
(cold %.y (mask "yY"))
|
||||||
|
(cold %.n (mask "nN"))
|
||||||
|
==
|
||||||
|
|= reset=?
|
||||||
|
?. reset
|
||||||
|
no-product
|
||||||
|
(produce [%helm-code %reset])
|
||||||
|
@ -50,18 +50,17 @@
|
|||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ index
|
++ index
|
||||||
|= i=^index
|
|= ind=^index
|
||||||
^- json
|
^- json
|
||||||
?: =(~ i) s+'/'
|
:- %s
|
||||||
=/ j=^tape ""
|
?: =(~ ind)
|
||||||
|-
|
'/'
|
||||||
?~ i [%s (crip j)]
|
%+ roll ind
|
||||||
=/ k=json (numb i.i)
|
|= [cur=@ acc=@t]
|
||||||
?> ?=(%n -.k)
|
^- @t
|
||||||
%_ $
|
=/ num (numb cur)
|
||||||
i t.i
|
?> ?=(%n -.num)
|
||||||
j (weld j (weld "/" (trip +.k)))
|
(rap 3 acc '/' p.num ~)
|
||||||
==
|
|
||||||
::
|
::
|
||||||
++ uid
|
++ uid
|
||||||
|= u=^uid
|
|= u=^uid
|
||||||
@ -721,9 +720,9 @@
|
|||||||
--
|
--
|
||||||
++ import
|
++ import
|
||||||
|= [arc=* our=ship]
|
|= [arc=* our=ship]
|
||||||
^- (quip card:agent:gall [%4 network])
|
^- (quip card:agent:gall [%5 network])
|
||||||
|^
|
|^
|
||||||
=/ sty [%4 (remake-network ;;(tree-network +.arc))]
|
=/ sty [%5 (remake-network ;;(tree-network +.arc))]
|
||||||
:_ sty
|
:_ sty
|
||||||
%+ turn ~(tap by graphs.sty)
|
%+ turn ~(tap by graphs.sty)
|
||||||
|= [rid=resource =marked-graph]
|
|= [rid=resource =marked-graph]
|
||||||
|
@ -76,6 +76,7 @@
|
|||||||
++ get-graph
|
++ get-graph
|
||||||
|= res=resource
|
|= res=resource
|
||||||
^- update:store
|
^- update:store
|
||||||
|
=- -(p *time)
|
||||||
%+ scry-for update:store
|
%+ scry-for update:store
|
||||||
/graph/(scot %p entity.res)/[name.res]
|
/graph/(scot %p entity.res)/[name.res]
|
||||||
::
|
::
|
||||||
|
@ -75,7 +75,12 @@
|
|||||||
=/ grp=(unit group)
|
=/ grp=(unit group)
|
||||||
(scry-group rid)
|
(scry-group rid)
|
||||||
?~ grp ~
|
?~ grp ~
|
||||||
=* group u.grp
|
(role-for-ship-with-group u.grp rid ship)
|
||||||
|
::
|
||||||
|
++ role-for-ship-with-group
|
||||||
|
|= [grp=group rid=resource =ship]
|
||||||
|
^- (unit (unit role-tag))
|
||||||
|
=* group grp
|
||||||
=* policy policy.group
|
=* policy policy.group
|
||||||
=* tags tags.group
|
=* tags tags.group
|
||||||
=/ admins=(set ^ship)
|
=/ admins=(set ^ship)
|
||||||
@ -107,7 +112,12 @@
|
|||||||
=/ grp=(unit group)
|
=/ grp=(unit group)
|
||||||
(scry-group rid)
|
(scry-group rid)
|
||||||
?~ grp ~
|
?~ grp ~
|
||||||
(~(get ju tags.u.grp) tag)
|
(get-tagged-ships-with-group u.grp rid tag)
|
||||||
|
::
|
||||||
|
++ get-tagged-ships-with-group
|
||||||
|
|= [grp=group rid=resource =tag]
|
||||||
|
^- (set ship)
|
||||||
|
(~(get ju tags.grp) tag)
|
||||||
::
|
::
|
||||||
++ is-managed
|
++ is-managed
|
||||||
|= rid=resource
|
|= rid=resource
|
||||||
|
@ -23,12 +23,12 @@
|
|||||||
%+ turn ~(tap by associations)
|
%+ turn ~(tap by associations)
|
||||||
|= [=md-resource [group=resource =^metadatum]]
|
|= [=md-resource [group=resource =^metadatum]]
|
||||||
^- [cord json]
|
^- [cord json]
|
||||||
:-
|
:- %: rap 3
|
||||||
%- crip
|
(spat (en-path:resource group))
|
||||||
;: weld
|
'/'
|
||||||
(trip (spat (en-path:resource group)))
|
app-name.md-resource
|
||||||
(weld "/" (trip app-name.md-resource))
|
(spat (en-path:resource resource.md-resource))
|
||||||
(trip (spat (en-path:resource resource.md-resource)))
|
~
|
||||||
==
|
==
|
||||||
%- pairs
|
%- pairs
|
||||||
:~ [%group s+(enjs-path:resource group)]
|
:~ [%group s+(enjs-path:resource group)]
|
||||||
|
@ -114,6 +114,14 @@
|
|||||||
state-3
|
state-3
|
||||||
state-4
|
state-4
|
||||||
==
|
==
|
||||||
|
:: +diplomatic: only renegotiate if versions changed
|
||||||
|
::
|
||||||
|
:: If %.n please leave note as to why renegotiation necessary
|
||||||
|
::
|
||||||
|
::
|
||||||
|
++ diplomatic
|
||||||
|
^- ?
|
||||||
|
%.y
|
||||||
::
|
::
|
||||||
++ default
|
++ default
|
||||||
|* [pull-hook=* =config]
|
|* [pull-hook=* =config]
|
||||||
@ -239,6 +247,7 @@
|
|||||||
=/ kick=(list card)
|
=/ kick=(list card)
|
||||||
?: ?& =(min-version.config prev-min-version.old)
|
?: ?& =(min-version.config prev-min-version.old)
|
||||||
=(version.config prev-version.old)
|
=(version.config prev-version.old)
|
||||||
|
diplomatic
|
||||||
==
|
==
|
||||||
~
|
~
|
||||||
(poke-self:pass kick+!>(%kick))^~
|
(poke-self:pass kick+!>(%kick))^~
|
||||||
@ -439,6 +448,7 @@
|
|||||||
?~ tan tr-core
|
?~ tan tr-core
|
||||||
?. versioned
|
?. versioned
|
||||||
(tr-ap-og:tr-cleanup |.((on-pull-nack:og rid u.tan)))
|
(tr-ap-og:tr-cleanup |.((on-pull-nack:og rid u.tan)))
|
||||||
|
%- (slog leaf+"versioned nack for {<rid>} in {<dap.bowl>}" u.tan)
|
||||||
=/ pax
|
=/ pax
|
||||||
(kick-mule:virt rid |.((on-pull-kick:og rid)))
|
(kick-mule:virt rid |.((on-pull-kick:og rid)))
|
||||||
?~ pax tr-failed-kick
|
?~ pax tr-failed-kick
|
||||||
@ -463,18 +473,18 @@
|
|||||||
:: subscription
|
:: subscription
|
||||||
tr-core
|
tr-core
|
||||||
(tr-suspend-pub-ver min-version.config)
|
(tr-suspend-pub-ver min-version.config)
|
||||||
=/ =vase
|
=/ =^cage
|
||||||
(convert-to:ver cage)
|
(convert-to:ver cage)
|
||||||
=/ =wire
|
=/ =wire
|
||||||
(make-wire /store)
|
(make-wire /store)
|
||||||
=+ resources=(~(gas in *(set resource)) (resource-for-update:og vase))
|
=+ resources=(~(gas in *(set resource)) (resource-for-update:og q.cage))
|
||||||
?> ?| no-validate.config
|
?> ?| no-validate.config
|
||||||
?& (check-src resources)
|
?& (check-src resources)
|
||||||
(~(has in resources) rid)
|
(~(has in resources) rid)
|
||||||
== ==
|
== ==
|
||||||
=/ =mark
|
=/ =mark
|
||||||
(append-version:ver version.config)
|
(append-version:ver version.config)
|
||||||
(tr-emit (~(poke-our pass wire) store-name.config mark vase))
|
(tr-emit (~(poke-our pass wire) store-name.config cage))
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ tr-kick
|
++ tr-kick
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
::
|
::
|
||||||
/- *push-hook
|
/- *push-hook
|
||||||
/+ default-agent, resource, verb, versioning, agentio
|
/+ default-agent, resource, verb, versioning, agentio
|
||||||
|
~% %push-hook-top ..part ~
|
||||||
|%
|
|%
|
||||||
+$ card card:agent:gall
|
+$ card card:agent:gall
|
||||||
::
|
::
|
||||||
@ -73,7 +74,16 @@
|
|||||||
state-1
|
state-1
|
||||||
state-2
|
state-2
|
||||||
==
|
==
|
||||||
|
:: +diplomatic: only renegotiate if versions changed
|
||||||
|
::
|
||||||
|
:: If %.n please leave note as to why renegotiation necessary
|
||||||
|
::
|
||||||
|
++ diplomatic
|
||||||
|
^- ?
|
||||||
|
%.y
|
||||||
|
::
|
||||||
++ push-hook
|
++ push-hook
|
||||||
|
~/ %push-hook
|
||||||
|* =config
|
|* =config
|
||||||
$_ ^|
|
$_ ^|
|
||||||
|_ bowl:gall
|
|_ bowl:gall
|
||||||
@ -103,7 +113,7 @@
|
|||||||
::
|
::
|
||||||
++ transform-proxy-update
|
++ transform-proxy-update
|
||||||
|~ vase
|
|~ vase
|
||||||
*(unit vase)
|
*[(list card) (unit vase)]
|
||||||
:: +initial-watch: produce initial state for a subscription
|
:: +initial-watch: produce initial state for a subscription
|
||||||
::
|
::
|
||||||
:: .resource is the resource being subscribed to.
|
:: .resource is the resource being subscribed to.
|
||||||
@ -165,6 +175,7 @@
|
|||||||
=* state -
|
=* state -
|
||||||
^- agent:gall
|
^- agent:gall
|
||||||
=<
|
=<
|
||||||
|
~% %push-agent-lib ..poke-hook-action ~
|
||||||
|_ =bowl:gall
|
|_ =bowl:gall
|
||||||
+* this .
|
+* this .
|
||||||
og ~(. push-hook bowl)
|
og ~(. push-hook bowl)
|
||||||
@ -221,6 +232,7 @@
|
|||||||
|= [prev-min-version=@ud prev-version=@ud]
|
|= [prev-min-version=@ud prev-version=@ud]
|
||||||
?: ?& =(min-version.config prev-min-version)
|
?: ?& =(min-version.config prev-min-version)
|
||||||
=(prev-version version.config)
|
=(prev-version version.config)
|
||||||
|
diplomatic
|
||||||
==
|
==
|
||||||
:: bail on kick if we didn't change versions
|
:: bail on kick if we didn't change versions
|
||||||
~
|
~
|
||||||
@ -256,6 +268,7 @@
|
|||||||
!>(state)
|
!>(state)
|
||||||
::
|
::
|
||||||
++ on-poke
|
++ on-poke
|
||||||
|
~/ %on-poke
|
||||||
|= [=mark =vase]
|
|= [=mark =vase]
|
||||||
^- (quip card:agent:gall agent:gall)
|
^- (quip card:agent:gall agent:gall)
|
||||||
?: =(mark %push-hook-action)
|
?: =(mark %push-hook-action)
|
||||||
@ -272,6 +285,7 @@
|
|||||||
[cards this]
|
[cards this]
|
||||||
::
|
::
|
||||||
++ on-watch
|
++ on-watch
|
||||||
|
~/ %on-watch
|
||||||
|= =path
|
|= =path
|
||||||
^- (quip card:agent:gall agent:gall)
|
^- (quip card:agent:gall agent:gall)
|
||||||
?: ?=([%version ~] path)
|
?: ?=([%version ~] path)
|
||||||
@ -291,26 +305,25 @@
|
|||||||
?. (supported:ver mark)
|
?. (supported:ver mark)
|
||||||
:_ this
|
:_ this
|
||||||
(fact-init-kick:io version+!>(min-version.config))
|
(fact-init-kick:io version+!>(min-version.config))
|
||||||
=/ =vase
|
|
||||||
(convert-to:ver mark (initial-watch:og t.t.t.t.t.t.path resource))
|
|
||||||
:_ this
|
:_ this
|
||||||
[%give %fact ~ mark vase]~
|
=- [%give %fact ~ -]~
|
||||||
|
(convert-to:ver mark (initial-watch:og t.t.t.t.t.t.path resource))
|
||||||
::
|
::
|
||||||
++ unversioned
|
++ unversioned
|
||||||
?> ?=([%ship @ @ *] t.path)
|
?> ?=([%ship @ @ *] t.path)
|
||||||
?. =(min-version.config 0)
|
|
||||||
~& >>> "unversioned req from: {<src.bowl>}, nooping"
|
|
||||||
`this
|
|
||||||
=/ =resource
|
=/ =resource
|
||||||
(de-path:resource t.path)
|
(de-path:resource t.path)
|
||||||
=/ =vase
|
=/ =vase
|
||||||
%+ convert-to:ver update-mark.config
|
|
||||||
(initial-watch:og t.t.t.t.path resource)
|
(initial-watch:og t.t.t.t.path resource)
|
||||||
:_ this
|
:_ this
|
||||||
[%give %fact ~ update-mark.config vase]~
|
?. =(min-version.config 0)
|
||||||
|
~& >>> "unversioned req from: {<src.bowl>}, nooping"
|
||||||
|
~
|
||||||
|
[%give %fact ~ (convert-to:ver update-mark.config vase)]~
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ on-agent
|
++ on-agent
|
||||||
|
~/ %on-agent
|
||||||
|= [=wire =sign:agent:gall]
|
|= [=wire =sign:agent:gall]
|
||||||
^- (quip card:agent:gall agent:gall)
|
^- (quip card:agent:gall agent:gall)
|
||||||
?. ?=([%helper %push-hook @ *] wire)
|
?. ?=([%helper %push-hook @ *] wire)
|
||||||
@ -364,6 +377,7 @@
|
|||||||
[%x %min-version ~] ``version+!>(version.config)
|
[%x %min-version ~] ``version+!>(version.config)
|
||||||
==
|
==
|
||||||
--
|
--
|
||||||
|
~% %push-helper-lib ..card ~
|
||||||
|_ =bowl:gall
|
|_ =bowl:gall
|
||||||
+* og ~(. push-hook bowl)
|
+* og ~(. push-hook bowl)
|
||||||
ver ~(. versioning [bowl [update-mark version min-version]:config])
|
ver ~(. versioning [bowl [update-mark version min-version]:config])
|
||||||
@ -371,6 +385,7 @@
|
|||||||
pass pass:io
|
pass pass:io
|
||||||
::
|
::
|
||||||
++ poke-hook-action
|
++ poke-hook-action
|
||||||
|
~/ %poke-hook-action
|
||||||
|= =action
|
|= =action
|
||||||
^- (quip card:agent:gall _state)
|
^- (quip card:agent:gall _state)
|
||||||
|^
|
|^
|
||||||
@ -439,6 +454,7 @@
|
|||||||
[%pass wire %agent [our.bowl store-name.config] %watch store-path.config]
|
[%pass wire %agent [our.bowl store-name.config] %watch store-path.config]
|
||||||
::
|
::
|
||||||
++ push-updates
|
++ push-updates
|
||||||
|
~/ %push-updates
|
||||||
|= =cage
|
|= =cage
|
||||||
^- (list card:agent:gall)
|
^- (list card:agent:gall)
|
||||||
%+ roll (resource-for-update q.cage)
|
%+ roll (resource-for-update q.cage)
|
||||||
@ -461,10 +477,7 @@
|
|||||||
|= [fact-ver=@ud paths=(set path)]
|
|= [fact-ver=@ud paths=(set path)]
|
||||||
=/ =mark
|
=/ =mark
|
||||||
(append-version:ver fact-ver)
|
(append-version:ver fact-ver)
|
||||||
=/ =^cage
|
(fact:io (convert-from:ver mark q.cage) ~(tap in paths))
|
||||||
:- mark
|
|
||||||
(convert-from:ver mark q.cage)
|
|
||||||
(fact:io cage ~(tap in paths))
|
|
||||||
:: TODO: deprecate
|
:: TODO: deprecate
|
||||||
++ unversioned
|
++ unversioned
|
||||||
?. =(min-version.config 0) ~
|
?. =(min-version.config 0) ~
|
||||||
@ -474,39 +487,39 @@
|
|||||||
%- ~(gas in *(set path))
|
%- ~(gas in *(set path))
|
||||||
(turn (incoming-subscriptions prefix) tail)
|
(turn (incoming-subscriptions prefix) tail)
|
||||||
?: =(0 ~(wyt in unversioned)) ~
|
?: =(0 ~(wyt in unversioned)) ~
|
||||||
=/ =^cage
|
(fact:io (convert-from:ver update-mark.config q.cage) ~(tap in unversioned))^~
|
||||||
:- update-mark.config
|
|
||||||
(convert-from:ver update-mark.config q.cage)
|
|
||||||
(fact:io cage ~(tap in unversioned))^~
|
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ forward-update
|
++ forward-update
|
||||||
|
~/ %forward-update
|
||||||
|= =cage
|
|= =cage
|
||||||
^- (list card:agent:gall)
|
^- (list card:agent:gall)
|
||||||
=- lis
|
=- lis
|
||||||
=/ vas
|
=/ vas=vase
|
||||||
(convert-to:ver cage)
|
q:(convert-to:ver cage)
|
||||||
%+ roll (resource-for-update q.cage)
|
%+ roll (resource-for-update q.cage)
|
||||||
|= [rid=resource [lis=(list card:agent:gall) tf-vas=(unit vase)]]
|
|= [rid=resource [lis=(list card:agent:gall) tf-vas=(unit vase)]]
|
||||||
^- [(list card:agent:gall) (unit vase)]
|
^- [(list card:agent:gall) (unit vase)]
|
||||||
=/ =path
|
=/ =path
|
||||||
resource+(en-path:resource rid)
|
resource+(en-path:resource rid)
|
||||||
=/ =wire (make-wire path)
|
|
||||||
=* ship entity.rid
|
=* ship entity.rid
|
||||||
=. tf-vas
|
=/ out=(pair (list card:agent:gall) (unit vase))
|
||||||
?. =(our.bowl ship)
|
?. =(our.bowl ship)
|
||||||
:: do not transform before forwarding
|
:: do not transform before forwarding
|
||||||
::
|
::
|
||||||
`vas
|
``vas
|
||||||
:: use cached transform
|
:: use cached transform
|
||||||
::
|
::
|
||||||
?^ tf-vas tf-vas
|
?^ tf-vas `tf-vas
|
||||||
:: transform before poking store
|
:: transform before poking store
|
||||||
::
|
::
|
||||||
(transform-proxy-update:og vas)
|
(transform-proxy-update:og vas)
|
||||||
~| "forwarding failed during transform. mark: {<p.cage>} resource: {<rid>}"
|
~| "forwarding failed during transform. mark: {<p.cage>} rid: {<rid>}"
|
||||||
?> ?=(^ tf-vas)
|
?> ?=(^ q.out)
|
||||||
=/ =dock
|
:_ q.out
|
||||||
|
:_ (weld lis p.out)
|
||||||
|
=/ =wire (make-wire path)
|
||||||
|
=- [%pass wire %agent - %poke [current-version:ver u.q.out]]
|
||||||
:- ship
|
:- ship
|
||||||
?. =(our.bowl ship)
|
?. =(our.bowl ship)
|
||||||
:: forward to host
|
:: forward to host
|
||||||
@ -515,11 +528,6 @@
|
|||||||
:: poke our store
|
:: poke our store
|
||||||
::
|
::
|
||||||
store-name.config
|
store-name.config
|
||||||
=/ cag=^cage
|
|
||||||
:- current-version:ver
|
|
||||||
u.tf-vas
|
|
||||||
:_ tf-vas
|
|
||||||
[[%pass wire %agent dock %poke cag] lis]
|
|
||||||
::
|
::
|
||||||
++ ver-from-path
|
++ ver-from-path
|
||||||
|= =path
|
|= =path
|
||||||
@ -529,6 +537,7 @@
|
|||||||
(slav %ud i.extra)
|
(slav %ud i.extra)
|
||||||
::
|
::
|
||||||
++ resource-for-update
|
++ resource-for-update
|
||||||
|
~/ %resource-for-update
|
||||||
|= =vase
|
|= =vase
|
||||||
^- (list resource)
|
^- (list resource)
|
||||||
%~ tap in
|
%~ tap in
|
||||||
|
@ -39,10 +39,10 @@
|
|||||||
~! +:*handler
|
~! +:*handler
|
||||||
(handler inbound-request)
|
(handler inbound-request)
|
||||||
::
|
::
|
||||||
=/ redirect=cord
|
=- [[307 ['location' -]~] ~]
|
||||||
%- crip
|
%^ cat 3
|
||||||
"/~/login?redirect={(trip url.request.inbound-request)}"
|
'/~/login?redirect='
|
||||||
[[307 ['location' redirect]~] ~]
|
url.request.inbound-request
|
||||||
::
|
::
|
||||||
:: +require-authorization-simple:
|
:: +require-authorization-simple:
|
||||||
:: redirect to the login page when unauthenticated
|
:: redirect to the login page when unauthenticated
|
||||||
@ -56,10 +56,10 @@
|
|||||||
~! this
|
~! this
|
||||||
simple-payload
|
simple-payload
|
||||||
::
|
::
|
||||||
=/ redirect=cord
|
=- [[307 ['location' -]~] ~]
|
||||||
%- crip
|
%^ cat 3
|
||||||
"/~/login?redirect={(trip url.request.inbound-request)}"
|
'/~/login?redirect='
|
||||||
[[307 ['location' redirect]~] ~]
|
url.request.inbound-request
|
||||||
::
|
::
|
||||||
++ give-simple-payload
|
++ give-simple-payload
|
||||||
|= [eyre-id=@ta =simple-payload:http]
|
|= [eyre-id=@ta =simple-payload:http]
|
||||||
@ -86,36 +86,52 @@
|
|||||||
:_ `octs
|
:_ `octs
|
||||||
[200 [['content-type' 'text/html'] ?:(cache [max-1-wk ~] ~)]]
|
[200 [['content-type' 'text/html'] ?:(cache [max-1-wk ~] ~)]]
|
||||||
::
|
::
|
||||||
++ js-response
|
|
||||||
|= =octs
|
|
||||||
^- simple-payload:http
|
|
||||||
[[200 [['content-type' 'text/javascript'] max-1-da ~]] `octs]
|
|
||||||
::
|
|
||||||
++ json-response
|
|
||||||
|= =json
|
|
||||||
^- simple-payload:http
|
|
||||||
[[200 ['content-type' 'application/json']~] `(json-to-octs json)]
|
|
||||||
::
|
|
||||||
++ css-response
|
++ css-response
|
||||||
|
=| cache=?
|
||||||
|= =octs
|
|= =octs
|
||||||
^- simple-payload:http
|
^- simple-payload:http
|
||||||
[[200 [['content-type' 'text/css'] max-1-da ~]] `octs]
|
:_ `octs
|
||||||
|
[200 [['content-type' 'text/css'] ?:(cache [max-1-wk ~] ~)]]
|
||||||
::
|
::
|
||||||
++ manx-response
|
++ js-response
|
||||||
|= man=manx
|
=| cache=?
|
||||||
|
|= =octs
|
||||||
^- simple-payload:http
|
^- simple-payload:http
|
||||||
[[200 ['content-type' 'text/html']~] `(manx-to-octs man)]
|
:_ `octs
|
||||||
|
[200 [['content-type' 'text/javascript'] ?:(cache [max-1-wk ~] ~)]]
|
||||||
::
|
::
|
||||||
++ png-response
|
++ png-response
|
||||||
|
=| cache=?
|
||||||
|= =octs
|
|= =octs
|
||||||
^- simple-payload:http
|
^- simple-payload:http
|
||||||
[[200 [['content-type' 'image/png'] max-1-wk ~]] `octs]
|
:_ `octs
|
||||||
|
[200 [['content-type' 'image/png'] ?:(cache [max-1-wk ~] ~)]]
|
||||||
|
::
|
||||||
|
++ ico-response
|
||||||
|
|= =octs
|
||||||
|
^- simple-payload:http
|
||||||
|
[[200 [['content-type' 'image/x-icon'] max-1-wk ~]] `octs]
|
||||||
::
|
::
|
||||||
++ woff2-response
|
++ woff2-response
|
||||||
|
=| cache=?
|
||||||
|= =octs
|
|= =octs
|
||||||
^- simple-payload:http
|
^- simple-payload:http
|
||||||
[[200 [['content-type' 'font/woff2'] max-1-wk ~]] `octs]
|
[[200 [['content-type' 'font/woff2'] max-1-wk ~]] `octs]
|
||||||
::
|
::
|
||||||
|
++ json-response
|
||||||
|
=| cache=_|
|
||||||
|
|= =json
|
||||||
|
^- simple-payload:http
|
||||||
|
:_ `(json-to-octs json)
|
||||||
|
[200 [['content-type' 'application/json'] ?:(cache [max-1-da ~] ~)]]
|
||||||
|
::
|
||||||
|
++ manx-response
|
||||||
|
=| cache=_|
|
||||||
|
|= man=manx
|
||||||
|
^- simple-payload:http
|
||||||
|
:_ `(manx-to-octs man)
|
||||||
|
[200 [['content-type' 'text/html'] ?:(cache [max-1-da ~] ~)]]
|
||||||
|
::
|
||||||
++ not-found
|
++ not-found
|
||||||
^- simple-payload:http
|
^- simple-payload:http
|
||||||
[[404 ~] ~]
|
[[404 ~] ~]
|
||||||
@ -123,10 +139,10 @@
|
|||||||
++ login-redirect
|
++ login-redirect
|
||||||
|= =request:http
|
|= =request:http
|
||||||
^- simple-payload:http
|
^- simple-payload:http
|
||||||
=/ redirect=cord
|
=- [[307 ['location' -]~] ~]
|
||||||
%- crip
|
%^ cat 3
|
||||||
"/~/login?redirect={(trip url.request)}"
|
'/~/login?redirect='
|
||||||
[[307 ['location' redirect]~] ~]
|
url.request
|
||||||
::
|
::
|
||||||
++ redirect
|
++ redirect
|
||||||
|= redirect=cord
|
|= redirect=cord
|
||||||
|
@ -29,11 +29,12 @@
|
|||||||
&((gte ver min) (lte ver version))
|
&((gte ver min) (lte ver version))
|
||||||
::
|
::
|
||||||
++ convert-to
|
++ convert-to
|
||||||
|= =cage
|
|= [=mark =vase]
|
||||||
^- vase
|
^- cage
|
||||||
?: =(p.cage current-version)
|
:- current-version
|
||||||
q.cage
|
?: =(mark current-version)
|
||||||
((tube-to p.cage) q.cage)
|
vase
|
||||||
|
((tube-to mark) vase)
|
||||||
::
|
::
|
||||||
++ tube-to
|
++ tube-to
|
||||||
|= =mark
|
|= =mark
|
||||||
@ -44,10 +45,11 @@
|
|||||||
.^(tube:clay %cc (scry:io %home /[current-version]/[mark]))
|
.^(tube:clay %cc (scry:io %home /[current-version]/[mark]))
|
||||||
::
|
::
|
||||||
++ convert-from
|
++ convert-from
|
||||||
|= =cage
|
|= [=mark =vase]
|
||||||
^- vase
|
^- cage
|
||||||
?: =(p.cage current-version)
|
:- mark
|
||||||
q.cage
|
?: =(mark current-version)
|
||||||
((tube-from p.cage) q.cage)
|
vase
|
||||||
|
((tube-from mark) vase)
|
||||||
--
|
--
|
||||||
|
|
||||||
|
20
pkg/arvo/mar/graph/cache/hook.hoon
vendored
Normal file
20
pkg/arvo/mar/graph/cache/hook.hoon
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/- metadata=metadata-store, res=resource
|
||||||
|
|%
|
||||||
|
+$ cache-action
|
||||||
|
$% [%graph-to-mark (pair resource:res (unit mark))]
|
||||||
|
[%perm-marks (pair (pair mark @tas) tube:clay)]
|
||||||
|
[%transform-marks (pair mark tube:clay)]
|
||||||
|
==
|
||||||
|
--
|
||||||
|
::
|
||||||
|
|_ act=cache-action
|
||||||
|
++ grad %noun
|
||||||
|
++ grow
|
||||||
|
|%
|
||||||
|
++ noun act
|
||||||
|
--
|
||||||
|
++ grab
|
||||||
|
|%
|
||||||
|
++ noun cache-action
|
||||||
|
--
|
||||||
|
--
|
12
pkg/arvo/mar/ico.hoon
Normal file
12
pkg/arvo/mar/ico.hoon
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|_ dat=@
|
||||||
|
++ grow
|
||||||
|
|%
|
||||||
|
++ mime [/image/x-icon (as-octs:mimes:html dat)]
|
||||||
|
--
|
||||||
|
++ grab
|
||||||
|
|%
|
||||||
|
++ mime |=([p=mite q=octs] q.q)
|
||||||
|
++ noun @
|
||||||
|
--
|
||||||
|
++ grad %mime
|
||||||
|
--
|
@ -1,3 +1,3 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: "@urbit"
|
extends: '@urbit'
|
||||||
};
|
};
|
3627
pkg/interface/package-lock.json
generated
3627
pkg/interface/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -8,9 +8,10 @@
|
|||||||
"@reach/disclosure": "^0.10.5",
|
"@reach/disclosure": "^0.10.5",
|
||||||
"@reach/menu-button": "^0.10.5",
|
"@reach/menu-button": "^0.10.5",
|
||||||
"@reach/tabs": "^0.10.5",
|
"@reach/tabs": "^0.10.5",
|
||||||
|
"@react-spring/web": "^9.1.1",
|
||||||
"@tlon/indigo-dark": "^1.0.6",
|
"@tlon/indigo-dark": "^1.0.6",
|
||||||
"@tlon/indigo-light": "^1.0.7",
|
"@tlon/indigo-light": "^1.0.7",
|
||||||
"@tlon/indigo-react": "^1.2.21",
|
"@tlon/indigo-react": "^1.2.22",
|
||||||
"@tlon/sigil-js": "^1.4.3",
|
"@tlon/sigil-js": "^1.4.3",
|
||||||
"@urbit/api": "file:../npm/api",
|
"@urbit/api": "file:../npm/api",
|
||||||
"any-ascii": "^0.1.7",
|
"any-ascii": "^0.1.7",
|
||||||
@ -22,8 +23,7 @@
|
|||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"formik": "^2.1.5",
|
"formik": "^2.1.5",
|
||||||
"immer": "^8.0.1",
|
"immer": "^8.0.1",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.21",
|
||||||
"markdown-to-jsx": "^6.11.4",
|
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"mousetrap": "^1.6.5",
|
"mousetrap": "^1.6.5",
|
||||||
"mousetrap-global-bind": "^1.1.0",
|
"mousetrap-global-bind": "^1.1.0",
|
||||||
@ -38,15 +38,18 @@
|
|||||||
"react-markdown": "^4.3.1",
|
"react-markdown": "^4.3.1",
|
||||||
"react-oembed-container": "^1.0.0",
|
"react-oembed-container": "^1.0.0",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
|
"react-use-gesture": "^9.1.3",
|
||||||
"react-virtuoso": "^0.20.3",
|
"react-virtuoso": "^0.20.3",
|
||||||
"react-visibility-sensor": "^5.1.1",
|
"react-visibility-sensor": "^5.1.1",
|
||||||
"remark-breaks": "^2.0.1",
|
"remark": "^12.0.0",
|
||||||
"remark-disable-tokenizers": "^1.0.24",
|
"remark-breaks": "^2.0.2",
|
||||||
|
"remark-disable-tokenizers": "1.1.0",
|
||||||
"stacktrace-js": "^2.0.2",
|
"stacktrace-js": "^2.0.2",
|
||||||
"style-loader": "^1.3.0",
|
"style-loader": "^1.3.0",
|
||||||
"styled-components": "^5.1.1",
|
"styled-components": "^5.1.1",
|
||||||
"styled-system": "^5.1.5",
|
"styled-system": "^5.1.5",
|
||||||
"suncalc": "^1.8.0",
|
"suncalc": "^1.8.0",
|
||||||
|
"unist-util-visit": "^3.0.0",
|
||||||
"urbit-ob": "^5.0.1",
|
"urbit-ob": "^5.0.1",
|
||||||
"workbox-core": "^6.0.2",
|
"workbox-core": "^6.0.2",
|
||||||
"workbox-precaching": "^6.0.2",
|
"workbox-precaching": "^6.0.2",
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import './wdyr';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as ReactDOM from 'react-dom';
|
import * as ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import './register-sw';
|
import './register-sw';
|
||||||
|
|
||||||
import App from './views/App';
|
import App from './views/App';
|
||||||
|
import './wdyr';
|
||||||
|
|
||||||
ReactDOM.render(<App />, document.getElementById('root'));
|
ReactDOM.render(<App />, document.getElementById('root'));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import { Path, Patp } from '@urbit/api';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { Patp, Path } from '@urbit/api';
|
|
||||||
import BaseStore from '../store/base';
|
import BaseStore from '../store/base';
|
||||||
|
|
||||||
export default class BaseApi<S extends object = {}> {
|
export default class BaseApi<S extends object = {}> {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import BaseApi from './base';
|
|
||||||
import { StoreState } from '../store/type';
|
|
||||||
import { Patp } from '@urbit/api';
|
import { Patp } from '@urbit/api';
|
||||||
import { ContactEdit } from '@urbit/api/contacts';
|
import { ContactEditField } from '@urbit/api/contacts';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import { StoreState } from '../store/type';
|
||||||
|
import BaseApi from './base';
|
||||||
|
|
||||||
export default class ContactsApi extends BaseApi<StoreState> {
|
export default class ContactsApi extends BaseApi<StoreState> {
|
||||||
add(ship: Patp, contact: any) {
|
add(ship: Patp, contact: any) {
|
||||||
@ -14,7 +14,7 @@ export default class ContactsApi extends BaseApi<StoreState> {
|
|||||||
return this.storeAction({ remove: { ship } });
|
return this.storeAction({ remove: { ship } });
|
||||||
}
|
}
|
||||||
|
|
||||||
edit(ship: Patp, editField: ContactEdit) {
|
edit(ship: Patp, editField: ContactEditField) {
|
||||||
/* editField can be...
|
/* editField can be...
|
||||||
{nickname: ''}
|
{nickname: ''}
|
||||||
{email: ''}
|
{email: ''}
|
||||||
@ -78,17 +78,17 @@ export default class ContactsApi extends BaseApi<StoreState> {
|
|||||||
return _.compact(
|
return _.compact(
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
ships.map(
|
ships.map(
|
||||||
async s => {
|
async (s) => {
|
||||||
const ship = `~${s}`;
|
const ship = `~${s}`;
|
||||||
if(s === window.ship) {
|
if(s === window.ship) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
const allowed = await this.fetchIsAllowed(
|
const allowed = await this.fetchIsAllowed(
|
||||||
`~${window.ship}`,
|
`~${window.ship}`,
|
||||||
'personal',
|
'personal',
|
||||||
ship,
|
ship,
|
||||||
true
|
true
|
||||||
)
|
);
|
||||||
return allowed ? null : ship;
|
return allowed ? null : ship;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import BaseApi from './base';
|
|
||||||
import type { StoreState } from '../store/type';
|
import type { StoreState } from '../store/type';
|
||||||
import type {GcpToken} from '../../types/gcp-state';
|
import BaseApi from './base';
|
||||||
|
|
||||||
|
|
||||||
export default class GcpApi extends BaseApi<StoreState> {
|
export default class GcpApi extends BaseApi<StoreState> {
|
||||||
// Does not touch the store; use the value manually.
|
// Does not touch the store; use the value manually.
|
||||||
@ -18,4 +16,4 @@ export default class GcpApi extends BaseApi<StoreState> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import { Patp } from '@urbit/api';
|
import { Patp } from '@urbit/api';
|
||||||
import BaseApi from './base';
|
|
||||||
import { StoreState } from '../store/type';
|
|
||||||
import GlobalStore from '../store/store';
|
import GlobalStore from '../store/store';
|
||||||
import LocalApi from './local';
|
import { StoreState } from '../store/type';
|
||||||
import InviteApi from './invite';
|
import BaseApi from './base';
|
||||||
import MetadataApi from './metadata';
|
|
||||||
import ContactsApi from './contacts';
|
import ContactsApi from './contacts';
|
||||||
import GroupsApi from './groups';
|
|
||||||
import LaunchApi from './launch';
|
|
||||||
import GraphApi from './graph';
|
|
||||||
import S3Api from './s3';
|
|
||||||
import GcpApi from './gcp';
|
import GcpApi from './gcp';
|
||||||
|
import GraphApi from './graph';
|
||||||
|
import GroupsApi from './groups';
|
||||||
import { HarkApi } from './hark';
|
import { HarkApi } from './hark';
|
||||||
|
import InviteApi from './invite';
|
||||||
|
import LaunchApi from './launch';
|
||||||
|
import LocalApi from './local';
|
||||||
|
import MetadataApi from './metadata';
|
||||||
|
import S3Api from './s3';
|
||||||
import SettingsApi from './settings';
|
import SettingsApi from './settings';
|
||||||
|
|
||||||
export default class GlobalApi extends BaseApi<StoreState> {
|
export default class GlobalApi extends BaseApi<StoreState> {
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import BaseApi from './base';
|
import { Content, Enc, GraphNode, GroupPolicy, Path, Patp, Post, Resource } from '@urbit/api';
|
||||||
import { StoreState } from '../store/type';
|
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
||||||
import { Patp, Path, Resource } from '@urbit/api';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import { decToUd, deSig, resourceAsPath, unixToDa } from '~/logic/lib/util';
|
||||||
import { makeResource, resourceFromPath } from '../lib/group';
|
import { makeResource, resourceFromPath } from '../lib/group';
|
||||||
import { GroupPolicy, Enc, Post, Content } from '@urbit/api';
|
import { StoreState } from '../store/type';
|
||||||
import { numToUd, unixToDa, decToUd, deSig, resourceAsPath } from '~/logic/lib/util';
|
import BaseApi from './base';
|
||||||
|
|
||||||
export const createBlankNodeWithChildPost = (
|
export const createBlankNodeWithChildPost = (
|
||||||
parentIndex = '',
|
parentIndex = '',
|
||||||
childIndex = '',
|
childIndex = '',
|
||||||
contents: Content[]
|
contents: Content[]
|
||||||
) => {
|
): GraphNode => {
|
||||||
const date = unixToDa(Date.now()).toString();
|
const date = unixToDa(Date.now()).toString();
|
||||||
const nodeIndex = parentIndex + '/' + date;
|
const nodeIndex = parentIndex + '/' + date;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ export const createBlankNodeWithChildPost = (
|
|||||||
hash: null,
|
hash: null,
|
||||||
signatures: []
|
signatures: []
|
||||||
},
|
},
|
||||||
children: childGraph
|
children: childGraph as BigIntOrderedMap<GraphNode>
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -185,13 +185,12 @@ export default class GraphApi extends BaseApi<StoreState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
eval(cord: string) {
|
eval(cord: string): Promise<string[] | undefined> {
|
||||||
return this.spider('graph-view-action', 'tang', 'graph-eval', {
|
return this.spider('graph-view-action', 'tang', 'graph-eval', {
|
||||||
eval: cord
|
eval: cord
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
addGraph(ship: Patp, name: string, graph: any, mark: any) {
|
addGraph(ship: Patp, name: string, graph: any, mark: any) {
|
||||||
return this.storeAction({
|
return this.storeAction({
|
||||||
'add-graph': {
|
'add-graph': {
|
||||||
@ -211,7 +210,7 @@ export default class GraphApi extends BaseApi<StoreState> {
|
|||||||
return this.addNodes(ship, name, nodes);
|
return this.addNodes(ship, name, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
addNode(ship: Patp, name: string, node: Object) {
|
addNode(ship: Patp, name: string, node: GraphNode) {
|
||||||
const nodes = {};
|
const nodes = {};
|
||||||
nodes[node.post.index] = node;
|
nodes[node.post.index] = node;
|
||||||
|
|
||||||
@ -265,7 +264,7 @@ export default class GraphApi extends BaseApi<StoreState> {
|
|||||||
'resource',
|
'resource',
|
||||||
'graph-create-group-feed',
|
'graph-create-group-feed',
|
||||||
{
|
{
|
||||||
"create-group-feed": { resource: group, vip }
|
'create-group-feed': { resource: group, vip }
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return resource;
|
return resource;
|
||||||
@ -277,12 +276,11 @@ export default class GraphApi extends BaseApi<StoreState> {
|
|||||||
'json',
|
'json',
|
||||||
'graph-disable-group-feed',
|
'graph-disable-group-feed',
|
||||||
{
|
{
|
||||||
"disable-group-feed": { resource: group }
|
'disable-group-feed': { resource: group }
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
removePosts(ship: Patp, name: string, indices: string[]) {
|
removePosts(ship: Patp, name: string, indices: string[]) {
|
||||||
return this.hookAction(ship, {
|
return this.hookAction(ship, {
|
||||||
'remove-posts': {
|
'remove-posts': {
|
||||||
@ -369,7 +367,7 @@ export default class GraphApi extends BaseApi<StoreState> {
|
|||||||
const node = data['graph-update'];
|
const node = data['graph-update'];
|
||||||
this.store.handleEvent({
|
this.store.handleEvent({
|
||||||
data: {
|
data: {
|
||||||
"graph-update-loose": node
|
'graph-update-loose': node
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import BaseApi from './base';
|
import { Enc, Patp } from '@urbit/api';
|
||||||
import { StoreState } from '../store/type';
|
|
||||||
import { Path, Patp, Enc } from '@urbit/api';
|
|
||||||
import {
|
import {
|
||||||
GroupAction,
|
GroupAction,
|
||||||
GroupPolicy,
|
GroupPolicy,
|
||||||
Resource,
|
|
||||||
Tag,
|
GroupPolicyDiff, Resource,
|
||||||
GroupPolicyDiff
|
Tag
|
||||||
} from '@urbit/api/groups';
|
} from '@urbit/api/groups';
|
||||||
import { makeResource } from '../lib/group';
|
import { makeResource } from '../lib/group';
|
||||||
|
import { StoreState } from '../store/type';
|
||||||
|
import BaseApi from './base';
|
||||||
|
|
||||||
export default class GroupsApi extends BaseApi<StoreState> {
|
export default class GroupsApi extends BaseApi<StoreState> {
|
||||||
remove(resource: Resource, ships: Patp[]) {
|
remove(resource: Resource, ships: Patp[]) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import BaseApi from './base';
|
import { Association, GraphNotifDescription, IndexedNotification, NotifIndex } from '@urbit/api';
|
||||||
import { StoreState } from '../store/type';
|
|
||||||
import { dateToDa, decToUd } from '../lib/util';
|
|
||||||
import { NotifIndex, IndexedNotification, Association, GraphNotifDescription } from '@urbit/api';
|
|
||||||
import { BigInteger } from 'big-integer';
|
import { BigInteger } from 'big-integer';
|
||||||
import { getParentIndex } from '../lib/notification';
|
import { getParentIndex } from '../lib/notification';
|
||||||
|
import { dateToDa, decToUd } from '../lib/util';
|
||||||
import useHarkState from '../state/hark';
|
import useHarkState from '../state/hark';
|
||||||
|
import { StoreState } from '../store/type';
|
||||||
|
import BaseApi from './base';
|
||||||
|
|
||||||
function getHarkSize() {
|
function getHarkSize() {
|
||||||
return useHarkState.getState().notifications.size ?? 0;
|
return useHarkState.getState().notifications.size ?? 0;
|
||||||
@ -75,7 +75,6 @@ export class HarkApi extends BaseApi<StoreState> {
|
|||||||
graph: {
|
graph: {
|
||||||
graph: association.resource,
|
graph: association.resource,
|
||||||
group: association.group,
|
group: association.group,
|
||||||
module: association.metadata.module,
|
|
||||||
description,
|
description,
|
||||||
index: parent
|
index: parent
|
||||||
} }
|
} }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import BaseApi from './base';
|
import { Serial } from '@urbit/api';
|
||||||
import { StoreState } from '../store/type';
|
import { StoreState } from '../store/type';
|
||||||
import { Serial, Path } from '@urbit/api';
|
import BaseApi from './base';
|
||||||
|
|
||||||
export default class InviteApi extends BaseApi<StoreState> {
|
export default class InviteApi extends BaseApi<StoreState> {
|
||||||
accept(app: string, uid: Serial) {
|
accept(app: string, uid: Serial) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import BaseApi from './base';
|
|
||||||
import { StoreState } from '../store/type';
|
import { StoreState } from '../store/type';
|
||||||
|
import BaseApi from './base';
|
||||||
|
|
||||||
export default class LaunchApi extends BaseApi<StoreState> {
|
export default class LaunchApi extends BaseApi<StoreState> {
|
||||||
add(name: string, tile = { basic : { title: '', linkedUrl: '', iconUrl: '' } }) {
|
add(name: string, tile = { basic : { title: '', linkedUrl: '', iconUrl: '' } }) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import BaseApi from './base';
|
|
||||||
import { StoreState } from '../store/type';
|
import { StoreState } from '../store/type';
|
||||||
|
import BaseApi from './base';
|
||||||
|
|
||||||
export default class LocalApi extends BaseApi<StoreState> {
|
export default class LocalApi extends BaseApi<StoreState> {
|
||||||
getBaseHash() {
|
getBaseHash() {
|
||||||
@ -8,7 +8,9 @@ export default class LocalApi extends BaseApi<StoreState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
dehydrate() {
|
getRuntimeLag() {
|
||||||
this.store.dehydrate();
|
return this.scry<boolean>('launch', '/runtime-lag').then((runtimeLag) => {
|
||||||
|
this.store.handleEvent({ data: { runtimeLag } });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
import BaseApi from './base';
|
import { Association, Metadata, MetadataUpdatePreview, Path } from '@urbit/api';
|
||||||
import { StoreState } from '../store/type';
|
|
||||||
import { Path, Patp, Association, Metadata, MetadataUpdatePreview } from '@urbit/api';
|
|
||||||
import { uxToHex } from '../lib/util';
|
import { uxToHex } from '../lib/util';
|
||||||
|
import { StoreState } from '../store/type';
|
||||||
|
import BaseApi from './base';
|
||||||
|
|
||||||
export default class MetadataApi extends BaseApi<StoreState> {
|
export default class MetadataApi extends BaseApi<StoreState> {
|
||||||
metadataAdd(appName: string, resource: Path, group: Path, title: string, description: string, dateCreated: string, color: string, moduleName: string) {
|
metadataAdd(appName: string, resource: Path, group: Path, title: string, description: string, dateCreated: string, color: string, moduleName: string) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import BaseApi from './base';
|
|
||||||
import { StoreState } from '../store/type';
|
import { StoreState } from '../store/type';
|
||||||
import { S3Update } from '../../types/s3-update';
|
import BaseApi from './base';
|
||||||
|
|
||||||
export default class S3Api extends BaseApi<StoreState> {
|
export default class S3Api extends BaseApi<StoreState> {
|
||||||
setCurrentBucket(bucket: string) {
|
setCurrentBucket(bucket: string) {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import BaseApi from './base';
|
import {
|
||||||
import { StoreState } from '../store/type';
|
Bucket, Key,
|
||||||
import { Key,
|
|
||||||
Value,
|
SettingsUpdate, Value
|
||||||
Bucket
|
|
||||||
} from '@urbit/api/settings';
|
} from '@urbit/api/settings';
|
||||||
|
import { StoreState } from '../store/type';
|
||||||
|
import BaseApi from './base';
|
||||||
|
|
||||||
export default class SettingsApi extends BaseApi<StoreState> {
|
export default class SettingsApi extends BaseApi<StoreState> {
|
||||||
private storeAction(action: SettingsEvent): Promise<any> {
|
private storeAction(action: SettingsUpdate): Promise<any> {
|
||||||
return this.action('settings-store', 'settings-event', action);
|
return this.action('settings-store', 'settings-event', action);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,14 +48,14 @@ export default class SettingsApi extends BaseApi<StoreState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getAll() {
|
async getAll() {
|
||||||
const { all } = await this.scry("settings-store", "/all");
|
const { all } = await this.scry('settings-store', '/all');
|
||||||
this.store.handleEvent({ data:
|
this.store.handleEvent({ data:
|
||||||
{"settings-data": { all } }
|
{ 'settings-data': { all } }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBucket(bucket: Key) {
|
async getBucket(bucket: Key) {
|
||||||
const data = await this.scry('settings-store', `/bucket/${bucket}`);
|
const data: Record<string, unknown> = await this.scry('settings-store', `/bucket/${bucket}`);
|
||||||
this.store.handleEvent({ data: { 'settings-data': {
|
this.store.handleEvent({ data: { 'settings-data': {
|
||||||
'bucket-key': bucket,
|
'bucket-key': bucket,
|
||||||
'bucket': data.bucket
|
'bucket': data.bucket
|
||||||
@ -62,7 +63,7 @@ export default class SettingsApi extends BaseApi<StoreState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getEntry(bucket: Key, entry: Key) {
|
async getEntry(bucket: Key, entry: Key) {
|
||||||
const data = await this.scry('settings-store', `/entry/${bucket}/${entry}`);
|
const data: Record<string, unknown> = await this.scry('settings-store', `/entry/${bucket}/${entry}`);
|
||||||
this.store.handleEvent({ data: { 'settings-data': {
|
this.store.handleEvent({ data: { 'settings-data': {
|
||||||
'bucket-key': bucket,
|
'bucket-key': bucket,
|
||||||
'entry-key': entry,
|
'entry-key': entry,
|
||||||
|
@ -7,14 +7,12 @@
|
|||||||
//
|
//
|
||||||
import querystring from 'querystring';
|
import querystring from 'querystring';
|
||||||
import {
|
import {
|
||||||
StorageAcl,
|
|
||||||
StorageClient,
|
StorageClient,
|
||||||
StorageUpload,
|
StorageUpload,
|
||||||
UploadParams,
|
UploadParams,
|
||||||
UploadResult
|
UploadResult
|
||||||
} from './StorageClient';
|
} from './StorageClient';
|
||||||
|
|
||||||
|
|
||||||
const ENDPOINT = 'storage.googleapis.com';
|
const ENDPOINT = 'storage.googleapis.com';
|
||||||
|
|
||||||
class GcpUpload implements StorageUpload {
|
class GcpUpload implements StorageUpload {
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
// Defines a StorageClient interface interoperable between S3 and GCP Storage.
|
// Defines a StorageClient interface interoperable between S3 and GCP Storage.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
// XX kind of gross. S3 needs 'public-read', GCP needs 'publicRead'.
|
// XX kind of gross. S3 needs 'public-read', GCP needs 'publicRead'.
|
||||||
// Rather than write a wrapper around S3, we offer this field here, which
|
// Rather than write a wrapper around S3, we offer this field here, which
|
||||||
// should always be passed, and will be replaced by 'publicRead' in the
|
// should always be passed, and will be replaced by 'publicRead' in the
|
||||||
// GCP client.
|
// GCP client.
|
||||||
export enum StorageAcl {
|
export enum StorageAcl {
|
||||||
PublicRead = 'public-read'
|
PublicRead = 'public-read'
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface UploadParams {
|
export interface UploadParams {
|
||||||
Bucket: string; // the bucket to upload the object to
|
Bucket: string; // the bucket to upload the object to
|
||||||
@ -16,17 +15,17 @@ export interface UploadParams {
|
|||||||
ContentType: string; // the object's mime-type
|
ContentType: string; // the object's mime-type
|
||||||
ACL: StorageAcl; // ACL, always 'public-read'
|
ACL: StorageAcl; // ACL, always 'public-read'
|
||||||
Body: File; // the object itself
|
Body: File; // the object itself
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface UploadResult {
|
export interface UploadResult {
|
||||||
Location: string;
|
Location: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
// Extra layer of indirection used by S3 client.
|
// Extra layer of indirection used by S3 client.
|
||||||
export interface StorageUpload {
|
export interface StorageUpload {
|
||||||
promise(): Promise<UploadResult>;
|
promise(): Promise<UploadResult>;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface StorageClient {
|
export interface StorageClient {
|
||||||
upload(params: UploadParams): StorageUpload;
|
upload(params: UploadParams): StorageUpload;
|
||||||
};
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import bigInt, { BigInteger } from 'big-integer';
|
import { BigInteger } from 'big-integer';
|
||||||
|
|
||||||
export function max(a: BigInteger, b: BigInteger) {
|
export function max(a: BigInteger, b: BigInteger) {
|
||||||
return a.gt(b) ? a : b;
|
return a.gt(b) ? a : b;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
|
|
||||||
export type SubmitHandler = () => Promise<any>;
|
export type SubmitHandler = () => Promise<any>;
|
||||||
interface IFormGroupContext {
|
interface IFormGroupContext {
|
||||||
@ -12,7 +12,7 @@ const fallback: IFormGroupContext = {
|
|||||||
addSubmit: () => {},
|
addSubmit: () => {},
|
||||||
onDirty: () => {},
|
onDirty: () => {},
|
||||||
onErrors: () => {},
|
onErrors: () => {},
|
||||||
submitAll: () => Promise.resolve(),
|
submitAll: () => Promise.resolve()
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FormGroupContext = React.createContext(fallback);
|
export const FormGroupContext = React.createContext(fallback);
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
import GlobalApi from '../api/global';
|
import GlobalApi from '../api/global';
|
||||||
import useStorageState from '../state/storage';
|
import useStorageState from '../state/storage';
|
||||||
|
|
||||||
|
|
||||||
class GcpManager {
|
class GcpManager {
|
||||||
#api: GlobalApi | null = null;
|
#api: GlobalApi | null = null;
|
||||||
|
|
||||||
@ -59,15 +58,15 @@ class GcpManager {
|
|||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
#consecutiveFailures: number = 0;
|
#consecutiveFailures = 0;
|
||||||
#configured: boolean = false;
|
#configured = false;
|
||||||
|
|
||||||
private refreshLoop() {
|
private refreshLoop() {
|
||||||
if (!this.#configured) {
|
if (!this.#configured) {
|
||||||
this.#api!.gcp.isConfigured()
|
this.#api!.gcp.isConfigured()
|
||||||
.then((configured) => {
|
.then((configured) => {
|
||||||
if (configured === undefined) {
|
if (configured === undefined) {
|
||||||
throw new Error("can't check whether GCP is configured?");
|
throw new Error('can\'t check whether GCP is configured?');
|
||||||
}
|
}
|
||||||
this.#configured = configured;
|
this.#configured = configured;
|
||||||
if (this.#configured) {
|
if (this.#configured) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
import { Path, PatpNoSig } from '@urbit/api';
|
||||||
|
import { Group, Resource, roleTags, RoleTags } from '@urbit/api/groups';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { roleTags, RoleTags, Group, Resource } from '@urbit/api/groups';
|
|
||||||
import { PatpNoSig, Path } from '@urbit/api';
|
|
||||||
import { deSig } from './util';
|
|
||||||
|
|
||||||
export function roleForShip(
|
export function roleForShip(
|
||||||
group: Group,
|
group: Group,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
import { IndexedNotification, NotificationGraphConfig, Unreads } from '@urbit/api';
|
||||||
import bigInt, { BigInteger } from 'big-integer';
|
import bigInt, { BigInteger } from 'big-integer';
|
||||||
|
import _ from 'lodash';
|
||||||
import f from 'lodash/fp';
|
import f from 'lodash/fp';
|
||||||
import { Unreads, NotificationGraphConfig } from '@urbit/api';
|
|
||||||
|
|
||||||
export function getLastSeen(
|
export function getLastSeen(
|
||||||
unreads: Unreads,
|
unreads: Unreads,
|
||||||
@ -31,16 +32,29 @@ export function getNotificationCount(
|
|||||||
): number {
|
): number {
|
||||||
const unread = unreads.graph?.[path] || {};
|
const unread = unreads.graph?.[path] || {};
|
||||||
return Object.keys(unread)
|
return Object.keys(unread)
|
||||||
.map(index => unread[index]?.notifications?.length || 0)
|
.map(index => _.get(unread[index], 'notifications.length', 0))
|
||||||
.reduce(f.add, 0);
|
.reduce(f.add, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isWatching(
|
export function isWatching(
|
||||||
config: NotificationGraphConfig,
|
config: NotificationGraphConfig,
|
||||||
graph: string,
|
graph: string,
|
||||||
index = "/"
|
index = '/'
|
||||||
) {
|
) {
|
||||||
return !!config.watching.find(
|
return Boolean(config.watching.find(
|
||||||
watch => watch.graph === graph && watch.index === index
|
watch => watch.graph === graph && watch.index === index
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getNotificationKey(time: BigInteger, notification: IndexedNotification): string {
|
||||||
|
const base = time.toString();
|
||||||
|
if('graph' in notification.index) {
|
||||||
|
const { graph, index } = notification.index.graph;
|
||||||
|
return `${base}-${graph}-${index}`;
|
||||||
|
} else if('group' in notification.index) {
|
||||||
|
const { group } = notification.index.group;
|
||||||
|
return `${base}-${group}`;
|
||||||
|
}
|
||||||
|
return `${base}-unknown`;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
export function useIdlingState() {
|
export function useIdlingState() {
|
||||||
const [idling, setIdling] = useState(false);
|
const [idling, setIdling] = useState(false);
|
||||||
@ -16,7 +16,7 @@ export function useIdlingState() {
|
|||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('blur', blur);
|
window.removeEventListener('blur', blur);
|
||||||
window.removeEventListener('focus', focus);
|
window.removeEventListener('focus', focus);
|
||||||
}
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return idling;
|
return idling;
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import useLocalState, { LocalState } from "~/logic/state/local";
|
import useLocalState from '~/logic/state/local';
|
||||||
import useSettingsState from "~/logic/state/settings";
|
import useSettingsState from '~/logic/state/settings';
|
||||||
import GlobalApi from "../api/global";
|
import { BackgroundConfig, RemoteContentPolicy } from '~/types';
|
||||||
import { BackgroundConfig, RemoteContentPolicy } from "~/types";
|
import GlobalApi from '../api/global';
|
||||||
|
|
||||||
const getBackgroundString = (bg: BackgroundConfig) => {
|
const getBackgroundString = (bg: BackgroundConfig) => {
|
||||||
if (bg?.type === "url") {
|
if (bg?.type === 'url') {
|
||||||
return bg.url;
|
return bg.url;
|
||||||
} else if (bg?.type === "color") {
|
} else if (bg?.type === 'color') {
|
||||||
return bg.color;
|
return bg.color;
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -18,17 +18,17 @@ export function useMigrateSettings(api: GlobalApi) {
|
|||||||
const { display, remoteContentPolicy, calm } = useSettingsState();
|
const { display, remoteContentPolicy, calm } = useSettingsState();
|
||||||
|
|
||||||
return async () => {
|
return async () => {
|
||||||
let promises: Promise<any>[] = [];
|
const promises: Promise<any>[] = [];
|
||||||
|
|
||||||
if (local.hideAvatars !== calm.hideAvatars) {
|
if (local.hideAvatars !== calm.hideAvatars) {
|
||||||
promises.push(
|
promises.push(
|
||||||
api.settings.putEntry("calm", "hideAvatars", local.hideAvatars)
|
api.settings.putEntry('calm', 'hideAvatars', local.hideAvatars)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local.hideNicknames !== calm.hideNicknames) {
|
if (local.hideNicknames !== calm.hideNicknames) {
|
||||||
promises.push(
|
promises.push(
|
||||||
api.settings.putEntry("calm", "hideNicknames", local.hideNicknames)
|
api.settings.putEntry('calm', 'hideNicknames', local.hideNicknames)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,15 +38,15 @@ export function useMigrateSettings(api: GlobalApi) {
|
|||||||
) {
|
) {
|
||||||
promises.push(
|
promises.push(
|
||||||
api.settings.putEntry(
|
api.settings.putEntry(
|
||||||
"display",
|
'display',
|
||||||
"background",
|
'background',
|
||||||
getBackgroundString(local.background)
|
getBackgroundString(local.background)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
promises.push(
|
promises.push(
|
||||||
api.settings.putEntry(
|
api.settings.putEntry(
|
||||||
"display",
|
'display',
|
||||||
"backgroundType",
|
'backgroundType',
|
||||||
local.background?.type
|
local.background?.type
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -57,12 +57,12 @@ export function useMigrateSettings(api: GlobalApi) {
|
|||||||
const localVal = local.remoteContentPolicy[key];
|
const localVal = local.remoteContentPolicy[key];
|
||||||
if (localVal !== remoteContentPolicy[key]) {
|
if (localVal !== remoteContentPolicy[key]) {
|
||||||
promises.push(
|
promises.push(
|
||||||
api.settings.putEntry("remoteContentPolicy", key, localVal)
|
api.settings.putEntry('remoteContentPolicy', key, localVal)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
localStorage.removeItem("localReducer");
|
localStorage.removeItem('localReducer');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { GraphNotifIndex, GraphNotificationContents } from '@urbit/api';
|
import { GraphNotificationContents, GraphNotifIndex } from '@urbit/api';
|
||||||
|
|
||||||
export function getParentIndex(
|
export function getParentIndex(
|
||||||
idx: GraphNotifIndex,
|
idx: GraphNotifIndex,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { cite } from '~/logic/lib/util';
|
|
||||||
import { isChannelAdmin } from '~/logic/lib/group';
|
import { isChannelAdmin } from '~/logic/lib/group';
|
||||||
|
import { cite } from '~/logic/lib/util';
|
||||||
|
|
||||||
const makeIndexes = () => new Map([
|
const makeIndexes = () => new Map([
|
||||||
['ships', []],
|
['ships', []],
|
||||||
@ -23,7 +23,7 @@ const result = function(title, link, app, host) {
|
|||||||
const shipIndex = function(contacts) {
|
const shipIndex = function(contacts) {
|
||||||
const ships = [];
|
const ships = [];
|
||||||
Object.keys(contacts).map((e) => {
|
Object.keys(contacts).map((e) => {
|
||||||
return ships.push(result(e, `/~profile/${e}`, 'profile', contacts[e]?.status || ""));
|
return ships.push(result(e, `/~profile/${e}`, 'profile', contacts[e]?.status || ''));
|
||||||
});
|
});
|
||||||
return ships;
|
return ships;
|
||||||
};
|
};
|
||||||
@ -38,11 +38,11 @@ const commandIndex = function (currentGroup, groups, associations) {
|
|||||||
? (association.metadata.vip === 'member-metadata' || isChannelAdmin(group, currentGroup))
|
? (association.metadata.vip === 'member-metadata' || isChannelAdmin(group, currentGroup))
|
||||||
: !currentGroup; // home workspace or hasn't loaded
|
: !currentGroup; // home workspace or hasn't loaded
|
||||||
const workspace = currentGroup || '/home';
|
const workspace = currentGroup || '/home';
|
||||||
commands.push(result(`Groups: Create`, `/~landscape/new`, 'Groups', null));
|
commands.push(result('Groups: Create', '/~landscape/new', 'Groups', null));
|
||||||
if (canAdd) {
|
if (canAdd) {
|
||||||
commands.push(result(`Channel: Create`, `/~landscape${workspace}/new`, 'Groups', null));
|
commands.push(result('Channel: Create', `/~landscape${workspace}/new`, 'Groups', null));
|
||||||
}
|
}
|
||||||
commands.push(result(`Groups: Join`, `/~landscape/join`, 'Groups', null));
|
commands.push(result('Groups: Join', '/~landscape/join', 'Groups', null));
|
||||||
|
|
||||||
return commands;
|
return commands;
|
||||||
};
|
};
|
||||||
@ -80,7 +80,7 @@ const otherIndex = function(config) {
|
|||||||
logout: result('Log Out', '/~/logout', 'logout', null)
|
logout: result('Log Out', '/~/logout', 'logout', null)
|
||||||
};
|
};
|
||||||
other.push(result('Tutorial', '/?tutorial=true', 'tutorial', null));
|
other.push(result('Tutorial', '/?tutorial=true', 'tutorial', null));
|
||||||
for(let cat of config.categories) {
|
for(const cat of config.categories) {
|
||||||
if(idx[cat]) {
|
if(idx[cat]) {
|
||||||
other.push(idx[cat]);
|
other.push(idx[cat]);
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ export default function index(contacts, associations, apps, currentGroup, groups
|
|||||||
}).map((e) => {
|
}).map((e) => {
|
||||||
// iterate through each app's metadata object
|
// iterate through each app's metadata object
|
||||||
Object.keys(associations[e])
|
Object.keys(associations[e])
|
||||||
.filter((association) => !associations?.[e]?.[association]?.metadata?.hidden)
|
.filter(association => !associations?.[e]?.[association]?.metadata?.hidden)
|
||||||
.map((association) => {
|
.map((association) => {
|
||||||
const each = associations[e][association];
|
const each = associations[e][association];
|
||||||
let title = each.resource;
|
let title = each.resource;
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Association,
|
ReferenceContent, resourceFromPath
|
||||||
resourceFromPath,
|
} from '@urbit/api';
|
||||||
Group,
|
|
||||||
ReferenceContent,
|
|
||||||
} from "@urbit/api";
|
|
||||||
|
|
||||||
export function getPermalinkForGraph(
|
export function getPermalinkForGraph(
|
||||||
group: string,
|
group: string,
|
||||||
graph: string,
|
graph: string,
|
||||||
index = ""
|
index = ''
|
||||||
) {
|
) {
|
||||||
const groupLink = getPermalinkForAssociatedGroup(group);
|
const groupLink = getPermalinkForAssociatedGroup(group);
|
||||||
const { ship, name } = resourceFromPath(graph);
|
const { ship, name } = resourceFromPath(graph);
|
||||||
@ -21,16 +18,16 @@ function getPermalinkForAssociatedGroup(group: string) {
|
|||||||
return `web+urbitgraph://group/${ship}/${name}`;
|
return `web+urbitgraph://group/${ship}/${name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type Permalink = GraphPermalink | GroupPermalink;
|
type Permalink = GraphPermalink | GroupPermalink;
|
||||||
|
|
||||||
interface GroupPermalink {
|
export interface GroupPermalink {
|
||||||
type: "group";
|
type: 'group';
|
||||||
group: string;
|
group: string;
|
||||||
link: string;
|
link: string;
|
||||||
}
|
}
|
||||||
interface GraphPermalink {
|
|
||||||
type: "graph";
|
export interface GraphPermalink {
|
||||||
|
type: 'graph';
|
||||||
link: string;
|
link: string;
|
||||||
graph: string;
|
graph: string;
|
||||||
group: string;
|
group: string;
|
||||||
@ -43,16 +40,16 @@ function parseGraphPermalink(
|
|||||||
segments: string[]
|
segments: string[]
|
||||||
): GraphPermalink | null {
|
): GraphPermalink | null {
|
||||||
const [kind, ship, name, ...index] = segments;
|
const [kind, ship, name, ...index] = segments;
|
||||||
if (kind !== "graph") {
|
if (kind !== 'graph') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const graph = `/ship/${ship}/${name}`;
|
const graph = `/ship/${ship}/${name}`;
|
||||||
return {
|
return {
|
||||||
type: "graph",
|
type: 'graph',
|
||||||
link: link.slice(16),
|
link: link.slice(16),
|
||||||
graph,
|
graph,
|
||||||
group,
|
group,
|
||||||
index: `/${index.join("/")}`,
|
index: `/${index.join('/')}`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +61,7 @@ export function permalinkToReference(link: Permalink): ReferenceContent {
|
|||||||
group: link.group,
|
group: link.group,
|
||||||
index: link.index
|
index: link.index
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
return { reference };
|
return { reference };
|
||||||
} else {
|
} else {
|
||||||
const reference = {
|
const reference = {
|
||||||
@ -89,22 +86,22 @@ export function referenceToPermalink({ reference }: ReferenceContent): Permalink
|
|||||||
type: 'group',
|
type: 'group',
|
||||||
link,
|
link,
|
||||||
...reference
|
...reference
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parsePermalink(url: string): Permalink | null {
|
export function parsePermalink(url: string): Permalink | null {
|
||||||
const [kind, ...rest] = url.slice(17).split("/");
|
const [kind, ...rest] = url.slice(17).split('/');
|
||||||
if (kind === "group") {
|
if (kind === 'group') {
|
||||||
const [ship, name, ...graph] = rest;
|
const [ship, name, ...graph] = rest;
|
||||||
const group = `/ship/${ship}/${name}`;
|
const group = `/ship/${ship}/${name}`;
|
||||||
if (graph.length > 0) {
|
if (graph.length > 0) {
|
||||||
return parseGraphPermalink(url, group, graph);
|
return parseGraphPermalink(url, group, graph);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: "group",
|
type: 'group',
|
||||||
group,
|
group,
|
||||||
link: url.slice(11),
|
link: url.slice(11)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Post, GraphNode } from '@urbit/api';
|
import { GraphNode, Post } from '@urbit/api';
|
||||||
|
|
||||||
export const buntPost = (): Post => ({
|
export const buntPost = (): Post => ({
|
||||||
author: '',
|
author: '',
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { Post, GraphNode, TextContent } from '@urbit/api';
|
import { Content, GraphNode, Post, TextContent } from '@urbit/api';
|
||||||
|
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
||||||
|
import bigInt, { BigInteger } from 'big-integer';
|
||||||
import { buntPost } from '~/logic/lib/post';
|
import { buntPost } from '~/logic/lib/post';
|
||||||
import { unixToDa } from '~/logic/lib/util';
|
import { unixToDa } from '~/logic/lib/util';
|
||||||
import BigIntOrderedMap from "@urbit/api/lib/BigIntOrderedMap";
|
import tokenizeMessage from './tokenizeMessage';
|
||||||
import bigInt, { BigInteger } from 'big-integer';
|
|
||||||
|
|
||||||
export function newPost(
|
export function newPost(
|
||||||
title: string,
|
title: string,
|
||||||
@ -19,13 +20,15 @@ export function newPost(
|
|||||||
signatures: []
|
signatures: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tokenisedBody = tokenizeMessage(body);
|
||||||
|
|
||||||
const revContainer: Post = { ...root, index: root.index + '/1' };
|
const revContainer: Post = { ...root, index: root.index + '/1' };
|
||||||
const commentsContainer = { ...root, index: root.index + '/2' };
|
const commentsContainer = { ...root, index: root.index + '/2' };
|
||||||
|
|
||||||
const firstRevision: Post = {
|
const firstRevision: Post = {
|
||||||
...revContainer,
|
...revContainer,
|
||||||
index: revContainer.index + '/1',
|
index: revContainer.index + '/1',
|
||||||
contents: [{ text: title }, { text: body }]
|
contents: [{ text: title }, ...tokenisedBody]
|
||||||
};
|
};
|
||||||
|
|
||||||
const nodes = {
|
const nodes = {
|
||||||
@ -54,11 +57,12 @@ export function newPost(
|
|||||||
|
|
||||||
export function editPost(rev: number, noteId: BigInteger, title: string, body: string) {
|
export function editPost(rev: number, noteId: BigInteger, title: string, body: string) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
const tokenisedBody = tokenizeMessage(body);
|
||||||
const newRev: Post = {
|
const newRev: Post = {
|
||||||
author: `~${window.ship}`,
|
author: `~${window.ship}`,
|
||||||
index: `/${noteId.toString()}/1/${rev}`,
|
index: `/${noteId.toString()}/1/${rev}`,
|
||||||
'time-sent': now,
|
'time-sent': now,
|
||||||
contents: [{ text: title }, { text: body }],
|
contents: [{ text: title }, ...tokenisedBody],
|
||||||
hash: null,
|
hash: null,
|
||||||
signatures: []
|
signatures: []
|
||||||
};
|
};
|
||||||
@ -85,8 +89,9 @@ export function getLatestRevision(node: GraphNode): [number, string, string, Pos
|
|||||||
if (!rev) {
|
if (!rev) {
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
const [title, body] = rev.post.contents as TextContent[];
|
const title = rev.post.contents[0];
|
||||||
return [revNum.toJSNumber(), title.text, body.text, rev.post];
|
const body = rev.post.contents.slice(1);
|
||||||
|
return [revNum.toJSNumber(), title.text, body, rev.post];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLatestCommentRevision(node: GraphNode): [number, Post] {
|
export function getLatestCommentRevision(node: GraphNode): [number, Post] {
|
||||||
@ -113,10 +118,12 @@ export function getComments(node: GraphNode): GraphNode {
|
|||||||
return comments;
|
return comments;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSnippet(body: string) {
|
export function getSnippet(body: Content[]) {
|
||||||
const newlineIdx = body.indexOf('\n', 2);
|
const firstContent = body
|
||||||
const end = newlineIdx > -1 ? newlineIdx : body.length;
|
.filter((c: Content): c is TextContent => 'text' in c).map(c => c.text)[0] ?? '';
|
||||||
const start = body.substr(0, end);
|
const newlineIdx = firstContent.indexOf('\n', 2);
|
||||||
|
const end = newlineIdx > -1 ? newlineIdx : firstContent.length;
|
||||||
|
const start = firstContent.substr(0, end);
|
||||||
|
|
||||||
return (start === body || start.startsWith('![')) ? start : `${start}...`;
|
return (start === firstContent || firstContent.startsWith('![')) ? start : `${start}...`;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { memo } from 'react';
|
|
||||||
import { sigil, reactRenderer } from '@tlon/sigil-js';
|
|
||||||
import { Box } from '@tlon/indigo-react';
|
import { Box } from '@tlon/indigo-react';
|
||||||
|
import { reactRenderer, sigil } from '@tlon/sigil-js';
|
||||||
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
export const foregroundFromBackground = (background) => {
|
export const foregroundFromBackground = (background) => {
|
||||||
const rgb = {
|
const rgb = {
|
||||||
|
@ -1,31 +1,43 @@
|
|||||||
import urbitOb from 'urbit-ob';
|
import urbitOb from 'urbit-ob';
|
||||||
import { parsePermalink, permalinkToReference } from "~/logic/lib/permalinks";
|
import { parsePermalink, permalinkToReference } from '~/logic/lib/permalinks';
|
||||||
|
|
||||||
const URL_REGEX = new RegExp(String(/^(([\w\-\+]+:\/\/)[-a-zA-Z0-9:@;?&=\/%\+\.\*!'\(\),\$_\{\}\^~\[\]`#|]+\w)/.source));
|
const URL_REGEX = new RegExp(String(/^(([\w\-\+]+:\/\/)[-a-zA-Z0-9:@;?&=\/%\+\.\*!'\(\),\$_\{\}\^~\[\]`#|]+\w)/.source));
|
||||||
|
|
||||||
|
const GROUP_REGEX = new RegExp(String(/^~[-a-z_]+\/[-a-z]+/.source));
|
||||||
|
|
||||||
const isUrl = (string) => {
|
const isUrl = (string) => {
|
||||||
try {
|
try {
|
||||||
return URL_REGEX.test(string);
|
return URL_REGEX.test(string);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const isRef = (str) => {
|
const isRef = (str) => {
|
||||||
return isUrl(str) && str.startsWith("web+urbitgraph://");
|
return isUrl(str) && str.startsWith('web+urbitgraph://');
|
||||||
|
};
|
||||||
|
|
||||||
|
const isGroup = str => {
|
||||||
|
try {
|
||||||
|
return GROUP_REGEX.test(str);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const convertToGroupRef = (group) => `web+urbitgraph://group/${group}`;
|
||||||
|
|
||||||
const tokenizeMessage = (text) => {
|
const tokenizeMessage = (text) => {
|
||||||
let messages = [];
|
let messages = [];
|
||||||
let message = [];
|
// by line
|
||||||
|
let currTextBlock = [];
|
||||||
let isInCodeBlock = false;
|
let isInCodeBlock = false;
|
||||||
let endOfCodeBlock = false;
|
let endOfCodeBlock = false;
|
||||||
text.split(/\r?\n/).forEach((line, index) => {
|
text.split(/\r?\n/).forEach((line, index) => {
|
||||||
if (index !== 0) {
|
// by space
|
||||||
message.push('\n');
|
let currTextLine = [];
|
||||||
}
|
|
||||||
// A line of backticks enters and exits a codeblock
|
// A line of backticks enters and exits a codeblock
|
||||||
if (line.startsWith('```')) {
|
if (line.trim().startsWith('```')) {
|
||||||
// But we need to check if we've ended a codeblock
|
// But we need to check if we've ended a codeblock
|
||||||
endOfCodeBlock = isInCodeBlock;
|
endOfCodeBlock = isInCodeBlock;
|
||||||
isInCodeBlock = (!isInCodeBlock);
|
isInCodeBlock = (!isInCodeBlock);
|
||||||
@ -34,25 +46,26 @@ const tokenizeMessage = (text) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isInCodeBlock || endOfCodeBlock) {
|
if (isInCodeBlock || endOfCodeBlock) {
|
||||||
message.push(line);
|
currTextLine = [line];
|
||||||
} else {
|
} else {
|
||||||
line.split(/\s/).forEach((str) => {
|
const words = line.split(/\s/);
|
||||||
|
words.forEach((word, idx) => {
|
||||||
|
const str = isGroup(word) ? convertToGroupRef(word) : word;
|
||||||
|
|
||||||
|
const last = words.length - 1 === idx;
|
||||||
if (
|
if (
|
||||||
(str.startsWith('`') && str !== '`')
|
(str.startsWith('`') && str !== '`')
|
||||||
|| (str === '`' && !isInCodeBlock)
|
|| (str === '`' && !isInCodeBlock)
|
||||||
) {
|
) {
|
||||||
isInCodeBlock = true;
|
isInCodeBlock = true;
|
||||||
} else if (
|
|
||||||
(str.endsWith('`') && str !== '`')
|
|
||||||
|| (str === '`' && isInCodeBlock)
|
|
||||||
) {
|
|
||||||
isInCodeBlock = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isRef(str) && !isInCodeBlock) {
|
if(isRef(str) && !isInCodeBlock) {
|
||||||
if (message.length > 0) {
|
if (currTextLine.length > 0 || currTextBlock.length > 0) {
|
||||||
// If we're in the middle of a message, add it to the stack and reset
|
// If we're in the middle of a message, add it to the stack and reset
|
||||||
messages.push({ text: message.join(' ') });
|
currTextLine.push('');
|
||||||
|
messages.push({ text: currTextBlock.join('\n') + currTextLine.join(' ') });
|
||||||
|
currTextBlock = last ? [''] : [];
|
||||||
|
currTextLine = [];
|
||||||
}
|
}
|
||||||
const link = parsePermalink(str);
|
const link = parsePermalink(str);
|
||||||
if(!link) {
|
if(!link) {
|
||||||
@ -61,34 +74,46 @@ const tokenizeMessage = (text) => {
|
|||||||
const reference = permalinkToReference(link);
|
const reference = permalinkToReference(link);
|
||||||
messages.push(reference);
|
messages.push(reference);
|
||||||
}
|
}
|
||||||
message = [];
|
currTextLine = [];
|
||||||
} else if (isUrl(str) && !isInCodeBlock) {
|
} else if (isUrl(str) && !isInCodeBlock) {
|
||||||
if (message.length > 0) {
|
if (currTextLine.length > 0 || currTextBlock.length > 0) {
|
||||||
// If we're in the middle of a message, add it to the stack and reset
|
// If we're in the middle of a message, add it to the stack and reset
|
||||||
messages.push({ text: message.join(' ') });
|
currTextLine.push('');
|
||||||
message = [];
|
messages.push({ text: currTextBlock.join('\n') + currTextLine.join(' ') });
|
||||||
|
currTextBlock = last ? [''] : [];
|
||||||
|
currTextLine = [];
|
||||||
}
|
}
|
||||||
messages.push({ url: str });
|
messages.push({ url: str });
|
||||||
message = [];
|
currTextLine = [];
|
||||||
} else if(urbitOb.isValidPatp(str) && !isInCodeBlock) {
|
} else if(urbitOb.isValidPatp(str) && !isInCodeBlock) {
|
||||||
if (message.length > 0) {
|
if (currTextLine.length > 0 || currTextBlock.length > 0) {
|
||||||
// If we're in the middle of a message, add it to the stack and reset
|
// If we're in the middle of a message, add it to the stack and reset
|
||||||
messages.push({ text: message.join(' ') });
|
currTextLine.push('');
|
||||||
message = [];
|
messages.push({ text: currTextBlock.join('\n') + currTextLine.join(' ') });
|
||||||
|
currTextBlock = last ? [''] : [];
|
||||||
|
currTextLine = [];
|
||||||
}
|
}
|
||||||
messages.push({ mention: str });
|
messages.push({ mention: str });
|
||||||
message = [];
|
currTextLine = [];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
message.push(str);
|
currTextLine.push(str);
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
(str.endsWith('`') && str !== '`')
|
||||||
|
|| (str === '`' && isInCodeBlock)
|
||||||
|
) {
|
||||||
|
isInCodeBlock = false;
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
currTextBlock.push(currTextLine.join(' '))
|
||||||
});
|
});
|
||||||
|
|
||||||
if (message.length) {
|
if (currTextBlock.length) {
|
||||||
// Add any remaining message
|
// Add any remaining message
|
||||||
messages.push({ text: message.join(' ') });
|
messages.push({ text: currTextBlock.join('\n') });
|
||||||
}
|
}
|
||||||
return messages;
|
return messages;
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Associations } from '@urbit/api';
|
import { Associations } from '@urbit/api';
|
||||||
import { TutorialProgress } from '~/types';
|
|
||||||
import { AlignX, AlignY } from '~/logic/lib/relativePosition';
|
import { AlignX, AlignY } from '~/logic/lib/relativePosition';
|
||||||
|
import { TutorialProgress } from '~/types';
|
||||||
import { Direction } from '~/views/components/Triangle';
|
import { Direction } from '~/views/components/Triangle';
|
||||||
|
|
||||||
export const MODAL_WIDTH = 256;
|
export const MODAL_WIDTH = 256;
|
||||||
@ -92,7 +92,7 @@ export const progressDetails: Record<TutorialProgress, StepDetail> = {
|
|||||||
alignY: 'top',
|
alignY: 'top',
|
||||||
arrow: 'East',
|
arrow: 'East',
|
||||||
offsetX: MODAL_WIDTH + 24,
|
offsetX: MODAL_WIDTH + 24,
|
||||||
offsetY: 80,
|
offsetY: 80
|
||||||
},
|
},
|
||||||
channels: {
|
channels: {
|
||||||
title: 'Channels',
|
title: 'Channels',
|
||||||
@ -157,17 +157,17 @@ export const progressDetails: Record<TutorialProgress, StepDetail> = {
|
|||||||
alignX: 'right',
|
alignX: 'right',
|
||||||
arrow: 'South',
|
arrow: 'South',
|
||||||
offsetX: -300 + MODAL_WIDTH / 2,
|
offsetX: -300 + MODAL_WIDTH / 2,
|
||||||
offsetY: -4,
|
offsetY: -4
|
||||||
},
|
},
|
||||||
leap: {
|
leap: {
|
||||||
title: 'Leap',
|
title: 'Leap',
|
||||||
description:
|
description:
|
||||||
'Leap allows you to go to a specific channel, message, collection, profile or group simply by typing in a command or selecting a shortcut from the dropdown menu.',
|
'Leap allows you to go to a specific channel, message, collection, profile or group simply by typing in a command or selecting a shortcut from the dropdown menu.',
|
||||||
url: `/~profile/~${window.ship}`,
|
url: `/~profile/~${window.ship}`,
|
||||||
alignY: "top",
|
alignY: 'top',
|
||||||
alignX: "left",
|
alignX: 'left',
|
||||||
arrow: "North",
|
arrow: 'North',
|
||||||
offsetX: 76,
|
offsetX: 76,
|
||||||
offsetY: -48,
|
offsetY: -48
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { writeText } from "./util";
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { useCallback, useState, useMemo } from "react";
|
import { writeText } from './util';
|
||||||
|
|
||||||
export function useCopy(copied: string, display: string) {
|
export function useCopy(copied: string, display?: string) {
|
||||||
const [didCopy, setDidCopy] = useState(false);
|
const [didCopy, setDidCopy] = useState(false);
|
||||||
const doCopy = useCallback(() => {
|
const doCopy = useCallback(() => {
|
||||||
writeText(copied);
|
writeText(copied);
|
||||||
@ -11,9 +11,9 @@ export function useCopy(copied: string, display: string) {
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
}, [copied]);
|
}, [copied]);
|
||||||
|
|
||||||
const copyDisplay = useMemo(() => (didCopy ? "Copied" : display), [
|
const copyDisplay = useMemo(() => (didCopy ? 'Copied' : display), [
|
||||||
didCopy,
|
didCopy,
|
||||||
display,
|
display
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return { copyDisplay, doCopy, didCopy };
|
return { copyDisplay, doCopy, didCopy };
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState, useCallback, useMemo, useEffect } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
function validateDragEvent(e: DragEvent): FileList | File[] | true | null {
|
function validateDragEvent(e: DragEvent): FileList | File[] | true | null {
|
||||||
const files: File[] = [];
|
const files: File[] = [];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, useMemo, useCallback } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
export function useDropdown<C>(
|
export function useDropdown<C>(
|
||||||
candidates: C[],
|
candidates: C[],
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, RefObject, useRef, useState } from 'react';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import { RefObject, useEffect, useState } from 'react';
|
||||||
import usePreviousValue from './usePreviousValue';
|
import usePreviousValue from './usePreviousValue';
|
||||||
|
|
||||||
export function distanceToBottom(el: HTMLElement) {
|
export function distanceToBottom(el: HTMLElement) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState, useCallback, useEffect } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
function retrieve<T>(key: string, initial: T): T {
|
function retrieve<T>(key: string, initial: T): T {
|
||||||
const s = localStorage.getItem(key);
|
const s = localStorage.getItem(key);
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
|
import { Box } from '@tlon/indigo-react';
|
||||||
import React, {
|
import React, {
|
||||||
useState,
|
|
||||||
ReactNode,
|
ReactNode,
|
||||||
useCallback,
|
useCallback,
|
||||||
useMemo,
|
useMemo,
|
||||||
useRef
|
useRef, useState
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
import { PropFunc } from '~/types';
|
||||||
import { Box } from '@tlon/indigo-react';
|
|
||||||
import { ModalOverlay } from '~/views/components/ModalOverlay';
|
import { ModalOverlay } from '~/views/components/ModalOverlay';
|
||||||
import { Portal } from '~/views/components/Portal';
|
import { Portal } from '~/views/components/Portal';
|
||||||
import { PropFunc } from '~/types';
|
|
||||||
|
|
||||||
type ModalFunc = (dismiss: () => void) => JSX.Element;
|
type ModalFunc = (dismiss: () => void) => JSX.Element;
|
||||||
interface UseModalProps {
|
interface UseModalProps {
|
||||||
@ -59,7 +57,7 @@ export function useModal(props: UseModalProps & PropFunc<typeof Box>): UseModalR
|
|||||||
display="flex"
|
display="flex"
|
||||||
alignItems="stretch"
|
alignItems="stretch"
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
spacing="2"
|
spacing={2}
|
||||||
dismiss={dismiss}
|
dismiss={dismiss}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, RefObject } from 'react';
|
import { RefObject, useEffect } from 'react';
|
||||||
|
|
||||||
export function useOutsideClick(
|
export function useOutsideClick(
|
||||||
ref: RefObject<HTMLElement | null | undefined>,
|
ref: RefObject<HTMLElement | null | undefined>,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useMemo, useCallback } from "react";
|
import _ from 'lodash';
|
||||||
import { useLocation } from "react-router-dom";
|
import { useCallback, useMemo } from 'react';
|
||||||
import _ from "lodash";
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
function mergeQuery(search: URLSearchParams, added: Record<string, string>) {
|
function mergeQuery(search: URLSearchParams, added: Record<string, string>) {
|
||||||
_.forIn(added, (v, k) => {
|
_.forIn(added, (v, k) => {
|
||||||
@ -32,7 +32,7 @@ export function useQuery() {
|
|||||||
mergeQuery(q, params);
|
mergeQuery(q, params);
|
||||||
return {
|
return {
|
||||||
pathname: path,
|
pathname: path,
|
||||||
search: q.toString(),
|
search: q.toString()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[search, pathname]
|
[search, pathname]
|
||||||
@ -41,6 +41,6 @@ export function useQuery() {
|
|||||||
return {
|
return {
|
||||||
query,
|
query,
|
||||||
appendQuery,
|
appendQuery,
|
||||||
toQuery,
|
toQuery
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import {unstable_batchedUpdates} from "react-dom";
|
import { unstable_batchedUpdates } from 'react-dom';
|
||||||
|
|
||||||
export type IOInstance<I, P, O> = (
|
export type IOInstance<I, P, O> = (
|
||||||
input: I
|
input: I
|
||||||
@ -29,7 +29,7 @@ export function useRunIO<I, O>(
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
reject(new Error("useRunIO: key changed"));
|
reject(new Error('useRunIO: key changed'));
|
||||||
setDone(false);
|
setDone(false);
|
||||||
setOutput(null);
|
setOutput(null);
|
||||||
}, [key]);
|
}, [key]);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { MouseEvent, useCallback, useState, useEffect } from 'react';
|
import { MouseEvent, useCallback, useEffect, useState } from 'react';
|
||||||
export type AsyncClickableState = 'waiting' | 'error' | 'loading' | 'success';
|
export type AsyncClickableState = 'waiting' | 'error' | 'loading' | 'success';
|
||||||
|
|
||||||
export function useStatelessAsyncClickable(
|
export function useStatelessAsyncClickable(
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
import { useCallback, useMemo, useEffect, useRef, useState } from 'react';
|
|
||||||
import {
|
|
||||||
GcpState,
|
|
||||||
S3State,
|
|
||||||
StorageState
|
|
||||||
} from '../../types';
|
|
||||||
import S3 from 'aws-sdk/clients/s3';
|
import S3 from 'aws-sdk/clients/s3';
|
||||||
import GcpClient from './GcpClient';
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { StorageClient, StorageAcl } from './StorageClient';
|
|
||||||
import { dateToDa, deSig } from './util';
|
|
||||||
import useStorageState from '../state/storage';
|
import useStorageState from '../state/storage';
|
||||||
|
import GcpClient from './GcpClient';
|
||||||
|
import { StorageAcl, StorageClient } from './StorageClient';
|
||||||
|
import { dateToDa, deSig } from './util';
|
||||||
|
|
||||||
export interface IuseStorage {
|
export interface IuseStorage {
|
||||||
canUpload: boolean;
|
canUpload: boolean;
|
||||||
upload: (file: File, bucket: string) => Promise<string>;
|
upload: (file: File, bucket: string) => Promise<string>;
|
||||||
uploadDefault: (file: File) => Promise<string>;
|
uploadDefault: (file: File) => Promise<string>;
|
||||||
uploading: boolean;
|
uploading: boolean;
|
||||||
promptUpload: () => Promise<unknown>;
|
promptUpload: () => Promise<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStorage = ({ accept = '*' } = { accept: '*' }): IuseStorage => {
|
const useStorage = ({ accept = '*' } = { accept: '*' }): IuseStorage => {
|
||||||
@ -54,7 +48,7 @@ const useStorage = ({ accept = '*' } = { accept: '*' }): IuseStorage => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const upload = useCallback(
|
const upload = useCallback(
|
||||||
async (file: File, bucket: string) => {
|
async (file: File, bucket: string): Promise<string> => {
|
||||||
if (client.current === null) {
|
if (client.current === null) {
|
||||||
throw new Error('Storage not ready');
|
throw new Error('Storage not ready');
|
||||||
}
|
}
|
||||||
@ -83,7 +77,7 @@ const useStorage = ({ accept = '*' } = { accept: '*' }): IuseStorage => {
|
|||||||
[client, setUploading]
|
[client, setUploading]
|
||||||
);
|
);
|
||||||
|
|
||||||
const uploadDefault = useCallback(async (file: File) => {
|
const uploadDefault = useCallback(async (file: File): Promise<string> => {
|
||||||
if (s3.configuration.currentBucket === '') {
|
if (s3.configuration.currentBucket === '') {
|
||||||
throw new Error('current bucket not set');
|
throw new Error('current bucket not set');
|
||||||
}
|
}
|
||||||
@ -91,7 +85,7 @@ const useStorage = ({ accept = '*' } = { accept: '*' }): IuseStorage => {
|
|||||||
}, [s3, upload]);
|
}, [s3, upload]);
|
||||||
|
|
||||||
const promptUpload = useCallback(
|
const promptUpload = useCallback(
|
||||||
() => {
|
(): Promise<string> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const fileSelector = document.createElement('input');
|
const fileSelector = document.createElement('input');
|
||||||
fileSelector.setAttribute('type', 'file');
|
fileSelector.setAttribute('type', 'file');
|
||||||
@ -101,10 +95,10 @@ const useStorage = ({ accept = '*' } = { accept: '*' }): IuseStorage => {
|
|||||||
const files = fileSelector.files;
|
const files = fileSelector.files;
|
||||||
if (!files || files.length <= 0) {
|
if (!files || files.length <= 0) {
|
||||||
reject();
|
reject();
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
uploadDefault(files[0]).then(resolve);
|
uploadDefault(files[0]).then(resolve);
|
||||||
document.body.removeChild(fileSelector);
|
document.body.removeChild(fileSelector);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
document.body.appendChild(fileSelector);
|
document.body.appendChild(fileSelector);
|
||||||
fileSelector.click();
|
fileSelector.click();
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { useState, useCallback } from "react";
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
export function useToggleState(initial: boolean) {
|
export function useToggleState(initial: boolean) {
|
||||||
const [state, setState] = useState(initial);
|
const [state, setState] = useState(initial);
|
||||||
|
|
||||||
const toggle = useCallback(() => {
|
const toggle = useCallback(() => {
|
||||||
setState((s) => !s);
|
setState(s => !s);
|
||||||
}, [setState]);
|
}, [setState]);
|
||||||
|
|
||||||
return [state, toggle] as const;
|
return [state, toggle] as const;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
export function useWaitForProps<P>(props: P, timeout = 0) {
|
export function useWaitForProps<P>(props: P, timeout = 0) {
|
||||||
const [resolve, setResolve] = useState<() => void>(() => () => {});
|
const [resolve, setResolve] = useState<() => void>(() => () => {});
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
import { useEffect, useState, useCallback, useMemo } from 'react';
|
/* eslint-disable max-lines */
|
||||||
import _ from 'lodash';
|
|
||||||
import f, { compose, memoize } from 'lodash/fp';
|
|
||||||
import bigInt, { BigInteger } from 'big-integer';
|
|
||||||
import { Association, Contact } from '@urbit/api';
|
import { Association, Contact } from '@urbit/api';
|
||||||
import useLocalState from '../state/local';
|
|
||||||
import produce, { enableMapSet } from 'immer';
|
|
||||||
import useSettingsState from '../state/settings';
|
|
||||||
import { State, UseStore } from 'zustand';
|
|
||||||
import { Cage } from '~/types/cage';
|
|
||||||
import { BaseState } from '../state/base';
|
|
||||||
import anyAscii from 'any-ascii';
|
import anyAscii from 'any-ascii';
|
||||||
|
import bigInt, { BigInteger } from 'big-integer';
|
||||||
|
import { enableMapSet } from 'immer';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import f from 'lodash/fp';
|
||||||
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { IconRef } from '~/types';
|
||||||
|
import useSettingsState from '../state/settings';
|
||||||
|
|
||||||
enableMapSet();
|
enableMapSet();
|
||||||
|
|
||||||
@ -24,7 +22,9 @@ export const MOMENT_CALENDAR_DATE = {
|
|||||||
sameElse: '~YYYY.M.D'
|
sameElse: '~YYYY.M.D'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getModuleIcon = (mod: string) => {
|
export type GraphModule = 'link' | 'post' | 'chat' | 'publish';
|
||||||
|
|
||||||
|
export const getModuleIcon = (mod: GraphModule): IconRef => {
|
||||||
if (mod === 'link') {
|
if (mod === 'link') {
|
||||||
return 'Collection';
|
return 'Collection';
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ export const getModuleIcon = (mod: string) => {
|
|||||||
return 'Dashboard';
|
return 'Dashboard';
|
||||||
}
|
}
|
||||||
|
|
||||||
return _.capitalize(mod);
|
return _.capitalize(mod) as IconRef;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function wait(ms: number) {
|
export function wait(ms: number) {
|
||||||
@ -172,9 +172,9 @@ export function dateToDa(d: Date, mil = false) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deSig(ship: string) {
|
export function deSig(ship: string): string {
|
||||||
if (!ship) {
|
if (!ship) {
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
return ship.replace('~', '');
|
return ship.replace('~', '');
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ export const hexToUx = (hex) => {
|
|||||||
return `0x${ux}`;
|
return `0x${ux}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function writeText(str: string) {
|
export function writeText(str: string | null): Promise<void> {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
const range = document.createRange();
|
const range = document.createRange();
|
||||||
range.selectNodeContents(document.body);
|
range.selectNodeContents(document.body);
|
||||||
@ -226,11 +226,11 @@ export function writeText(str: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// trim patps to match dojo, chat-cli
|
// trim patps to match dojo, chat-cli
|
||||||
export function cite(ship: string) {
|
export function cite(ship: string): string {
|
||||||
let patp = ship,
|
let patp = ship,
|
||||||
shortened = '';
|
shortened = '';
|
||||||
if (patp === null || patp === '') {
|
if (patp === null || patp === '') {
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
if (patp.startsWith('~')) {
|
if (patp.startsWith('~')) {
|
||||||
patp = patp.substr(1);
|
patp = patp.substr(1);
|
||||||
@ -400,7 +400,7 @@ export function pluralize(text: string, isPlural = false, vowel = false) {
|
|||||||
export function useShowNickname(contact: Contact | null, hide?: boolean): boolean {
|
export function useShowNickname(contact: Contact | null, hide?: boolean): boolean {
|
||||||
const hideState = useSettingsState(state => state.calm.hideNicknames);
|
const hideState = useSettingsState(state => state.calm.hideNicknames);
|
||||||
const hideNicknames = typeof hide !== 'undefined' ? hide : hideState;
|
const hideNicknames = typeof hide !== 'undefined' ? hide : hideState;
|
||||||
return !!(contact && contact.nickname && !hideNicknames);
|
return Boolean(contact && contact.nickname && !hideNicknames);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface useHoveringInterface {
|
interface useHoveringInterface {
|
||||||
@ -413,19 +413,25 @@ interface useHoveringInterface {
|
|||||||
|
|
||||||
export const useHovering = (): useHoveringInterface => {
|
export const useHovering = (): useHoveringInterface => {
|
||||||
const [hovering, setHovering] = useState(false);
|
const [hovering, setHovering] = useState(false);
|
||||||
const onMouseOver = useCallback(() => setHovering(true), [])
|
const onMouseOver = useCallback(() => setHovering(true), []);
|
||||||
const onMouseLeave = useCallback(() => setHovering(false), [])
|
const onMouseLeave = useCallback(() => setHovering(false), []);
|
||||||
const bind = useMemo(() => ({
|
const bind = useMemo(() => ({
|
||||||
onMouseOver,
|
onMouseOver,
|
||||||
onMouseLeave,
|
onMouseLeave
|
||||||
}), [onMouseLeave, onMouseOver]);
|
}), [onMouseLeave, onMouseOver]);
|
||||||
|
|
||||||
|
|
||||||
return useMemo(() => ({ hovering, bind }), [hovering, bind]);
|
return useMemo(() => ({ hovering, bind }), [hovering, bind]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function withHovering<T>(Component: React.ComponentType<T>) {
|
||||||
|
return React.forwardRef((props, ref) => {
|
||||||
|
const { hovering, bind } = useHovering();
|
||||||
|
return <Component ref={ref} hovering={hovering} bind={bind} {...props} />
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const DM_REGEX = /ship\/~([a-z]|-)*\/dm--/;
|
const DM_REGEX = /ship\/~([a-z]|-)*\/dm--/;
|
||||||
export function getItemTitle(association: Association) {
|
export function getItemTitle(association: Association): string {
|
||||||
if (DM_REGEX.test(association.resource)) {
|
if (DM_REGEX.test(association.resource)) {
|
||||||
const [, , ship, name] = association.resource.split('/');
|
const [, , ship, name] = association.resource.split('/');
|
||||||
if (ship.slice(1) === window.ship) {
|
if (ship.slice(1) === window.ship) {
|
||||||
@ -433,6 +439,6 @@ export function getItemTitle(association: Association) {
|
|||||||
}
|
}
|
||||||
return cite(ship);
|
return cite(ship);
|
||||||
}
|
}
|
||||||
return association.metadata.title || association.resource;
|
return association.metadata.title ?? association.resource ?? '';
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,10 @@
|
|||||||
import React, {
|
import React, {
|
||||||
useContext,
|
useCallback, useContext,
|
||||||
useState,
|
|
||||||
useCallback,
|
useEffect, useState
|
||||||
useLayoutEffect,
|
} from 'react';
|
||||||
useRef,
|
import { Primitive } from '~/types';
|
||||||
useEffect,
|
import usePreviousValue from './usePreviousValue';
|
||||||
} from "react";
|
|
||||||
import usePreviousValue from "./usePreviousValue";
|
|
||||||
import {Primitive} from "~/types";
|
|
||||||
|
|
||||||
export interface VirtualContextProps {
|
export interface VirtualContextProps {
|
||||||
save: () => void;
|
save: () => void;
|
||||||
@ -15,7 +12,7 @@ export interface VirtualContextProps {
|
|||||||
}
|
}
|
||||||
const fallback: VirtualContextProps = {
|
const fallback: VirtualContextProps = {
|
||||||
save: () => {},
|
save: () => {},
|
||||||
restore: () => {},
|
restore: () => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VirtualContext = React.createContext(fallback);
|
export const VirtualContext = React.createContext(fallback);
|
||||||
@ -27,7 +24,7 @@ export function useVirtual() {
|
|||||||
export const withVirtual = <P extends {}>(Component: React.ComponentType<P>) =>
|
export const withVirtual = <P extends {}>(Component: React.ComponentType<P>) =>
|
||||||
React.forwardRef((props: P, ref) => (
|
React.forwardRef((props: P, ref) => (
|
||||||
<VirtualContext.Consumer>
|
<VirtualContext.Consumer>
|
||||||
{(context) => <Component ref={ref} {...props} {...context} />}
|
{context => <Component ref={ref} {...props} {...context} />}
|
||||||
</VirtualContext.Consumer>
|
</VirtualContext.Consumer>
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -52,7 +49,7 @@ export function useVirtualResizeState(s: boolean) {
|
|||||||
|
|
||||||
export function useVirtualResizeProp(prop: Primitive) {
|
export function useVirtualResizeProp(prop: Primitive) {
|
||||||
const { save, restore } = useVirtual();
|
const { save, restore } = useVirtual();
|
||||||
const oldProp = usePreviousValue(prop)
|
const oldProp = usePreviousValue(prop);
|
||||||
|
|
||||||
if(prop !== oldProp) {
|
if(prop !== oldProp) {
|
||||||
save();
|
save();
|
||||||
@ -61,6 +58,4 @@ export function useVirtualResizeProp(prop: Primitive) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
requestAnimationFrame(restore);
|
requestAnimationFrame(restore);
|
||||||
}, [prop]);
|
}, [prop]);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import { ReactElement } from "react";
|
import { UseStore } from 'zustand';
|
||||||
import { UseStore } from "zustand";
|
import { BaseState } from '../state/base';
|
||||||
import { BaseState } from "../state/base";
|
|
||||||
|
|
||||||
const withStateo = <
|
const withStateo = <
|
||||||
StateType extends BaseState<any>
|
StateType extends BaseState<any>
|
||||||
@ -16,19 +15,21 @@ const withStateo = <
|
|||||||
(object, key) => ({ ...object, [key]: state[key] }), {}
|
(object, key) => ({ ...object, [key]: state[key] }), {}
|
||||||
)
|
)
|
||||||
) : useState();
|
) : useState();
|
||||||
return <Component ref={ref} {...state} {...props} />
|
return <Component ref={ref} {...state} {...props} />;
|
||||||
})
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const withState = <
|
interface StatePicker extends Array<any> {
|
||||||
StateType extends BaseState<StateType>,
|
0: UseStore<any>;
|
||||||
stateKey extends keyof StateType
|
1?: string[];
|
||||||
>(
|
}
|
||||||
|
|
||||||
|
const withState = (
|
||||||
Component: any,
|
Component: any,
|
||||||
stores: ([UseStore<StateType>, stateKey[]])[],
|
stores: StatePicker[]
|
||||||
) => {
|
) => {
|
||||||
return React.forwardRef((props, ref) => {
|
return React.forwardRef((props, ref) => {
|
||||||
let stateProps: unknown = {};
|
const stateProps: unknown = {};
|
||||||
stores.forEach(([store, keys]) => {
|
stores.forEach(([store, keys]) => {
|
||||||
const storeProps = Array.isArray(keys)
|
const storeProps = Array.isArray(keys)
|
||||||
? store(state => keys.reduce(
|
? store(state => keys.reduce(
|
||||||
@ -37,8 +38,8 @@ const withState = <
|
|||||||
: store();
|
: store();
|
||||||
Object.assign(stateProps, storeProps);
|
Object.assign(stateProps, storeProps);
|
||||||
});
|
});
|
||||||
return <Component ref={ref} {...stateProps} {...props} />
|
return <Component ref={ref} {...stateProps} {...props} />;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export default withState;
|
export default withState;
|
@ -18,10 +18,10 @@ export function getTitleFromWorkspace(
|
|||||||
|
|
||||||
export function getGroupFromWorkspace(
|
export function getGroupFromWorkspace(
|
||||||
workspace: Workspace
|
workspace: Workspace
|
||||||
): string | undefined {
|
): string {
|
||||||
if (workspace.type === 'group') {
|
if (workspace.type === 'group') {
|
||||||
return workspace.group;
|
return workspace.group;
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { StoreState } from '../store/type';
|
|
||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
|
import { StoreState } from '../store/type';
|
||||||
|
|
||||||
type LocalState = Pick<StoreState, 'connection'>;
|
type LocalState = Pick<StoreState, 'connection'>;
|
||||||
|
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
import _ from 'lodash';
|
|
||||||
import { compose } from 'lodash/fp';
|
|
||||||
|
|
||||||
import { ContactUpdate } from '@urbit/api';
|
import { ContactUpdate } from '@urbit/api';
|
||||||
|
import _ from 'lodash';
|
||||||
import useContactState, { ContactState } from '../state/contact';
|
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
|
import useContactState, { ContactState } from '../state/contact';
|
||||||
|
|
||||||
export const ContactReducer = (json) => {
|
export const ContactReducer = (json) => {
|
||||||
const data: ContactUpdate = _.get(json, 'contact-update', false);
|
const data: ContactUpdate = _.get(json, 'contact-update', false);
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import {StoreState} from '../store/type';
|
|
||||||
import type {GcpToken} from '../../types/gcp-state';
|
|
||||||
import type { Cage } from '~/types/cage';
|
import type { Cage } from '~/types/cage';
|
||||||
import useStorageState, { StorageState } from '../state/storage';
|
import type { GcpToken } from '../../types/gcp-state';
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
|
import useStorageState, { StorageState } from '../state/storage';
|
||||||
|
|
||||||
export default class GcpReducer {
|
export default class GcpReducer {
|
||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
@ -13,21 +12,21 @@ export default class GcpReducer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const reduceToken = (json: Cage, state: StorageState): StorageState => {
|
const reduceToken = (json: Cage, state: StorageState): StorageState => {
|
||||||
let data = json['gcp-token'];
|
const data = json['gcp-token'];
|
||||||
if (data) {
|
if (data) {
|
||||||
setToken(data, state);
|
setToken(data, state);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const setToken = (data: any, state: StorageState): StorageState => {
|
const setToken = (data: any, state: StorageState): StorageState => {
|
||||||
if (isToken(data)) {
|
if (isToken(data)) {
|
||||||
state.gcp.token = data;
|
state.gcp.token = data;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const isToken = (token: any): token is GcpToken => {
|
const isToken = (token: any): token is GcpToken => {
|
||||||
return (typeof(token.accessKey) === 'string' &&
|
return (typeof(token.accessKey) === 'string' &&
|
||||||
typeof(token.expiresIn) === 'number');
|
typeof(token.expiresIn) === 'number');
|
||||||
}
|
};
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import _ from 'lodash';
|
import { GraphNode } from '@urbit/api';
|
||||||
import BigIntOrderedMap from "@urbit/api/lib/BigIntOrderedMap";
|
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
||||||
|
import bigInt, { BigInteger } from 'big-integer';
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import bigInt, { BigInteger } from "big-integer";
|
import _ from 'lodash';
|
||||||
import useGraphState, { GraphState } from '../state/graph';
|
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
|
import useGraphState, { GraphState } from '../state/graph';
|
||||||
|
|
||||||
export const GraphReducer = (json) => {
|
export const GraphReducer = (json) => {
|
||||||
const data = _.get(json, 'graph-update', false);
|
const data = _.get(json, 'graph-update', false);
|
||||||
@ -36,13 +37,13 @@ const addNodesLoose = (json: any, state: GraphState): GraphState => {
|
|||||||
_.set(state.looseNodes, [resource], indices);
|
_.set(state.looseNodes, [resource], indices);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const keys = (json, state: GraphState): GraphState => {
|
const keys = (json, state: GraphState): GraphState => {
|
||||||
const data = _.get(json, 'keys', false);
|
const data = _.get(json, 'keys', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
state.graphKeys = new Set(data.map((res) => {
|
state.graphKeys = new Set(data.map((res) => {
|
||||||
let resource = res.ship + '/' + res.name;
|
const resource = res.ship + '/' + res.name;
|
||||||
return resource;
|
return resource;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -52,36 +53,32 @@ const keys = (json, state: GraphState): GraphState => {
|
|||||||
const processNode = (node) => {
|
const processNode = (node) => {
|
||||||
// is empty
|
// is empty
|
||||||
if (!node.children) {
|
if (!node.children) {
|
||||||
return produce(node, draft => {
|
return produce<GraphNode>(node, (draft: GraphNode) => {
|
||||||
draft.children = new BigIntOrderedMap();
|
draft.children = new BigIntOrderedMap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// is graph
|
// is graph
|
||||||
return produce(node, draft => {
|
return produce<GraphNode>(node, (draft: GraphNode) => {
|
||||||
draft.children = new BigIntOrderedMap()
|
draft.children = new BigIntOrderedMap<GraphNode>()
|
||||||
.gas(_.map(draft.children, (item, idx) =>
|
.gas(_.map(draft.children, (item, idx) =>
|
||||||
[bigInt(idx), processNode(item)] as [BigInteger, any]
|
[bigInt(idx), processNode(item)] as [BigInteger, any]
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const addGraph = (json, state: GraphState): GraphState => {
|
const addGraph = (json, state: GraphState): GraphState => {
|
||||||
|
|
||||||
|
|
||||||
const data = _.get(json, 'add-graph', false);
|
const data = _.get(json, 'add-graph', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
if (!('graphs' in state)) {
|
if (!('graphs' in state)) {
|
||||||
state.graphs = {};
|
state.graphs = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
let resource = data.resource.ship + '/' + data.resource.name;
|
const resource = data.resource.ship + '/' + data.resource.name;
|
||||||
state.graphs[resource] = new BigIntOrderedMap();
|
state.graphs[resource] = new BigIntOrderedMap();
|
||||||
state.graphTimesentMap[resource] = {};
|
state.graphTimesentMap[resource] = {};
|
||||||
|
|
||||||
|
state.graphs[resource] = state.graphs[resource].gas(Object.keys(data.graph).map((idx) => {
|
||||||
state.graphs[resource] = state.graphs[resource].gas(Object.keys(data.graph).map(idx => {
|
|
||||||
return [bigInt(idx), processNode(data.graph[idx])];
|
return [bigInt(idx), processNode(data.graph[idx])];
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -93,11 +90,10 @@ const addGraph = (json, state: GraphState): GraphState => {
|
|||||||
const removeGraph = (json, state: GraphState): GraphState => {
|
const removeGraph = (json, state: GraphState): GraphState => {
|
||||||
const data = _.get(json, 'remove-graph', false);
|
const data = _.get(json, 'remove-graph', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|
||||||
if (!('graphs' in state)) {
|
if (!('graphs' in state)) {
|
||||||
state.graphs = {};
|
state.graphs = {};
|
||||||
}
|
}
|
||||||
let resource = data.ship + '/' + data.name;
|
const resource = data.ship + '/' + data.name;
|
||||||
state.graphKeys.delete(resource);
|
state.graphKeys.delete(resource);
|
||||||
delete state.graphs[resource];
|
delete state.graphs[resource];
|
||||||
}
|
}
|
||||||
@ -121,12 +117,12 @@ const addNodes = (json, state) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set parent of graph
|
// set parent of graph
|
||||||
let parNode = graph.get(index[0]);
|
const parNode = graph.get(index[0]);
|
||||||
if (!parNode) {
|
if (!parNode) {
|
||||||
console.error('parent node does not exist, cannot add child');
|
console.error('parent node does not exist, cannot add child');
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
return graph.set(index[0], produce(parNode, draft => {
|
return graph.set(index[0], produce(parNode, (draft) => {
|
||||||
draft.children = _addNode(draft.children, index.slice(1), node);
|
draft.children = _addNode(draft.children, index.slice(1), node);
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@ -137,7 +133,7 @@ const addNodes = (json, state) => {
|
|||||||
} else {
|
} else {
|
||||||
const child = graph.get(index[0]);
|
const child = graph.get(index[0]);
|
||||||
if (child) {
|
if (child) {
|
||||||
return graph.set(index[0], produce(child, draft => {
|
return graph.set(index[0], produce(child, (draft) => {
|
||||||
draft.children = _remove(draft.children, index.slice(1));
|
draft.children = _remove(draft.children, index.slice(1));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -148,10 +144,12 @@ const addNodes = (json, state) => {
|
|||||||
|
|
||||||
const _killByFuzzyTimestamp = (graph, resource, timestamp) => {
|
const _killByFuzzyTimestamp = (graph, resource, timestamp) => {
|
||||||
if (state.graphTimesentMap[resource][timestamp]) {
|
if (state.graphTimesentMap[resource][timestamp]) {
|
||||||
let index = state.graphTimesentMap[resource][timestamp];
|
const index = state.graphTimesentMap[resource][timestamp];
|
||||||
|
|
||||||
if (index.split('/').length === 0) { return graph; }
|
if (index.split('/').length === 0) {
|
||||||
let indexArr = index.split('/').slice(1).map((ind) => {
|
return graph;
|
||||||
|
}
|
||||||
|
const indexArr = index.split('/').slice(1).map((ind) => {
|
||||||
return bigInt(ind);
|
return bigInt(ind);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -174,9 +172,11 @@ const addNodes = (json, state) => {
|
|||||||
|
|
||||||
const data = _.get(json, 'add-nodes', false);
|
const data = _.get(json, 'add-nodes', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
if (!('graphs' in state)) { return state; }
|
if (!('graphs' in state)) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
let resource = data.resource.ship + '/' + data.resource.name;
|
const resource = data.resource.ship + '/' + data.resource.name;
|
||||||
if (!(resource in state.graphs)) {
|
if (!(resource in state.graphs)) {
|
||||||
state.graphs[resource] = new BigIntOrderedMap();
|
state.graphs[resource] = new BigIntOrderedMap();
|
||||||
}
|
}
|
||||||
@ -187,47 +187,46 @@ const addNodes = (json, state) => {
|
|||||||
|
|
||||||
state.graphKeys.add(resource);
|
state.graphKeys.add(resource);
|
||||||
|
|
||||||
let indices = Array.from(Object.keys(data.nodes));
|
const indices = Array.from(Object.keys(data.nodes));
|
||||||
|
|
||||||
indices.sort((a, b) => {
|
indices.sort((a, b) => {
|
||||||
let aArr = a.split('/');
|
const aArr = a.split('/');
|
||||||
let bArr = b.split('/');
|
const bArr = b.split('/');
|
||||||
return aArr.length - bArr.length;
|
return aArr.length - bArr.length;
|
||||||
});
|
});
|
||||||
|
|
||||||
indices.forEach((index) => {
|
indices.forEach((index) => {
|
||||||
let node = data.nodes[index];
|
const node = data.nodes[index];
|
||||||
const old = state.graphs[resource].size;
|
const old = state.graphs[resource].size;
|
||||||
state.graphs[resource] = _removePending(state.graphs[resource], node.post, resource);
|
state.graphs[resource] = _removePending(state.graphs[resource], node.post, resource);
|
||||||
const newSize = state.graphs[resource].size;
|
const newSize = state.graphs[resource].size;
|
||||||
|
|
||||||
|
if (index.split('/').length === 0) {
|
||||||
if (index.split('/').length === 0) { return; }
|
return;
|
||||||
let indexArr = index.split('/').slice(1).map((ind) => {
|
}
|
||||||
|
const indexArr = index.split('/').slice(1).map((ind) => {
|
||||||
return bigInt(ind);
|
return bigInt(ind);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (indexArr.length === 0) { return state; }
|
if (indexArr.length === 0) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
if (node.post.pending) {
|
if (node.post.pending) {
|
||||||
state.graphTimesentMap[resource][node.post['time-sent']] = index;
|
state.graphTimesentMap[resource][node.post['time-sent']] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
state.graphs[resource] = _addNode(
|
state.graphs[resource] = _addNode(
|
||||||
state.graphs[resource],
|
state.graphs[resource],
|
||||||
indexArr,
|
indexArr,
|
||||||
produce(node, draft => {
|
produce(node, (draft) => {
|
||||||
draft.children = mapifyChildren(draft?.children || {});
|
draft.children = mapifyChildren(draft?.children || {});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
if(newSize !== old) {
|
if(newSize !== old) {
|
||||||
console.log(`${resource}, (${old}, ${newSize}, ${state.graphs[resource].size})`);
|
console.log(`${resource}, (${old}, ${newSize}, ${state.graphs[resource].size})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
@ -249,8 +248,8 @@ const removePosts = (json, state: GraphState): GraphState => {
|
|||||||
} else {
|
} else {
|
||||||
const child = graph.get(index[0]);
|
const child = graph.get(index[0]);
|
||||||
if (child) {
|
if (child) {
|
||||||
return graph.set(index[0], produce(draft => {
|
return graph.set(index[0], produce((draft) => {
|
||||||
draft.children = _remove(draft.children, index.slice(1))
|
draft.children = _remove(draft.children, index.slice(1));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return graph;
|
return graph;
|
||||||
@ -262,11 +261,15 @@ const removePosts = (json, state: GraphState): GraphState => {
|
|||||||
if (data) {
|
if (data) {
|
||||||
const { ship, name } = data.resource;
|
const { ship, name } = data.resource;
|
||||||
const res = `${ship}/${name}`;
|
const res = `${ship}/${name}`;
|
||||||
if (!(res in state.graphs)) { return state; }
|
if (!(res in state.graphs)) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
data.indices.forEach((index) => {
|
data.indices.forEach((index) => {
|
||||||
if (index.split('/').length === 0) { return; }
|
if (index.split('/').length === 0) {
|
||||||
let indexArr = index.split('/').slice(1).map((ind) => {
|
return;
|
||||||
|
}
|
||||||
|
const indexArr = index.split('/').slice(1).map((ind) => {
|
||||||
return bigInt(ind);
|
return bigInt(ind);
|
||||||
});
|
});
|
||||||
state.graphs[res] = _remove(state.graphs[res], indexArr);
|
state.graphs[res] = _remove(state.graphs[res], indexArr);
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
|
import { Enc } from '@urbit/api';
|
||||||
|
import {
|
||||||
|
Group,
|
||||||
|
|
||||||
|
GroupPolicy, GroupUpdate,
|
||||||
|
|
||||||
|
InvitePolicy, InvitePolicyDiff, OpenPolicy, OpenPolicyDiff, Tags
|
||||||
|
} from '@urbit/api/groups';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
import {
|
|
||||||
GroupUpdate,
|
|
||||||
Group,
|
|
||||||
Tags,
|
|
||||||
GroupPolicy,
|
|
||||||
OpenPolicyDiff,
|
|
||||||
OpenPolicy,
|
|
||||||
InvitePolicyDiff,
|
|
||||||
InvitePolicy
|
|
||||||
} from '@urbit/api/groups';
|
|
||||||
import { Enc } from '@urbit/api';
|
|
||||||
import { resourceAsPath } from '../lib/util';
|
import { resourceAsPath } from '../lib/util';
|
||||||
import useGroupState, { GroupState } from '../state/group';
|
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
|
import useGroupState, { GroupState } from '../state/group';
|
||||||
|
|
||||||
function decodeGroup(group: Enc<Group>): Group {
|
function decodeGroup(group: Enc<Group>): Group {
|
||||||
const members = new Set(group.members);
|
const members = new Set(group.members);
|
||||||
@ -41,7 +38,7 @@ function decodePolicy(policy: Enc<GroupPolicy>): GroupPolicy {
|
|||||||
function decodeTags(tags: Enc<Tags>): Tags {
|
function decodeTags(tags: Enc<Tags>): Tags {
|
||||||
return _.reduce(
|
return _.reduce(
|
||||||
tags,
|
tags,
|
||||||
(acc, ships, key): Tags => {
|
(acc, ships: any, key): Tags => {
|
||||||
if (key.search(/\\/) === -1) {
|
if (key.search(/\\/) === -1) {
|
||||||
acc.role[key] = new Set(ships);
|
acc.role[key] = new Set(ships);
|
||||||
return acc;
|
return acc;
|
||||||
@ -69,11 +66,10 @@ export default class GroupReducer {
|
|||||||
addGroup,
|
addGroup,
|
||||||
removeGroup,
|
removeGroup,
|
||||||
changePolicy,
|
changePolicy,
|
||||||
expose,
|
expose
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
const initial = (json: GroupUpdate, state: GroupState): GroupState => {
|
const initial = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
const data = json['initial'];
|
const data = json['initial'];
|
||||||
@ -81,7 +77,7 @@ const initial = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
state.groups = _.mapValues(data, decodeGroup);
|
state.groups = _.mapValues(data, decodeGroup);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const initialGroup = (json: GroupUpdate, state: GroupState): GroupState => {
|
const initialGroup = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
if ('initialGroup' in json) {
|
if ('initialGroup' in json) {
|
||||||
@ -90,7 +86,7 @@ const initialGroup = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
state.groups[path] = decodeGroup(group);
|
state.groups[path] = decodeGroup(group);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const addGroup = (json: GroupUpdate, state: GroupState): GroupState => {
|
const addGroup = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
if ('addGroup' in json) {
|
if ('addGroup' in json) {
|
||||||
@ -104,7 +100,7 @@ const addGroup = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const removeGroup = (json: GroupUpdate, state: GroupState): GroupState => {
|
const removeGroup = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
if('removeGroup' in json) {
|
if('removeGroup' in json) {
|
||||||
@ -113,7 +109,7 @@ const removeGroup = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
delete state.groups[resourcePath];
|
delete state.groups[resourcePath];
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const addMembers = (json: GroupUpdate, state: GroupState): GroupState => {
|
const addMembers = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
if ('addMembers' in json) {
|
if ('addMembers' in json) {
|
||||||
@ -130,7 +126,7 @@ const addMembers = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const removeMembers = (json: GroupUpdate, state: GroupState): GroupState => {
|
const removeMembers = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
if ('removeMembers' in json) {
|
if ('removeMembers' in json) {
|
||||||
@ -141,7 +137,7 @@ const removeMembers = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const addTag = (json: GroupUpdate, state: GroupState): GroupState => {
|
const addTag = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
if ('addTag' in json) {
|
if ('addTag' in json) {
|
||||||
@ -177,7 +173,7 @@ const removeTag = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
_.set(tags, tagAccessors, tagged);
|
_.set(tags, tagAccessors, tagged);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const changePolicy = (json: GroupUpdate, state: GroupState): GroupState => {
|
const changePolicy = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
if ('changePolicy' in json && state) {
|
if ('changePolicy' in json && state) {
|
||||||
@ -195,7 +191,7 @@ const changePolicy = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const expose = (json: GroupUpdate, state: GroupState): GroupState => {
|
const expose = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
if( 'expose' in json && state) {
|
if( 'expose' in json && state) {
|
||||||
@ -204,7 +200,7 @@ const expose = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
state.groups[resourcePath].hidden = false;
|
state.groups[resourcePath].hidden = false;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const inviteChangePolicy = (diff: InvitePolicyDiff, policy: InvitePolicy) => {
|
const inviteChangePolicy = (diff: InvitePolicyDiff, policy: InvitePolicy) => {
|
||||||
if ('addInvites' in diff) {
|
if ('addInvites' in diff) {
|
||||||
@ -220,7 +216,7 @@ const inviteChangePolicy = (diff: InvitePolicyDiff, policy: InvitePolicy) => {
|
|||||||
} else {
|
} else {
|
||||||
console.log('bad policy change');
|
console.log('bad policy change');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const openChangePolicy = (diff: OpenPolicyDiff, policy: OpenPolicy) => {
|
const openChangePolicy = (diff: OpenPolicyDiff, policy: OpenPolicy) => {
|
||||||
if ('allowRanks' in diff) {
|
if ('allowRanks' in diff) {
|
||||||
@ -246,4 +242,4 @@ const openChangePolicy = (diff: OpenPolicyDiff, policy: OpenPolicy) => {
|
|||||||
} else {
|
} else {
|
||||||
console.log('bad policy change');
|
console.log('bad policy change');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { GroupUpdate } from '@urbit/api/groups';
|
import { GroupUpdate } from '@urbit/api/groups';
|
||||||
import { resourceAsPath } from '~/logic/lib/util';
|
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
import useGroupState, { GroupState } from '../state/group';
|
import useGroupState, { GroupState } from '../state/group';
|
||||||
|
|
||||||
@ -18,7 +17,7 @@ const started = (json: any, state: GroupState): GroupState => {
|
|||||||
state.pendingJoin[resource] = request;
|
state.pendingJoin[resource] = request;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const progress = (json: any, state: GroupState): GroupState => {
|
const progress = (json: any, state: GroupState): GroupState => {
|
||||||
const data = json.progress;
|
const data = json.progress;
|
||||||
@ -26,7 +25,6 @@ const progress = (json: any, state: GroupState): GroupState => {
|
|||||||
const { progress, resource } = data;
|
const { progress, resource } = data;
|
||||||
state.pendingJoin[resource].progress = progress;
|
state.pendingJoin[resource].progress = progress;
|
||||||
if(progress === 'done') {
|
if(progress === 'done') {
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
delete state.pendingJoin[resource];
|
delete state.pendingJoin[resource];
|
||||||
}, 10000);
|
}, 10000);
|
||||||
@ -41,8 +39,7 @@ const hide = (json: any, state: GroupState) => {
|
|||||||
state.pendingJoin[data].hidden = true;
|
state.pendingJoin[data].hidden = true;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export const GroupViewReducer = (json: any) => {
|
export const GroupViewReducer = (json: any) => {
|
||||||
const data = json['group-view-update'];
|
const data = json['group-view-update'];
|
||||||
|
@ -2,13 +2,13 @@ import {
|
|||||||
NotifIndex,
|
NotifIndex,
|
||||||
Timebox
|
Timebox
|
||||||
} from '@urbit/api';
|
} from '@urbit/api';
|
||||||
import { makePatDa } from '~/logic/lib/util';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
||||||
import useHarkState, { HarkState } from '../state/hark';
|
|
||||||
import { compose } from 'lodash/fp';
|
|
||||||
import { reduceState } from '../state/base';
|
|
||||||
import { BigInteger } from 'big-integer';
|
import { BigInteger } from 'big-integer';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { compose } from 'lodash/fp';
|
||||||
|
import { makePatDa } from '~/logic/lib/util';
|
||||||
|
import { reduceState } from '../state/base';
|
||||||
|
import useHarkState, { HarkState } from '../state/hark';
|
||||||
|
|
||||||
export const HarkReducer = (json: any) => {
|
export const HarkReducer = (json: any) => {
|
||||||
const data = _.get(json, 'harkUpdate', false);
|
const data = _.get(json, 'harkUpdate', false);
|
||||||
@ -22,7 +22,7 @@ export const HarkReducer = (json: any) => {
|
|||||||
graphIgnore,
|
graphIgnore,
|
||||||
graphListen,
|
graphListen,
|
||||||
graphWatchSelf,
|
graphWatchSelf,
|
||||||
graphMentions,
|
graphMentions
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
const groupHookData = _.get(json, 'hark-group-hook-update', false);
|
const groupHookData = _.get(json, 'hark-group-hook-update', false);
|
||||||
@ -30,7 +30,7 @@ export const HarkReducer = (json: any) => {
|
|||||||
reduceState<HarkState, any>(useHarkState, groupHookData, [
|
reduceState<HarkState, any>(useHarkState, groupHookData, [
|
||||||
groupInitial,
|
groupInitial,
|
||||||
groupListen,
|
groupListen,
|
||||||
groupIgnore,
|
groupIgnore
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -52,9 +52,9 @@ function reduce(data, state) {
|
|||||||
unreadEach,
|
unreadEach,
|
||||||
seenIndex,
|
seenIndex,
|
||||||
removeGraph,
|
removeGraph,
|
||||||
readAll,
|
readAll
|
||||||
];
|
];
|
||||||
const reducer = compose(reducers.map(r => s => {
|
const reducer = compose(reducers.map(r => (s) => {
|
||||||
return r(data, s);
|
return r(data, s);
|
||||||
}));
|
}));
|
||||||
return reducer(state);
|
return reducer(state);
|
||||||
@ -63,13 +63,21 @@ function reduce(data, state) {
|
|||||||
function calculateCount(json: any, state: HarkState) {
|
function calculateCount(json: any, state: HarkState) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
_.forEach(state.unreads.graph, (graphs) => {
|
_.forEach(state.unreads.graph, (graphs) => {
|
||||||
_.forEach(graphs, graph => {
|
_.forEach(graphs, (graph) => {
|
||||||
count += (graph?.notifications || []).length;
|
if (typeof graph?.notifications === 'object') {
|
||||||
|
count += graph?.notifications.length;
|
||||||
|
} else {
|
||||||
|
count += 0;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
_.forEach(state.unreads.group, group => {
|
_.forEach(state.unreads.group, (group) => {
|
||||||
count += (group?.notifications || []).length;
|
if (typeof group?.notifications === 'object') {
|
||||||
})
|
count += group?.notifications.length;
|
||||||
|
} else {
|
||||||
|
count += 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
state.notificationsCount = count;
|
state.notificationsCount = count;
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -260,7 +268,7 @@ function updateUnreads(state: HarkState, index: NotifIndex, f: (us: Set<string>)
|
|||||||
if(!('graph' in index)) {
|
if(!('graph' in index)) {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
let unreads: any = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], new Set<string>());
|
const unreads: any = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], new Set<string>());
|
||||||
f(unreads);
|
f(unreads);
|
||||||
|
|
||||||
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], unreads);
|
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], unreads);
|
||||||
@ -294,19 +302,18 @@ function removeNotificationFromUnread(state: HarkState, index: NotifIndex, time:
|
|||||||
const path = [index.graph.graph, index.graph.index, 'notifications'];
|
const path = [index.graph.graph, index.graph.index, 'notifications'];
|
||||||
const curr = _.get(state.unreads.graph, path, []);
|
const curr = _.get(state.unreads.graph, path, []);
|
||||||
_.set(state.unreads.graph, path,
|
_.set(state.unreads.graph, path,
|
||||||
curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index))),
|
curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index)))
|
||||||
);
|
);
|
||||||
} else if ('group' in index) {
|
} else if ('group' in index) {
|
||||||
const path = [index.group.group, 'notifications'];
|
const path = [index.group.group, 'notifications'];
|
||||||
const curr = _.get(state.unreads.group, path, []);
|
const curr = _.get(state.unreads.group, path, []);
|
||||||
_.set(state.unreads.group, path,
|
_.set(state.unreads.group, path,
|
||||||
curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index))),
|
curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateNotificationStats(state: HarkState, index: NotifIndex, statField: 'unreads' | 'last', f: (x: number) => number) {
|
function updateNotificationStats(state: HarkState, index: NotifIndex, statField: 'unreads' | 'last', f: (x: number) => number) {
|
||||||
|
|
||||||
if('graph' in index) {
|
if('graph' in index) {
|
||||||
const curr: any = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, statField], 0);
|
const curr: any = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, statField], 0);
|
||||||
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, statField], f(curr));
|
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, statField], f(curr));
|
||||||
@ -359,7 +366,7 @@ const timebox = (json: any, state: HarkState): HarkState => {
|
|||||||
function more(json: any, state: HarkState): HarkState {
|
function more(json: any, state: HarkState): HarkState {
|
||||||
const data = _.get(json, 'more', false);
|
const data = _.get(json, 'more', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
_.forEach(data, d => {
|
_.forEach(data, (d) => {
|
||||||
reduce(d, state);
|
reduce(d, state);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -431,7 +438,7 @@ function archive(json: any, state: HarkState): HarkState {
|
|||||||
const data = _.get(json, 'archive', false);
|
const data = _.get(json, 'archive', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
const { index } = data;
|
const { index } = data;
|
||||||
removeNotificationFromUnread(state, index, makePatDa(data.time))
|
removeNotificationFromUnread(state, index, makePatDa(data.time));
|
||||||
const time = makePatDa(data.time);
|
const time = makePatDa(data.time);
|
||||||
const timebox = state.notifications.get(time);
|
const timebox = state.notifications.get(time);
|
||||||
if (!timebox) {
|
if (!timebox) {
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import _ from 'lodash';
|
|
||||||
import { compose } from 'lodash/fp';
|
|
||||||
|
|
||||||
import { InviteUpdate } from '@urbit/api/invite';
|
import { InviteUpdate } from '@urbit/api/invite';
|
||||||
|
import _ from 'lodash';
|
||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
import useInviteState, { InviteState } from '../state/invite';
|
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
|
import useInviteState, { InviteState } from '../state/invite';
|
||||||
|
|
||||||
export default class InviteReducer {
|
export default class InviteReducer {
|
||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
@ -17,7 +14,7 @@ export default class InviteReducer {
|
|||||||
deleteInvite,
|
deleteInvite,
|
||||||
invite,
|
invite,
|
||||||
accepted,
|
accepted,
|
||||||
decline,
|
decline
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,7 +26,7 @@ const initial = (json: InviteUpdate, state: InviteState): InviteState => {
|
|||||||
state.invites = data;
|
state.invites = data;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const create = (json: InviteUpdate, state: InviteState): InviteState => {
|
const create = (json: InviteUpdate, state: InviteState): InviteState => {
|
||||||
const data = _.get(json, 'create', false);
|
const data = _.get(json, 'create', false);
|
||||||
@ -37,7 +34,7 @@ const create = (json: InviteUpdate, state: InviteState): InviteState => {
|
|||||||
state.invites[data] = {};
|
state.invites[data] = {};
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const deleteInvite = (json: InviteUpdate, state: InviteState): InviteState => {
|
const deleteInvite = (json: InviteUpdate, state: InviteState): InviteState => {
|
||||||
const data = _.get(json, 'delete', false);
|
const data = _.get(json, 'delete', false);
|
||||||
@ -45,7 +42,7 @@ const deleteInvite = (json: InviteUpdate, state: InviteState): InviteState => {
|
|||||||
delete state.invites[data];
|
delete state.invites[data];
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const invite = (json: InviteUpdate, state: InviteState): InviteState => {
|
const invite = (json: InviteUpdate, state: InviteState): InviteState => {
|
||||||
const data = _.get(json, 'invite', false);
|
const data = _.get(json, 'invite', false);
|
||||||
@ -53,7 +50,7 @@ const invite = (json: InviteUpdate, state: InviteState): InviteState => {
|
|||||||
state.invites[data.term][data.uid] = data.invite;
|
state.invites[data.term][data.uid] = data.invite;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const accepted = (json: InviteUpdate, state: InviteState): InviteState => {
|
const accepted = (json: InviteUpdate, state: InviteState): InviteState => {
|
||||||
const data = _.get(json, 'accepted', false);
|
const data = _.get(json, 'accepted', false);
|
||||||
@ -61,7 +58,7 @@ const accepted = (json: InviteUpdate, state: InviteState): InviteState => {
|
|||||||
delete state.invites[data.term][data.uid];
|
delete state.invites[data.term][data.uid];
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const decline = (json: InviteUpdate, state: InviteState): InviteState => {
|
const decline = (json: InviteUpdate, state: InviteState): InviteState => {
|
||||||
const data = _.get(json, 'decline', false);
|
const data = _.get(json, 'decline', false);
|
||||||
@ -69,4 +66,4 @@ const decline = (json: InviteUpdate, state: InviteState): InviteState => {
|
|||||||
delete state.invites[data.term][data.uid];
|
delete state.invites[data.term][data.uid];
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { LaunchUpdate, WeatherState } from '~/types/launch-update';
|
|
||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
import useLaunchState, { LaunchState } from '../state/launch';
|
import { LaunchUpdate, WeatherState } from '~/types/launch-update';
|
||||||
import { compose } from 'lodash/fp';
|
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
|
import useLaunchState, { LaunchState } from '../state/launch';
|
||||||
|
|
||||||
export default class LaunchReducer {
|
export default class LaunchReducer {
|
||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
@ -14,29 +13,36 @@ export default class LaunchReducer {
|
|||||||
changeFirstTime,
|
changeFirstTime,
|
||||||
changeOrder,
|
changeOrder,
|
||||||
changeFirstTime,
|
changeFirstTime,
|
||||||
changeIsShown,
|
changeIsShown
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const weatherData: WeatherState | boolean | Record<string, never> = _.get(json, 'weather', false);
|
const weatherData: WeatherState | boolean | Record<string, never> = _.get(json, 'weather', false);
|
||||||
if (weatherData) {
|
if (weatherData) {
|
||||||
useLaunchState.getState().set(state => {
|
useLaunchState.getState().set((state) => {
|
||||||
state.weather = weatherData;
|
state.weather = weatherData;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const locationData = _.get(json, 'location', false);
|
const locationData = _.get(json, 'location', false);
|
||||||
if (locationData) {
|
if (locationData) {
|
||||||
useLaunchState.getState().set(state => {
|
useLaunchState.getState().set((state) => {
|
||||||
state.userLocation = locationData;
|
state.userLocation = locationData;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseHash = _.get(json, 'baseHash', false);
|
const baseHash = _.get(json, 'baseHash', false);
|
||||||
if (baseHash) {
|
if (baseHash) {
|
||||||
useLaunchState.getState().set(state => {
|
useLaunchState.getState().set((state) => {
|
||||||
state.baseHash = baseHash;
|
state.baseHash = baseHash;
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const runtimeLag = _.get(json, 'runtimeLag', null);
|
||||||
|
if (runtimeLag !== null) {
|
||||||
|
useLaunchState.getState().set(state => {
|
||||||
|
state.runtimeLag = runtimeLag;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,12 +50,12 @@ export default class LaunchReducer {
|
|||||||
export const initial = (json: LaunchUpdate, state: LaunchState): LaunchState => {
|
export const initial = (json: LaunchUpdate, state: LaunchState): LaunchState => {
|
||||||
const data = _.get(json, 'initial', false);
|
const data = _.get(json, 'initial', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
Object.keys(data).forEach(key => {
|
Object.keys(data).forEach((key) => {
|
||||||
state[key] = data[key];
|
state[key] = data[key];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const changeFirstTime = (json: LaunchUpdate, state: LaunchState): LaunchState => {
|
export const changeFirstTime = (json: LaunchUpdate, state: LaunchState): LaunchState => {
|
||||||
const data = _.get(json, 'changeFirstTime', false);
|
const data = _.get(json, 'changeFirstTime', false);
|
||||||
@ -57,7 +63,7 @@ export const changeFirstTime = (json: LaunchUpdate, state: LaunchState): LaunchS
|
|||||||
state.firstTime = data;
|
state.firstTime = data;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const changeOrder = (json: LaunchUpdate, state: LaunchState): LaunchState => {
|
export const changeOrder = (json: LaunchUpdate, state: LaunchState): LaunchState => {
|
||||||
const data = _.get(json, 'changeOrder', false);
|
const data = _.get(json, 'changeOrder', false);
|
||||||
@ -65,7 +71,7 @@ export const changeOrder = (json: LaunchUpdate, state: LaunchState): LaunchState
|
|||||||
state.tileOrdering = data;
|
state.tileOrdering = data;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const changeIsShown = (json: LaunchUpdate, state: LaunchState): LaunchState => {
|
export const changeIsShown = (json: LaunchUpdate, state: LaunchState): LaunchState => {
|
||||||
const data = _.get(json, 'changeIsShown', false);
|
const data = _.get(json, 'changeIsShown', false);
|
||||||
@ -76,4 +82,4 @@ export const changeIsShown = (json: LaunchUpdate, state: LaunchState): LaunchSta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import _ from 'lodash';
|
|
||||||
import { compose } from 'lodash/fp';
|
|
||||||
|
|
||||||
import { MetadataUpdate } from '@urbit/api/metadata';
|
import { MetadataUpdate } from '@urbit/api/metadata';
|
||||||
|
import _ from 'lodash';
|
||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
import useMetadataState, { MetadataState } from '../state/metadata';
|
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
|
import useMetadataState, { MetadataState } from '../state/metadata';
|
||||||
|
|
||||||
export default class MetadataReducer {
|
export default class MetadataReducer {
|
||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
@ -16,7 +13,7 @@ export default class MetadataReducer {
|
|||||||
add,
|
add,
|
||||||
update,
|
update,
|
||||||
remove,
|
remove,
|
||||||
groupInitial,
|
groupInitial
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,7 +25,7 @@ const groupInitial = (json: MetadataUpdate, state: MetadataState): MetadataState
|
|||||||
associations(data, state);
|
associations(data, state);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const associations = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
const associations = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
||||||
const data = _.get(json, 'associations', false);
|
const data = _.get(json, 'associations', false);
|
||||||
@ -50,7 +47,7 @@ const associations = (json: MetadataUpdate, state: MetadataState): MetadataState
|
|||||||
state.associations = metadata;
|
state.associations = metadata;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const add = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
const add = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
||||||
const data = _.get(json, 'add', false);
|
const data = _.get(json, 'add', false);
|
||||||
@ -70,7 +67,7 @@ const add = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
|||||||
state.associations = metadata;
|
state.associations = metadata;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const update = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
const update = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
||||||
const data = _.get(json, 'update-metadata', false);
|
const data = _.get(json, 'update-metadata', false);
|
||||||
@ -90,7 +87,7 @@ const update = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
|||||||
state.associations = metadata;
|
state.associations = metadata;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const remove = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
const remove = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
||||||
const data = _.get(json, 'remove', false);
|
const data = _.get(json, 'remove', false);
|
||||||
@ -105,4 +102,4 @@ const remove = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
|||||||
state.associations = metadata;
|
state.associations = metadata;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { compose } from 'lodash/fp';
|
|
||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
import { S3Update } from '~/types/s3-update';
|
import { S3Update } from '~/types/s3-update';
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
import useStorageState, { StorageState } from '../state/storage';
|
import useStorageState, { StorageState } from '../state/storage';
|
||||||
|
|
||||||
|
|
||||||
export default class S3Reducer {
|
export default class S3Reducer {
|
||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
const data = _.get(json, 's3-update', false);
|
const data = _.get(json, 's3-update', false);
|
||||||
@ -18,7 +16,7 @@ export default class S3Reducer {
|
|||||||
removeBucket,
|
removeBucket,
|
||||||
endpoint,
|
endpoint,
|
||||||
accessKeyId,
|
accessKeyId,
|
||||||
secretAccessKey,
|
secretAccessKey
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,7 +28,7 @@ const credentials = (json: S3Update, state: StorageState): StorageState => {
|
|||||||
state.s3.credentials = data;
|
state.s3.credentials = data;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const configuration = (json: S3Update, state: StorageState): StorageState => {
|
const configuration = (json: S3Update, state: StorageState): StorageState => {
|
||||||
const data = _.get(json, 'configuration', false);
|
const data = _.get(json, 'configuration', false);
|
||||||
@ -41,7 +39,7 @@ const configuration = (json: S3Update, state: StorageState): StorageState => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const currentBucket = (json: S3Update, state: StorageState): StorageState => {
|
const currentBucket = (json: S3Update, state: StorageState): StorageState => {
|
||||||
const data = _.get(json, 'setCurrentBucket', false);
|
const data = _.get(json, 'setCurrentBucket', false);
|
||||||
@ -49,7 +47,7 @@ const currentBucket = (json: S3Update, state: StorageState): StorageState => {
|
|||||||
state.s3.configuration.currentBucket = data;
|
state.s3.configuration.currentBucket = data;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const addBucket = (json: S3Update, state: StorageState): StorageState => {
|
const addBucket = (json: S3Update, state: StorageState): StorageState => {
|
||||||
const data = _.get(json, 'addBucket', false);
|
const data = _.get(json, 'addBucket', false);
|
||||||
@ -58,7 +56,7 @@ const addBucket = (json: S3Update, state: StorageState): StorageState => {
|
|||||||
state.s3.configuration.buckets.add(data);
|
state.s3.configuration.buckets.add(data);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const removeBucket = (json: S3Update, state: StorageState): StorageState => {
|
const removeBucket = (json: S3Update, state: StorageState): StorageState => {
|
||||||
const data = _.get(json, 'removeBucket', false);
|
const data = _.get(json, 'removeBucket', false);
|
||||||
@ -66,7 +64,7 @@ const removeBucket = (json: S3Update, state: StorageState): StorageState => {
|
|||||||
state.s3.configuration.buckets.delete(data);
|
state.s3.configuration.buckets.delete(data);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const endpoint = (json: S3Update, state: StorageState): StorageState => {
|
const endpoint = (json: S3Update, state: StorageState): StorageState => {
|
||||||
const data = _.get(json, 'setEndpoint', false);
|
const data = _.get(json, 'setEndpoint', false);
|
||||||
@ -74,7 +72,7 @@ const endpoint = (json: S3Update, state: StorageState): StorageState => {
|
|||||||
state.s3.credentials.endpoint = data;
|
state.s3.credentials.endpoint = data;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const accessKeyId = (json: S3Update , state: StorageState): StorageState => {
|
const accessKeyId = (json: S3Update , state: StorageState): StorageState => {
|
||||||
const data = _.get(json, 'setAccessKeyId', false);
|
const data = _.get(json, 'setAccessKeyId', false);
|
||||||
@ -82,7 +80,7 @@ const accessKeyId = (json: S3Update , state: StorageState): StorageState => {
|
|||||||
state.s3.credentials.accessKeyId = data;
|
state.s3.credentials.accessKeyId = data;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
const secretAccessKey = (json: S3Update, state: StorageState): StorageState => {
|
const secretAccessKey = (json: S3Update, state: StorageState): StorageState => {
|
||||||
const data = _.get(json, 'setSecretAccessKey', false);
|
const data = _.get(json, 'setSecretAccessKey', false);
|
||||||
@ -90,4 +88,4 @@ const secretAccessKey = (json: S3Update, state: StorageState): StorageState => {
|
|||||||
state.s3.credentials.secretAccessKey = data;
|
state.s3.credentials.secretAccessKey = data;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
@ -1,26 +1,25 @@
|
|||||||
|
import { SettingsUpdate } from '@urbit/api/settings';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import useSettingsState, { SettingsState } from '~/logic/state/settings';
|
import useSettingsState, { SettingsState } from '~/logic/state/settings';
|
||||||
import { SettingsUpdate } from '@urbit/api/settings';
|
|
||||||
import { reduceState } from '../state/base';
|
import { reduceState } from '../state/base';
|
||||||
import { string } from 'prop-types';
|
|
||||||
|
|
||||||
export default class SettingsReducer {
|
export default class SettingsReducer {
|
||||||
reduce(json: any) {
|
reduce(json: any) {
|
||||||
let data = json["settings-event"];
|
let data = json['settings-event'];
|
||||||
if (data) {
|
if (data) {
|
||||||
reduceState<SettingsState, SettingsUpdate>(useSettingsState, data, [
|
reduceState<SettingsState, SettingsUpdate>(useSettingsState, data, [
|
||||||
this.putBucket,
|
this.putBucket,
|
||||||
this.delBucket,
|
this.delBucket,
|
||||||
this.putEntry,
|
this.putEntry,
|
||||||
this.delEntry,
|
this.delEntry
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
data = json["settings-data"];
|
data = json['settings-data'];
|
||||||
if (data) {
|
if (data) {
|
||||||
reduceState<SettingsState, SettingsUpdate>(useSettingsState, data, [
|
reduceState<SettingsState, SettingsUpdate>(useSettingsState, data, [
|
||||||
this.getAll,
|
this.getAll,
|
||||||
this.getBucket,
|
this.getBucket,
|
||||||
this.getEntry,
|
this.getEntry
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,7 +27,7 @@ export default class SettingsReducer {
|
|||||||
putBucket(json: SettingsUpdate, state: SettingsState): SettingsState {
|
putBucket(json: SettingsUpdate, state: SettingsState): SettingsState {
|
||||||
const data = _.get(json, 'put-bucket', false);
|
const data = _.get(json, 'put-bucket', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
state[data["bucket-key"]] = data.bucket;
|
state[data['bucket-key']] = data.bucket;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -63,7 +62,7 @@ export default class SettingsReducer {
|
|||||||
getAll(json: any, state: SettingsState): SettingsState {
|
getAll(json: any, state: SettingsState): SettingsState {
|
||||||
const data = _.get(json, 'all');
|
const data = _.get(json, 'all');
|
||||||
if(data) {
|
if(data) {
|
||||||
_.mergeWith(state, data, (obj, src) => _.isArray(src) ? src : undefined)
|
_.mergeWith(state, data, (obj, src) => _.isArray(src) ? src : undefined);
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import produce, { setAutoFreeze } from "immer";
|
import produce, { setAutoFreeze } from 'immer';
|
||||||
import { compose } from "lodash/fp";
|
import { compose } from 'lodash/fp';
|
||||||
import create, { State, UseStore } from "zustand";
|
import create, { State, UseStore } from 'zustand';
|
||||||
import { persist, devtools } from "zustand/middleware";
|
import { persist } from 'zustand/middleware';
|
||||||
|
|
||||||
setAutoFreeze(false);
|
setAutoFreeze(false);
|
||||||
|
|
||||||
|
|
||||||
export const stateSetter = <StateType>(
|
export const stateSetter = <StateType>(
|
||||||
fn: (state: StateType) => void,
|
fn: (state: StateType) => void,
|
||||||
set
|
set
|
||||||
@ -22,7 +21,7 @@ export const reduceState = <
|
|||||||
reducers: ((data: UpdateType, state: StateType) => StateType)[]
|
reducers: ((data: UpdateType, state: StateType) => StateType)[]
|
||||||
): void => {
|
): void => {
|
||||||
const reducer = compose(reducers.map(r => sta => r(data, sta)));
|
const reducer = compose(reducers.map(r => sta => r(data, sta)));
|
||||||
state.getState().set(state => {
|
state.getState().set((state) => {
|
||||||
reducer(state);
|
reducer(state);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -36,25 +35,24 @@ export const stateStorageKey = (stateName: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
(window as any).clearStates = () => {
|
(window as any).clearStates = () => {
|
||||||
stateStorageKeys.forEach(key => {
|
stateStorageKeys.forEach((key) => {
|
||||||
localStorage.removeItem(key);
|
localStorage.removeItem(key);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface BaseState<StateType> extends State {
|
export interface BaseState<StateType> extends State {
|
||||||
set: (fn: (state: StateType) => void) => void;
|
set: (fn: (state: StateType) => void) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createState = <StateType extends BaseState<any>>(
|
export const createState = <T extends BaseState<T>>(
|
||||||
name: string,
|
name: string,
|
||||||
properties: Omit<StateType, 'set'>,
|
properties: { [K in keyof Omit<T, 'set'>]: T[K] },
|
||||||
blacklist: string[] = []
|
blacklist: string[] = []
|
||||||
): UseStore<StateType> => create(persist((set, get) => ({
|
): UseStore<T> => create(persist((set, get) => ({
|
||||||
// TODO why does this typing break?
|
|
||||||
set: fn => stateSetter(fn, set),
|
set: fn => stateSetter(fn, set),
|
||||||
...properties
|
...properties as any
|
||||||
}), {
|
}), {
|
||||||
blacklist,
|
blacklist,
|
||||||
name: stateStorageKey(name),
|
name: stateStorageKey(name),
|
||||||
version: process.env.LANDSCAPE_SHORTHASH
|
version: process.env.LANDSCAPE_SHORTHASH as any
|
||||||
}));
|
}));
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Patp, Rolodex, Scry, Contact } from "@urbit/api";
|
import { Contact, Patp, Rolodex } from '@urbit/api';
|
||||||
|
import { useCallback } from 'react';
|
||||||
import { BaseState, createState } from "./base";
|
import { BaseState, createState } from './base';
|
||||||
import {useCallback} from "react";
|
|
||||||
|
|
||||||
export interface ContactState extends BaseState<ContactState> {
|
export interface ContactState extends BaseState<ContactState> {
|
||||||
contacts: Rolodex;
|
contacts: Rolodex;
|
||||||
@ -13,7 +12,7 @@ export interface ContactState extends BaseState<ContactState> {
|
|||||||
const useContactState = createState<ContactState>('Contact', {
|
const useContactState = createState<ContactState>('Contact', {
|
||||||
contacts: {},
|
contacts: {},
|
||||||
nackedContacts: new Set(),
|
nackedContacts: new Set(),
|
||||||
isContactPublic: false,
|
isContactPublic: false
|
||||||
// fetchIsAllowed: async (
|
// fetchIsAllowed: async (
|
||||||
// entity,
|
// entity,
|
||||||
// name,
|
// name,
|
||||||
@ -36,7 +35,7 @@ export function useContact(ship: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useOurContact() {
|
export function useOurContact() {
|
||||||
return useContact(`~${window.ship}`)
|
return useContact(`~${window.ship}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useContactState;
|
export default useContactState;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Graphs, decToUd, numToUd, GraphNode, deSig, Association, resourceFromPath } from "@urbit/api";
|
import { Association, deSig, GraphNode, Graphs, resourceFromPath } from '@urbit/api';
|
||||||
import {useCallback} from "react";
|
import { useCallback } from 'react';
|
||||||
|
import { BaseState, createState } from './base';
|
||||||
import { BaseState, createState } from "./base";
|
|
||||||
|
|
||||||
export interface GraphState extends BaseState<GraphState> {
|
export interface GraphState extends BaseState<GraphState> {
|
||||||
graphs: Graphs;
|
graphs: Graphs;
|
||||||
@ -22,14 +21,14 @@ export interface GraphState extends BaseState<GraphState> {
|
|||||||
// getYoungerSiblings: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
|
// getYoungerSiblings: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
|
||||||
// getGraphSubset: (ship: string, resource: string, start: string, end: string) => Promise<void>;
|
// getGraphSubset: (ship: string, resource: string, start: string, end: string) => Promise<void>;
|
||||||
// getNode: (ship: string, resource: string, index: string) => Promise<void>;
|
// getNode: (ship: string, resource: string, index: string) => Promise<void>;
|
||||||
};
|
}
|
||||||
|
|
||||||
const useGraphState = createState<GraphState>('Graph', {
|
const useGraphState = createState<GraphState>('Graph', {
|
||||||
graphs: {},
|
graphs: {},
|
||||||
graphKeys: new Set(),
|
graphKeys: new Set(),
|
||||||
looseNodes: {},
|
looseNodes: {},
|
||||||
pendingIndices: {},
|
pendingIndices: {},
|
||||||
graphTimesentMap: {},
|
graphTimesentMap: {}
|
||||||
// getKeys: async () => {
|
// getKeys: async () => {
|
||||||
// const api = useApi();
|
// const api = useApi();
|
||||||
// const keys = await api.scry({
|
// const keys = await api.scry({
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
import { Path, JoinRequests, Association, Group } from "@urbit/api";
|
import { Association, Group, JoinRequests } from '@urbit/api';
|
||||||
|
import { useCallback } from 'react';
|
||||||
import { BaseState, createState } from "./base";
|
import { BaseState, createState } from './base';
|
||||||
import {useCallback} from "react";
|
|
||||||
|
|
||||||
export interface GroupState extends BaseState<GroupState> {
|
export interface GroupState extends BaseState<GroupState> {
|
||||||
groups: {
|
groups: {
|
||||||
[group: string]: Group;
|
[group: string]: Group;
|
||||||
}
|
}
|
||||||
pendingJoin: JoinRequests;
|
pendingJoin: JoinRequests;
|
||||||
};
|
}
|
||||||
|
|
||||||
const useGroupState = createState<GroupState>('Group', {
|
const useGroupState = createState<GroupState>('Group', {
|
||||||
groups: {},
|
groups: {},
|
||||||
pendingJoin: {},
|
pendingJoin: {}
|
||||||
}, ['groups']);
|
}, ['groups']);
|
||||||
|
|
||||||
export function useGroup(group: string) {
|
export function useGroup(group: string) {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { NotificationGraphConfig, Timebox, Unreads, dateToDa } from "@urbit/api";
|
import { NotificationGraphConfig, Timebox, Unreads } from '@urbit/api';
|
||||||
import BigIntOrderedMap from "@urbit/api/lib/BigIntOrderedMap";
|
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
||||||
|
|
||||||
// import { harkGraphHookReducer, harkGroupHookReducer, harkReducer } from "~/logic/subscription/hark";
|
// import { harkGraphHookReducer, harkGroupHookReducer, harkReducer } from "~/logic/subscription/hark";
|
||||||
import { BaseState, createState } from "./base";
|
import { BaseState, createState } from './base';
|
||||||
|
|
||||||
export const HARK_FETCH_MORE_COUNT = 3;
|
export const HARK_FETCH_MORE_COUNT = 3;
|
||||||
|
|
||||||
@ -17,7 +16,7 @@ export interface HarkState extends BaseState<HarkState> {
|
|||||||
notificationsGraphConfig: NotificationGraphConfig; // TODO unthread this everywhere
|
notificationsGraphConfig: NotificationGraphConfig; // TODO unthread this everywhere
|
||||||
notificationsGroupConfig: string[];
|
notificationsGroupConfig: string[];
|
||||||
unreads: Unreads;
|
unreads: Unreads;
|
||||||
};
|
}
|
||||||
|
|
||||||
const useHarkState = createState<HarkState>('Hark', {
|
const useHarkState = createState<HarkState>('Hark', {
|
||||||
archivedNotifications: new BigIntOrderedMap<Timebox>(),
|
archivedNotifications: new BigIntOrderedMap<Timebox>(),
|
||||||
@ -62,8 +61,7 @@ const useHarkState = createState<HarkState>('Hark', {
|
|||||||
unreads: {
|
unreads: {
|
||||||
graph: {},
|
graph: {},
|
||||||
group: {}
|
group: {}
|
||||||
},
|
}
|
||||||
}, ['notifications', 'archivedNotifications', 'unreads', 'notificationsCount']);
|
}, ['notifications', 'archivedNotifications', 'unreads', 'notificationsCount']);
|
||||||
|
|
||||||
|
|
||||||
export default useHarkState;
|
export default useHarkState;
|
||||||
|
@ -3,10 +3,10 @@ import { BaseState, createState } from './base';
|
|||||||
|
|
||||||
export interface InviteState extends BaseState<InviteState> {
|
export interface InviteState extends BaseState<InviteState> {
|
||||||
invites: Invites;
|
invites: Invites;
|
||||||
};
|
}
|
||||||
|
|
||||||
const useInviteState = createState<InviteState>('Invite', {
|
const useInviteState = createState<InviteState>('Invite', {
|
||||||
invites: {},
|
invites: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default useInviteState;
|
export default useInviteState;
|
@ -1,7 +1,5 @@
|
|||||||
import { Tile, WeatherState } from "~/types/launch-update";
|
import { Tile, WeatherState } from '~/types/launch-update';
|
||||||
|
import { BaseState, createState } from './base';
|
||||||
import { BaseState, createState } from "./base";
|
|
||||||
|
|
||||||
|
|
||||||
export interface LaunchState extends BaseState<LaunchState> {
|
export interface LaunchState extends BaseState<LaunchState> {
|
||||||
firstTime: boolean;
|
firstTime: boolean;
|
||||||
@ -12,6 +10,7 @@ export interface LaunchState extends BaseState<LaunchState> {
|
|||||||
weather: WeatherState | null | Record<string, never> | boolean,
|
weather: WeatherState | null | Record<string, never> | boolean,
|
||||||
userLocation: string | null;
|
userLocation: string | null;
|
||||||
baseHash: string | null;
|
baseHash: string | null;
|
||||||
|
runtimeLag: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useLaunchState = createState<LaunchState>('Launch', {
|
const useLaunchState = createState<LaunchState>('Launch', {
|
||||||
@ -20,8 +19,8 @@ const useLaunchState = createState<LaunchState>('Launch', {
|
|||||||
tiles: {},
|
tiles: {},
|
||||||
weather: null,
|
weather: null,
|
||||||
userLocation: null,
|
userLocation: null,
|
||||||
baseHash: null
|
baseHash: null,
|
||||||
|
runtimeLag: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export default useLaunchState;
|
export default useLaunchState;
|
@ -1,13 +1,12 @@
|
|||||||
import React, { ReactNode } from 'react';
|
import produce from 'immer';
|
||||||
import f from 'lodash/fp';
|
import f from 'lodash/fp';
|
||||||
|
import React from 'react';
|
||||||
import create, { State } from 'zustand';
|
import create, { State } from 'zustand';
|
||||||
import { persist } from 'zustand/middleware';
|
import { persist } from 'zustand/middleware';
|
||||||
import produce from 'immer';
|
import { BackgroundConfig, LeapCategories, RemoteContentPolicy, TutorialProgress, tutorialProgress } from '~/types/local-update';
|
||||||
import { BackgroundConfig, RemoteContentPolicy, TutorialProgress, tutorialProgress, LeapCategories } from "~/types/local-update";
|
|
||||||
|
|
||||||
|
|
||||||
export interface LocalState {
|
export interface LocalState {
|
||||||
theme: "light" | "dark" | "auto";
|
theme: 'light' | 'dark' | 'auto';
|
||||||
hideAvatars: boolean;
|
hideAvatars: boolean;
|
||||||
hideNicknames: boolean;
|
hideNicknames: boolean;
|
||||||
remoteContentPolicy: RemoteContentPolicy;
|
remoteContentPolicy: RemoteContentPolicy;
|
||||||
@ -21,12 +20,13 @@ export interface LocalState {
|
|||||||
hideLeapCats: LeapCategories[];
|
hideLeapCats: LeapCategories[];
|
||||||
setTutorialRef: (el: HTMLElement | null) => void;
|
setTutorialRef: (el: HTMLElement | null) => void;
|
||||||
dark: boolean;
|
dark: boolean;
|
||||||
|
mobile: boolean;
|
||||||
background: BackgroundConfig;
|
background: BackgroundConfig;
|
||||||
omniboxShown: boolean;
|
omniboxShown: boolean;
|
||||||
suspendedFocus?: HTMLElement;
|
suspendedFocus?: HTMLElement;
|
||||||
toggleOmnibox: () => void;
|
toggleOmnibox: () => void;
|
||||||
set: (fn: (state: LocalState) => void) => void
|
set: (fn: (state: LocalState) => void) => void
|
||||||
};
|
}
|
||||||
|
|
||||||
type LocalStateZus = LocalState & State;
|
type LocalStateZus = LocalState & State;
|
||||||
|
|
||||||
@ -35,8 +35,9 @@ export const selectLocalState =
|
|||||||
|
|
||||||
const useLocalState = create<LocalStateZus>(persist((set, get) => ({
|
const useLocalState = create<LocalStateZus>(persist((set, get) => ({
|
||||||
dark: false,
|
dark: false,
|
||||||
|
mobile: false,
|
||||||
background: undefined,
|
background: undefined,
|
||||||
theme: "auto",
|
theme: 'auto',
|
||||||
hideAvatars: false,
|
hideAvatars: false,
|
||||||
hideNicknames: false,
|
hideNicknames: false,
|
||||||
hideLeapCats: [],
|
hideLeapCats: [],
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user