mirror of
https://github.com/tloncorp/landscape.git
synced 2024-12-01 02:45:49 +03:00
Merge pull request #16 from urbit/t/merge-agent-clay
grid: migrate upstream changes for compatibility with 417 clay + kiln
This commit is contained in:
commit
d882b0dce0
@ -3,7 +3,7 @@
|
|||||||
|%
|
|%
|
||||||
+$ card card:agent:gall
|
+$ card card:agent:gall
|
||||||
+$ app-state
|
+$ app-state
|
||||||
$: %2
|
$: %3
|
||||||
:: local
|
:: local
|
||||||
charges=(map desk charge)
|
charges=(map desk charge)
|
||||||
==
|
==
|
||||||
@ -42,7 +42,7 @@
|
|||||||
++ on-init
|
++ on-init
|
||||||
^- (quip card _this)
|
^- (quip card _this)
|
||||||
:_ this
|
:_ this
|
||||||
:~ (~(watch-our pass /kiln) %hood /kiln/vats)
|
:~ ~(tire pass /tire)
|
||||||
(~(connect pass /eyre) [~ /] %docket)
|
(~(connect pass /eyre) [~ /] %docket)
|
||||||
(~(wait pass /init) (add 1 now.bowl))
|
(~(wait pass /init) (add 1 now.bowl))
|
||||||
(~(connect pass /eyre) [~ /apps] %docket)
|
(~(connect pass /eyre) [~ /apps] %docket)
|
||||||
@ -54,20 +54,21 @@
|
|||||||
|^
|
|^
|
||||||
=+ !<(old=app-states vase)
|
=+ !<(old=app-states vase)
|
||||||
=? old ?=(?(~ ^) -.old) [%1 old]
|
=? old ?=(?(~ ^) -.old) [%1 old]
|
||||||
=^ cards old
|
=^ cards-1 old
|
||||||
?. ?=(%1 -.old) `old
|
?. ?=(%1 -.old) `old
|
||||||
=/ rein=cage kiln-rein+!>([%base %.y ~ ~])
|
`old(- %2)
|
||||||
=/ nuke=cage kiln-uninstall+!>(%hodl)
|
=^ cards-2 old
|
||||||
:_ old(- %2)
|
?. ?=(%2 -.old) `old
|
||||||
:~ [%pass /rein %agent [our.bowl %hood] %poke rein]
|
:_ old(- %3) :_ ~
|
||||||
[%pass /nuke %agent [our.bowl %hood] %poke nuke]
|
~(tire pass /tire)
|
||||||
==
|
?> ?=(%3 -.old)
|
||||||
?> ?=(%2 -.old)
|
=/ cards-tire [~(tire pass /tire) ~]
|
||||||
=. -.state old
|
=. -.state old
|
||||||
:: inflate-cache needs to be called after the state is set
|
:: inflate-cache needs to be called after the state is set
|
||||||
::
|
::
|
||||||
=. +.state inflate-cache
|
=. +.state inflate-cache
|
||||||
[cards this]
|
[:(weld cards-1 cards-2 cards-tire) this]
|
||||||
|
|
||||||
::
|
::
|
||||||
++ inflate-cache
|
++ inflate-cache
|
||||||
^- cache
|
^- cache
|
||||||
@ -81,9 +82,11 @@
|
|||||||
$^ state-0-ket
|
$^ state-0-ket
|
||||||
$% state-0-sig
|
$% state-0-sig
|
||||||
state-1
|
state-1
|
||||||
|
state-2
|
||||||
app-state
|
app-state
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
|
+$ state-2 [%2 (map desk charge)]
|
||||||
+$ state-1 [%1 (map desk charge)]
|
+$ state-1 [%1 (map desk charge)]
|
||||||
+$ state-0-sig
|
+$ state-0-sig
|
||||||
$: ~
|
$: ~
|
||||||
@ -94,6 +97,7 @@
|
|||||||
==
|
==
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
|
|
||||||
++ on-save !>(-.state)
|
++ on-save !>(-.state)
|
||||||
++ on-poke
|
++ on-poke
|
||||||
|= [=mark =vase]
|
|= [=mark =vase]
|
||||||
@ -189,13 +193,21 @@
|
|||||||
==
|
==
|
||||||
::
|
::
|
||||||
[%x %charges ~]
|
[%x %charges ~]
|
||||||
|
=/ tyr
|
||||||
|
.^(rock:tire:clay %cx /(scot %p our.bowl)//(scot %da now.bowl)/tire)
|
||||||
:- ~ :- ~
|
:- ~ :- ~
|
||||||
%- charge-update:cg
|
%- charge-update:cg
|
||||||
:- %initial
|
:- %initial
|
||||||
%- ~(gas by *(map desk charge))
|
%- ~(gas by *(map desk charge))
|
||||||
%+ turn ~(tap by charges)
|
%+ murn ~(tap by charges)
|
||||||
|= [=desk =charge]
|
|= [=desk =charge]
|
||||||
[desk (get-light-charge charge)]
|
?~ got=(~(get by tyr) desk)
|
||||||
|
~
|
||||||
|
?: ?& ?=(%dead zest.u.got)
|
||||||
|
?=(~ (get-apps-have:hood our.bowl desk now.bowl))
|
||||||
|
==
|
||||||
|
~
|
||||||
|
`u=[desk (get-light-charge charge)]
|
||||||
::
|
::
|
||||||
[%x %charges @ %version ~]
|
[%x %charges @ %version ~]
|
||||||
?~ charge=(~(get by charges) i.t.t.path)
|
?~ charge=(~(get by charges) i.t.t.path)
|
||||||
@ -212,114 +224,11 @@
|
|||||||
~ `state
|
~ `state
|
||||||
[%rein ~] ~&(%reined `state)
|
[%rein ~] ~&(%reined `state)
|
||||||
[%nuke ~] ~&(%nuked `state)
|
[%nuke ~] ~&(%nuked `state)
|
||||||
[%kiln ~] take-kiln
|
[%kiln ~] `state
|
||||||
[%charge @ *] (take-charge i.t.wire t.t.wire)
|
[%charge @ *] (take-charge i.t.wire t.t.wire)
|
||||||
==
|
==
|
||||||
[cards this]
|
[cards this]
|
||||||
::
|
::
|
||||||
++ take-kiln
|
|
||||||
^- (quip card _state)
|
|
||||||
?+ -.sign (on-agent:def:cc wire sign)
|
|
||||||
%kick [(~(watch-our pass /kiln) %hood /kiln/vats)^~ state]
|
|
||||||
%fact
|
|
||||||
|^ ^- (quip card _state)
|
|
||||||
?+ p.cage.sign ~|(take-kiln-mark/p.cage.sign !!)
|
|
||||||
%kiln-vats-snap-0 (on-snap !<(snap:hood q.cage.sign))
|
|
||||||
%kiln-vats-diff-0 (on-diff !<(diff:hood q.cage.sign))
|
|
||||||
==
|
|
||||||
::
|
|
||||||
++ on-snap
|
|
||||||
|= =snap:hood
|
|
||||||
^- (quip card _state)
|
|
||||||
=| fex=(list card)
|
|
||||||
=/ ark ~(tap by snap)
|
|
||||||
|- ^- (quip card _state)
|
|
||||||
?~ ark [(flop fex) state]
|
|
||||||
=^ caz state (on-commit i.ark)
|
|
||||||
$(ark t.ark, fex (weld (flop caz) fex))
|
|
||||||
::
|
|
||||||
++ on-diff
|
|
||||||
|= =diff:hood
|
|
||||||
=+ !<(=diff:hood q.cage.sign)
|
|
||||||
?- -.diff
|
|
||||||
%commit (on-commit [desk arak]:diff)
|
|
||||||
%suspend (on-suspend [desk arak]:diff)
|
|
||||||
%revive (on-revive [desk arak]:diff)
|
|
||||||
?(%block %reset %merge-sunk %merge-fail)
|
|
||||||
`state
|
|
||||||
==
|
|
||||||
::
|
|
||||||
++ on-commit
|
|
||||||
|= [=desk =arak:hood]
|
|
||||||
^- (quip card _state)
|
|
||||||
=* cha ~(. ch desk)
|
|
||||||
?. docket-exists:cha
|
|
||||||
~? ?& !=(%base desk)
|
|
||||||
!=(%kids desk)
|
|
||||||
==
|
|
||||||
[dap.bowl %no-docket-file-for desk]
|
|
||||||
`state
|
|
||||||
:: always update the docket in state to match clay's
|
|
||||||
::
|
|
||||||
=/ =docket docket:cha
|
|
||||||
=/ pre=(unit charge) (~(get by charges) desk)
|
|
||||||
=. charges (new-docket:cha docket)
|
|
||||||
:: if the new chad is a site, we're instantly done
|
|
||||||
::
|
|
||||||
?: ?=(%site -.href.docket)
|
|
||||||
=. charges (new-chad:cha %site ~)
|
|
||||||
:- ~[add-fact:cha]
|
|
||||||
state
|
|
||||||
::
|
|
||||||
=. by-base (~(put by by-base) base.href.docket desk)
|
|
||||||
:: if the glob specification is unchanged, keep it
|
|
||||||
::
|
|
||||||
?: &(?=(^ pre) =(href.docket.u.pre href.docket) ?=(%glob -.chad.u.pre))
|
|
||||||
[~[add-fact:cha] state]
|
|
||||||
:: if the glob spec changed, but we already host it, keep it
|
|
||||||
:: (this is the "just locally uploaded" case)
|
|
||||||
::
|
|
||||||
?: ?& ?=(^ pre)
|
|
||||||
?=(%glob -.chad.u.pre)
|
|
||||||
::
|
|
||||||
.= [(sham glob.chad.u.pre) %ames our.bowl]
|
|
||||||
glob-reference.href.docket
|
|
||||||
==
|
|
||||||
[~[add-fact:cha] state]
|
|
||||||
:: if the glob changed, forget the old and fetch the new
|
|
||||||
::
|
|
||||||
=. charges (new-chad:cha %install ~)
|
|
||||||
[[add-fact:cha fetch-glob:cha] state]
|
|
||||||
::
|
|
||||||
++ on-suspend
|
|
||||||
|= [=desk =arak:hood]
|
|
||||||
^- (quip card _state)
|
|
||||||
=* cha ~(. ch desk)
|
|
||||||
?. (~(has by charges) desk) `state
|
|
||||||
=/ glob=(unit glob)
|
|
||||||
=/ =chad
|
|
||||||
chad:(~(got by charges) desk)
|
|
||||||
?:(?=(%glob -.chad) `glob.chad ~)
|
|
||||||
=. charges (new-chad:cha %suspend glob)
|
|
||||||
:_(state ~[add-fact:cha])
|
|
||||||
::
|
|
||||||
++ on-revive
|
|
||||||
|= [=desk =arak:hood]
|
|
||||||
^- (quip card _state)
|
|
||||||
=* cha ~(. ch desk)
|
|
||||||
?. (~(has by charges) desk) `state
|
|
||||||
=/ =charge (~(got by charges) desk)
|
|
||||||
?. ?=(%glob -.href.docket.charge)
|
|
||||||
=. charges (new-chad:cha %site ~)
|
|
||||||
:_(state ~[add-fact:cha])
|
|
||||||
=. charges
|
|
||||||
%- new-chad:cha
|
|
||||||
?. ?=([%suspend ~ *] chad.charge)
|
|
||||||
[%install ~]
|
|
||||||
[%glob u.glob.chad.charge]
|
|
||||||
:_(state [add-fact fetch-glob]:cha)
|
|
||||||
--
|
|
||||||
==
|
|
||||||
++ take-charge
|
++ take-charge
|
||||||
|= [=desk =^wire]
|
|= [=desk =^wire]
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
@ -398,6 +307,7 @@
|
|||||||
::
|
::
|
||||||
++ on-arvo
|
++ on-arvo
|
||||||
|= [=wire sign=sign-arvo]
|
|= [=wire sign=sign-arvo]
|
||||||
|
|^
|
||||||
=^ cards state
|
=^ cards state
|
||||||
?+ wire (on-arvo:def wire sign)
|
?+ wire (on-arvo:def wire sign)
|
||||||
[%init ~]
|
[%init ~]
|
||||||
@ -410,8 +320,114 @@
|
|||||||
?: accepted.sign `state
|
?: accepted.sign `state
|
||||||
~& [dap.bowl %failed-to-bind path.binding.sign]
|
~& [dap.bowl %failed-to-bind path.binding.sign]
|
||||||
`state
|
`state
|
||||||
|
::
|
||||||
|
[%tire ~]
|
||||||
|
?> ?=([%clay %tire *] sign)
|
||||||
|
?- -.p.sign
|
||||||
|
%& (on-rock p.p.sign)
|
||||||
|
%| (on-wave p.p.sign)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
[%warp * ~]
|
||||||
|
?> ?=(%writ +<.sign)
|
||||||
|
(on-writ i.t.wire p.sign)
|
||||||
==
|
==
|
||||||
[cards this]
|
[cards this]
|
||||||
|
::
|
||||||
|
++ on-rock
|
||||||
|
|= tyr=rock:tire:clay
|
||||||
|
^- (quip card _state)
|
||||||
|
=| fex=(list card)
|
||||||
|
=/ ark ~(tap by tyr)
|
||||||
|
|- ^- (quip card _state)
|
||||||
|
?~ ark [(flop fex) state]
|
||||||
|
=^ caz state (on-zest [p zest.q]:i.ark)
|
||||||
|
$(ark t.ark, fex (weld (flop caz) fex))
|
||||||
|
::
|
||||||
|
++ on-wave
|
||||||
|
|= =wave:tire:clay
|
||||||
|
^- (quip card _state)
|
||||||
|
?- -.wave
|
||||||
|
%wait `state
|
||||||
|
%warp `state
|
||||||
|
%zest (on-zest +.wave)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ on-zest
|
||||||
|
|= [=desk =zest:clay]
|
||||||
|
^- (quip card _state)
|
||||||
|
=* cha ~(. ch desk)
|
||||||
|
=/ card-1
|
||||||
|
(~(warp-our pass /warp/[desk]) desk ~ %sing %z da+now.bowl /desk/docket-0)
|
||||||
|
=^ cards-2 state
|
||||||
|
?. (~(has by charges) desk)
|
||||||
|
`state
|
||||||
|
=/ =charge (~(got by charges) desk)
|
||||||
|
?- zest
|
||||||
|
%live
|
||||||
|
?. ?=(%glob -.href.docket.charge)
|
||||||
|
=. charges (new-chad:cha %site ~)
|
||||||
|
:_(state ~[add-fact:cha])
|
||||||
|
:_(state ~[add-fact:cha])
|
||||||
|
::
|
||||||
|
?(%held %dead)
|
||||||
|
=/ glob=(unit glob)
|
||||||
|
?:(?=(%glob -.chad.charge) `glob.chad.charge ~)
|
||||||
|
=. charges (new-chad:cha %suspend glob)
|
||||||
|
:_(state ~[add-fact:cha])
|
||||||
|
==
|
||||||
|
[[card-1 cards-2] state]
|
||||||
|
::
|
||||||
|
++ on-writ
|
||||||
|
|= [=desk =riot:clay]
|
||||||
|
^- (quip card _state)
|
||||||
|
=/ card-1
|
||||||
|
(~(warp-our pass /warp/[desk]) desk ~ %next %z da+now.bowl /desk/docket-0)
|
||||||
|
=^ cards-2 state
|
||||||
|
=* cha ~(. ch desk)
|
||||||
|
=/ tyr
|
||||||
|
.^(rock:tire:clay %cx /(scot %p our.bowl)//(scot %da now.bowl)/tire)
|
||||||
|
?. =(%live zest:(~(got by tyr) desk))
|
||||||
|
`state
|
||||||
|
?. docket-exists:cha
|
||||||
|
:: ~? ?& !=(%base desk)
|
||||||
|
:: !=(%kids desk)
|
||||||
|
:: ==
|
||||||
|
:: [dap.bowl %no-docket-file-for desk]
|
||||||
|
`state
|
||||||
|
:: always update the docket in state to match clay's
|
||||||
|
::
|
||||||
|
=/ =docket docket:cha
|
||||||
|
=/ pre=(unit charge) (~(get by charges) desk)
|
||||||
|
=. charges (new-docket:cha docket)
|
||||||
|
:: if the new chad is a site, we're instantly done
|
||||||
|
::
|
||||||
|
?: ?=(%site -.href.docket)
|
||||||
|
=. charges (new-chad:cha %site ~)
|
||||||
|
:- ~[add-fact:cha]
|
||||||
|
state
|
||||||
|
::
|
||||||
|
=. by-base (~(put by by-base) base.href.docket desk)
|
||||||
|
:: if the glob specification is unchanged, keep it
|
||||||
|
::
|
||||||
|
?: &(?=(^ pre) =(href.docket.u.pre href.docket) ?=(%glob -.chad.u.pre))
|
||||||
|
[~[add-fact:cha] state]
|
||||||
|
:: if the glob spec changed, but we already host it, keep it
|
||||||
|
:: (this is the "just locally uploaded" case)
|
||||||
|
::
|
||||||
|
?: ?& ?=(^ pre)
|
||||||
|
?=(%glob -.chad.u.pre)
|
||||||
|
::
|
||||||
|
.= [(sham glob.chad.u.pre) %ames our.bowl]
|
||||||
|
glob-reference.href.docket
|
||||||
|
==
|
||||||
|
[~[add-fact:cha] state]
|
||||||
|
:: if the glob changed, forget the old and fetch the new
|
||||||
|
::
|
||||||
|
=. charges (new-chad:cha %install ~)
|
||||||
|
[[add-fact:cha fetch-glob:cha] state]
|
||||||
|
[[card-1 cards-2] state]
|
||||||
|
--
|
||||||
::
|
::
|
||||||
++ on-fail on-fail:def
|
++ on-fail on-fail:def
|
||||||
++ on-leave on-leave:def
|
++ on-leave on-leave:def
|
||||||
@ -728,4 +744,3 @@
|
|||||||
++ docket .^(^docket %cx (scry:io desk docket-loc))
|
++ docket .^(^docket %cx (scry:io desk docket-loc))
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
|
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
/+ verb, dbug, default-agent, agentio
|
/+ verb, dbug, default-agent, agentio
|
||||||
|%
|
|%
|
||||||
+$ card card:agent:gall
|
+$ card card:agent:gall
|
||||||
+$ state-0 [%0 lagging=_|]
|
+$ state-1 [%1 lagging=_|]
|
||||||
::
|
::
|
||||||
++ lag-interval ~m10
|
++ lag-interval ~m10
|
||||||
--
|
--
|
||||||
%+ verb |
|
%+ verb |
|
||||||
%- agent:dbug
|
%- agent:dbug
|
||||||
^- agent:gall
|
^- agent:gall
|
||||||
=| state-0
|
=| state-1
|
||||||
=* state -
|
=* state -
|
||||||
=<
|
=<
|
||||||
|_ =bowl:gall
|
|_ =bowl:gall
|
||||||
+* this .
|
+* this .
|
||||||
def ~(. (default-agent this %|) bowl)
|
def ~(. (default-agent this %|) bowl)
|
||||||
@ -21,12 +21,23 @@
|
|||||||
++ on-init
|
++ on-init
|
||||||
^- (quip card _this)
|
^- (quip card _this)
|
||||||
:_ this
|
:_ this
|
||||||
[onboard watch:kiln check:lag ~]:cc
|
[onboard tire:cy check:lag ~]:cc
|
||||||
::
|
::
|
||||||
++ on-load
|
++ on-load
|
||||||
|= =vase
|
|= =vase
|
||||||
=+ !<(old=state-0 vase)
|
^- (quip card _this)
|
||||||
`this(state old)
|
|^
|
||||||
|
=+ !<(old=app-states vase)
|
||||||
|
=^ cards-1 old
|
||||||
|
?. ?=(%0 -.old) `old
|
||||||
|
[[tire:cy:cc]~ old(- %1)]
|
||||||
|
?> ?=(%1 -.old)
|
||||||
|
=/ cards-tire [tire:cy:cc ~]
|
||||||
|
[(weld cards-1 cards-tire) this(state old)]
|
||||||
|
::
|
||||||
|
+$ app-states $%(state-0 state-1)
|
||||||
|
+$ state-0 [%0 lagging=_|]
|
||||||
|
--
|
||||||
::
|
::
|
||||||
++ on-save !>(state)
|
++ on-save !>(state)
|
||||||
++ on-poke on-poke:def
|
++ on-poke on-poke:def
|
||||||
@ -34,45 +45,57 @@
|
|||||||
++ on-watch on-watch:def
|
++ on-watch on-watch:def
|
||||||
++ on-agent
|
++ on-agent
|
||||||
|= [=wire =sign:agent:gall]
|
|= [=wire =sign:agent:gall]
|
||||||
|^
|
^- (quip card _this)
|
||||||
?+ wire (on-agent:def wire sign)
|
?+ wire (on-agent:def wire sign)
|
||||||
[%kiln %vats ~] take-kiln-vats
|
[%kiln %vats ~] `this
|
||||||
==
|
==
|
||||||
++ take-kiln-vats
|
::
|
||||||
?- -.sign
|
++ on-arvo
|
||||||
?(%poke-ack %watch-ack) (on-agent:def wire sign)
|
|= [=wire sign=sign-arvo]
|
||||||
%kick :_(this (drop safe-watch:kiln:cc))
|
^- (quip card _this)
|
||||||
::
|
|^
|
||||||
%fact
|
?+ wire (on-arvo:def wire sign)
|
||||||
?. ?=(%kiln-vats-diff-0 p.cage.sign) `this
|
[%clay %tire ~] take-clay-tire
|
||||||
=+ !<(=diff:hood q.cage.sign)
|
[%clay %warp * ~] (take-clay-warp i.t.t.wire)
|
||||||
?+ -.diff `this
|
[%check-lag ~] take-check-lag
|
||||||
::
|
==
|
||||||
%commit
|
::
|
||||||
?. |(=(desk.diff %base) ~(has-docket de:cc desk.diff)) `this
|
++ take-check-lag
|
||||||
=/ =action:hark ~(commit de:cc desk.diff)
|
^- (quip card _this)
|
||||||
|
?> ?=([%behn %wake *] sign)
|
||||||
|
=+ .^(lag=? %$ (scry:io %$ /zen/lag))
|
||||||
|
?: =(lagging lag) :_(this ~[check:lag:cc])
|
||||||
|
:_ this(lagging lag)
|
||||||
|
:_ ~[check:lag:cc]
|
||||||
|
?:(lagging start:lag:cc stop:lag:cc)
|
||||||
|
::
|
||||||
|
++ take-clay-tire
|
||||||
|
^- (quip card _this)
|
||||||
|
?> ?=(%tire +<.sign)
|
||||||
|
?- -.p.sign
|
||||||
|
%& [(turn ~(tap in ~(key by p.p.sign)) warp:cy:cc) this]
|
||||||
|
%|
|
||||||
|
?- -.p.p.sign
|
||||||
|
%zest `this
|
||||||
|
%warp `this
|
||||||
|
%wait
|
||||||
|
=/ =action:hark (~(blocked de:cc desk.p.p.sign) weft.p.p.sign)
|
||||||
:_ this
|
:_ this
|
||||||
~[(poke:ha:cc action)]
|
~[(poke:ha:cc action)]
|
||||||
::
|
|
||||||
%block
|
|
||||||
=/ =action:hark (~(blocked de:cc desk.diff) blockers.diff)
|
|
||||||
:_ this
|
|
||||||
~[(poke:ha:cc action)]
|
|
||||||
==
|
==
|
||||||
==
|
==
|
||||||
|
::
|
||||||
|
++ take-clay-warp
|
||||||
|
|= =desk
|
||||||
|
^- (quip card _this)
|
||||||
|
?> ?=(%writ +<.sign)
|
||||||
|
=/ cards
|
||||||
|
?. |(=(desk %base) ~(has-docket de:cc desk)) ~
|
||||||
|
=/ =action:hark ~(commit de:cc desk)
|
||||||
|
~[(poke:ha:cc action)]
|
||||||
|
[[(warp:cy:cc desk) cards] this]
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ on-arvo
|
|
||||||
|= [=wire sign=sign-arvo]
|
|
||||||
^- (quip card _this)
|
|
||||||
?. ?=([%check-lag ~] wire) (on-arvo:def wire sign)
|
|
||||||
?> ?=([%behn %wake *] sign)
|
|
||||||
=+ .^(lag=? %$ (scry:io %$ /zen/lag))
|
|
||||||
?: =(lagging lag) :_(this ~[check:lag:cc])
|
|
||||||
:_ this(lagging lag)
|
|
||||||
:_ ~[check:lag:cc]
|
|
||||||
?:(lagging start:lag:cc stop:lag:cc)
|
|
||||||
::
|
|
||||||
++ on-fail on-fail:def
|
++ on-fail on-fail:def
|
||||||
++ on-leave on-leave:def
|
++ on-leave on-leave:def
|
||||||
--
|
--
|
||||||
@ -89,7 +112,7 @@
|
|||||||
[~[text+'Welcome to urbit'] ~ now.bowl / /]
|
[~[text+'Welcome to urbit'] ~ now.bowl / /]
|
||||||
::
|
::
|
||||||
++ lag
|
++ lag
|
||||||
|%
|
|%
|
||||||
++ check (~(wait pass /check-lag) (add now.bowl lag-interval))
|
++ check (~(wait pass /check-lag) (add now.bowl lag-interval))
|
||||||
++ place [q.byk.bowl /lag]
|
++ place [q.byk.bowl /lag]
|
||||||
++ body `body:hark`[~[text/'Runtime lagging'] ~ now.bowl / /]
|
++ body `body:hark`[~[text/'Runtime lagging'] ~ now.bowl / /]
|
||||||
@ -102,24 +125,23 @@
|
|||||||
++ poke
|
++ poke
|
||||||
|=(=action:hark (poke-our:pass %hark-store hark-action+!>(action)))
|
|=(=action:hark (poke-our:pass %hark-store hark-action+!>(action)))
|
||||||
--
|
--
|
||||||
++ kiln
|
::
|
||||||
|
++ cy
|
||||||
|%
|
|%
|
||||||
++ path /kiln/vats
|
++ tire ~(tire pass /clay/tire)
|
||||||
++ pass ~(. ^pass path)
|
++ warp
|
||||||
++ watch (watch-our:pass %hood path)
|
|= =desk
|
||||||
++ watching (~(has by wex.bowl) [path our.bowl %hood])
|
(~(warp-our pass /clay/warp/[desk]) desk ~ %next %z da+now.bowl /)
|
||||||
++ safe-watch `(unit card)`?:(watching ~ `watch)
|
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
++ de
|
++ de
|
||||||
|_ =desk
|
|_ =desk
|
||||||
++ scry-path (scry:io desk /desk/docket-0)
|
++ scry-path (scry:io desk /desk/docket-0)
|
||||||
++ has-docket .^(? %cu scry-path)
|
++ has-docket .^(? %cu scry-path)
|
||||||
++ docket .^(docket:^docket %cx scry-path)
|
++ docket .^(docket:^docket %cx scry-path)
|
||||||
++ hash .^(@uv %cz (scry:io desk ~))
|
++ hash .^(@uv %cz (scry:io desk ~))
|
||||||
++ place `place:hark`[q.byk.bowl /desk/[desk]]
|
++ place `place:hark`[q.byk.bowl /desk/[desk]]
|
||||||
++ vat
|
++ version ud:.^(cass:clay %cw (scry:io desk /))
|
||||||
.^(vat:hood %gx (scry:io %hood /kiln/vat/[desk]/noun))
|
|
||||||
++ body
|
++ body
|
||||||
|= [=path title=cord content=(unit cord)]
|
|= [=path title=cord content=(unit cord)]
|
||||||
^- body:hark
|
^- body:hark
|
||||||
@ -131,7 +153,7 @@
|
|||||||
%+ rap 3
|
%+ rap 3
|
||||||
?: =(desk %base)
|
?: =(desk %base)
|
||||||
['System software' cord ~]
|
['System software' cord ~]
|
||||||
?: has-docket
|
?: has-docket
|
||||||
['App: "' title:docket '"' cord ~]
|
['App: "' title:docket '"' cord ~]
|
||||||
['Desk: ' desk cord ~]
|
['Desk: ' desk cord ~]
|
||||||
::
|
::
|
||||||
@ -142,7 +164,7 @@
|
|||||||
::
|
::
|
||||||
++ commit
|
++ commit
|
||||||
^- action:hark
|
^- action:hark
|
||||||
?:(=(1 ud.cass:vat) created updated)
|
?:(=(1 version) created updated)
|
||||||
::
|
::
|
||||||
++ created
|
++ created
|
||||||
^- action:hark
|
^- action:hark
|
||||||
@ -155,11 +177,11 @@
|
|||||||
(body /desk/[desk] (title-prefix (rap 3 ' has been updated to ' get-version ~)) ~)
|
(body /desk/[desk] (title-prefix (rap 3 ' has been updated to ' get-version ~)) ~)
|
||||||
::
|
::
|
||||||
++ blocked
|
++ blocked
|
||||||
|= blockers=(set ^desk)
|
|= =weft
|
||||||
^- action:hark
|
^- action:hark
|
||||||
:+ %add-note [/blocked place]
|
:+ %add-note [/blocked place]
|
||||||
%^ body /blocked (title-prefix ' is blocked from upgrading')
|
%^ body /blocked (title-prefix ' is blocked from upgrading')
|
||||||
`(rap 3 'Blocking desks: ' (join ', ' ~(tap in blockers)))
|
`(rap 3 'Blocked waiting for system version: ' (scot %ud num.weft) 'K' ~)
|
||||||
::
|
::
|
||||||
++ ver
|
++ ver
|
||||||
|= =version:^docket
|
|= =version:^docket
|
||||||
@ -172,7 +194,7 @@
|
|||||||
--
|
--
|
||||||
++ note
|
++ note
|
||||||
|%
|
|%
|
||||||
++ merge
|
++ merge
|
||||||
|= [=desk hash=@uv]
|
|= [=desk hash=@uv]
|
||||||
^- (list body:hark)
|
^- (list body:hark)
|
||||||
:_ ~
|
:_ ~
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
%tas s+(scot %tas p.c)
|
%tas s+(scot %tas p.c)
|
||||||
%ud (numb p.c)
|
%ud (numb p.c)
|
||||||
==
|
==
|
||||||
|
::
|
||||||
++ foreign-desk
|
++ foreign-desk
|
||||||
|= [s=^ship =desk]
|
|= [s=^ship =desk]
|
||||||
^- cord
|
^- cord
|
||||||
|
@ -1 +1 @@
|
|||||||
[%zuse 418]
|
[%zuse 417]
|
||||||
|
53
desk/ted/get-dudes.hoon
Normal file
53
desk/ted/get-dudes.hoon
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/- spider
|
||||||
|
/+ *strandio
|
||||||
|
::
|
||||||
|
=, strand=strand:spider
|
||||||
|
::
|
||||||
|
:: send on /spider/garden/json/get-dudes/json
|
||||||
|
::
|
||||||
|
|%
|
||||||
|
++ buds :: get agents currently running
|
||||||
|
|= p=desk
|
||||||
|
=/ m (strand ,(list dude:gall))
|
||||||
|
^- form:m
|
||||||
|
?. =(%$ p)
|
||||||
|
;< q=(list dude:gall) bind:m (suds p)
|
||||||
|
(pure:m q)
|
||||||
|
;< q=(list desk) bind:m duds
|
||||||
|
=| r=(list (list dude:gall))
|
||||||
|
|- ^- form:m
|
||||||
|
=* s $
|
||||||
|
?~ q (pure:m (zing r))
|
||||||
|
;< t=(list dude:gall) bind:m (suds i.q)
|
||||||
|
s(q t.q, r [t r])
|
||||||
|
::
|
||||||
|
++ suds :: clean %ge scry
|
||||||
|
|= p=desk
|
||||||
|
=/ m (strand ,(list dude:gall))
|
||||||
|
^- form:m
|
||||||
|
;< q=(set [dude:gall ?]) bind:m
|
||||||
|
(scry (set ,[dude:gall ?]) /ge/(scot %tas p))
|
||||||
|
%- pure:m
|
||||||
|
(murn ~(tap in q) |=([dude:gall ?] ?.(+.+< ~ `-.+<)))
|
||||||
|
::
|
||||||
|
++ duds :: get desks
|
||||||
|
=/ m (strand ,(list desk))
|
||||||
|
^- form:m
|
||||||
|
;< p=(set desk) bind:m (scry (set ,desk) /cd/base)
|
||||||
|
(pure:m ~(tap in p))
|
||||||
|
--
|
||||||
|
::
|
||||||
|
^- thread:spider
|
||||||
|
|= jon=vase
|
||||||
|
=/ m (strand ,vase)
|
||||||
|
^- form:m
|
||||||
|
;< =bowl:spider bind:m get-bowl
|
||||||
|
=, bowl
|
||||||
|
?~ know=!<((unit json) jon)
|
||||||
|
(pure:m !>(`json`[%s 'invalid-request']))
|
||||||
|
?. ?=([%s @] u.know)
|
||||||
|
(pure:m !>(`json`[%s 'invalid-request']))
|
||||||
|
=, format
|
||||||
|
;< breh=(list @tas) bind:m (buds (so:dejs u.know))
|
||||||
|
%- pure:m
|
||||||
|
!>(`json`(frond:enjs 'buds' a+(turn breh |=(@tas s+[+<]))))
|
16
ui/package-lock.json
generated
16
ui/package-lock.json
generated
@ -20,8 +20,8 @@
|
|||||||
"@tlon/sigil-js": "^1.4.4",
|
"@tlon/sigil-js": "^1.4.4",
|
||||||
"@tloncorp/mock-http-api": "^1.2.0",
|
"@tloncorp/mock-http-api": "^1.2.0",
|
||||||
"@types/lodash": "^4.14.172",
|
"@types/lodash": "^4.14.172",
|
||||||
"@urbit/api": "^2.1.1",
|
"@urbit/api": "^2.2.0",
|
||||||
"@urbit/http-api": "^2.2.0",
|
"@urbit/http-api": "^2.3.0",
|
||||||
"big-integer": "^1.6.48",
|
"big-integer": "^1.6.48",
|
||||||
"browser-cookies": "^1.2.0",
|
"browser-cookies": "^1.2.0",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
@ -1695,9 +1695,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@urbit/api": {
|
"node_modules/@urbit/api": {
|
||||||
"version": "2.1.1",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@urbit/api/-/api-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@urbit/api/-/api-2.2.0.tgz",
|
||||||
"integrity": "sha512-QRlqhtJ73q+pgMdSwuOO62HlxA7/2c5ylCcOUT01LXkJ2LTVCl5u+QnejdDvUmqjOuN2PyZk7df30xJVg6rC2A==",
|
"integrity": "sha512-W8kP9OT6yOK62n+4yCPO3i9QqU5xriLvZQ9WYW4SAV7ktbSrGuf2kmYbnoqfA/NybIs9Q/MbFkPewrz4XJ96Ag==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.16.0",
|
"@babel/runtime": "^7.16.0",
|
||||||
"big-integer": "^1.6.48",
|
"big-integer": "^1.6.48",
|
||||||
@ -8888,9 +8888,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@urbit/api": {
|
"@urbit/api": {
|
||||||
"version": "2.1.1",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@urbit/api/-/api-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@urbit/api/-/api-2.2.0.tgz",
|
||||||
"integrity": "sha512-QRlqhtJ73q+pgMdSwuOO62HlxA7/2c5ylCcOUT01LXkJ2LTVCl5u+QnejdDvUmqjOuN2PyZk7df30xJVg6rC2A==",
|
"integrity": "sha512-W8kP9OT6yOK62n+4yCPO3i9QqU5xriLvZQ9WYW4SAV7ktbSrGuf2kmYbnoqfA/NybIs9Q/MbFkPewrz4XJ96Ag==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.16.0",
|
"@babel/runtime": "^7.16.0",
|
||||||
"big-integer": "^1.6.48",
|
"big-integer": "^1.6.48",
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
"@tlon/sigil-js": "^1.4.4",
|
"@tlon/sigil-js": "^1.4.4",
|
||||||
"@tloncorp/mock-http-api": "^1.2.0",
|
"@tloncorp/mock-http-api": "^1.2.0",
|
||||||
"@types/lodash": "^4.14.172",
|
"@types/lodash": "^4.14.172",
|
||||||
"@urbit/api": "^2.1.1",
|
"@urbit/api": "^2.2.0",
|
||||||
"@urbit/http-api": "^2.2.0",
|
"@urbit/http-api": "^2.3.0",
|
||||||
"big-integer": "^1.6.48",
|
"big-integer": "^1.6.48",
|
||||||
"browser-cookies": "^1.2.0",
|
"browser-cookies": "^1.2.0",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
|
@ -86,9 +86,8 @@ const AppRoutes = () => {
|
|||||||
fetchCharges();
|
fetchCharges();
|
||||||
fetchAllies();
|
fetchAllies();
|
||||||
|
|
||||||
const { fetchVats, fetchLag } = useKilnState.getState();
|
const { initializeKiln } = useKilnState.getState();
|
||||||
fetchVats();
|
initializeKiln();
|
||||||
fetchLag();
|
|
||||||
|
|
||||||
useContactState.getState().initialize(api);
|
useContactState.getState().initialize(api);
|
||||||
useHarkState.getState().start();
|
useHarkState.getState().start();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { chadIsRunning, Treaty, Vat } from '@urbit/api';
|
import { chadIsRunning, Pike, Treaty } from '@urbit/api';
|
||||||
import clipboardCopy from 'clipboard-copy';
|
import clipboardCopy from 'clipboard-copy';
|
||||||
import React, { FC, useCallback, useState } from 'react';
|
import React, { FC, useCallback, useState } from 'react';
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
@ -6,7 +6,7 @@ import { Button, PillButton } from './Button';
|
|||||||
import { Dialog, DialogClose, DialogContent, DialogTrigger } from './Dialog';
|
import { Dialog, DialogClose, DialogContent, DialogTrigger } from './Dialog';
|
||||||
import { DocketHeader } from './DocketHeader';
|
import { DocketHeader } from './DocketHeader';
|
||||||
import { Spinner } from './Spinner';
|
import { Spinner } from './Spinner';
|
||||||
import { VatMeta } from './VatMeta';
|
import { PikeMeta } from './PikeMeta';
|
||||||
import useDocketState, { ChargeWithDesk, useTreaty } from '../state/docket';
|
import useDocketState, { ChargeWithDesk, useTreaty } from '../state/docket';
|
||||||
import { getAppHref, getAppName } from '../state/util';
|
import { getAppHref, getAppName } from '../state/util';
|
||||||
import { addRecentApp } from '../nav/search/Home';
|
import { addRecentApp } from '../nav/search/Home';
|
||||||
@ -17,7 +17,7 @@ type InstallStatus = 'uninstalled' | 'installing' | 'installed';
|
|||||||
type App = ChargeWithDesk | Treaty;
|
type App = ChargeWithDesk | Treaty;
|
||||||
interface AppInfoProps {
|
interface AppInfoProps {
|
||||||
docket: App;
|
docket: App;
|
||||||
vat?: Vat;
|
pike?: Pike;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,10 +34,9 @@ function getInstallStatus(docket: App): InstallStatus {
|
|||||||
return 'uninstalled';
|
return 'uninstalled';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRemoteDesk(docket: App, vat?: Vat) {
|
function getRemoteDesk(docket: App, pike?: Pike) {
|
||||||
if (vat && vat.arak.rail) {
|
if (pike && pike.sync) {
|
||||||
const { ship, desk } = vat.arak.rail;
|
return [pike.sync.ship, pike.sync.desk];
|
||||||
return [ship, desk];
|
|
||||||
}
|
}
|
||||||
if ('chad' in docket) {
|
if ('chad' in docket) {
|
||||||
return ['', docket.desk];
|
return ['', docket.desk];
|
||||||
@ -46,10 +45,10 @@ function getRemoteDesk(docket: App, vat?: Vat) {
|
|||||||
return [ship, desk];
|
return [ship, desk];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AppInfo: FC<AppInfoProps> = ({ docket, vat, className }) => {
|
export const AppInfo: FC<AppInfoProps> = ({ docket, pike, className }) => {
|
||||||
const installStatus = getInstallStatus(docket);
|
const installStatus = getInstallStatus(docket);
|
||||||
const [ship, desk] = getRemoteDesk(docket, vat);
|
const [ship, desk] = getRemoteDesk(docket, pike);
|
||||||
const publisher = vat?.arak?.rail?.publisher ?? ship;
|
const publisher = pike?.sync?.ship ?? ship;
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
const treaty = useTreaty(ship, desk);
|
const treaty = useTreaty(ship, desk);
|
||||||
|
|
||||||
@ -136,10 +135,10 @@ export const AppInfo: FC<AppInfoProps> = ({ docket, vat, className }) => {
|
|||||||
</div>
|
</div>
|
||||||
</DocketHeader>
|
</DocketHeader>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{vat ? (
|
{pike ? (
|
||||||
<>
|
<>
|
||||||
<hr className="-mx-5 sm:-mx-8 border-gray-50" />
|
<hr className="-mx-5 sm:-mx-8 border-gray-50" />
|
||||||
<VatMeta vat={vat} />
|
<PikeMeta pike={pike} />
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
{!treaty ? null : (
|
{!treaty ? null : (
|
||||||
|
25
ui/src/components/PikeMeta.tsx
Normal file
25
ui/src/components/PikeMeta.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Pike } from '@urbit/api';
|
||||||
|
|
||||||
|
import { Attribute } from './Attribute';
|
||||||
|
|
||||||
|
export function PikeMeta(props: { pike: Pike }) {
|
||||||
|
const { pike } = props;
|
||||||
|
|
||||||
|
const pluralUpdates = pike.wefts?.length !== 1;
|
||||||
|
return (
|
||||||
|
<div className="mt-5 sm:mt-8 space-y-5 sm:space-y-8">
|
||||||
|
<Attribute title="Desk Hash" attr="hash">
|
||||||
|
{pike.hash}
|
||||||
|
</Attribute>
|
||||||
|
<Attribute title="Installed into" attr="local-desk">
|
||||||
|
%{pike.sync?.desk}
|
||||||
|
</Attribute>
|
||||||
|
{pike.wefts && pike.wefts.length > 0 ? (
|
||||||
|
<Attribute attr="next" title="Pending Updates">
|
||||||
|
{pike.wefts.length} update{pluralUpdates ? 's are' : ' is'} pending a System Update
|
||||||
|
</Attribute>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -3,11 +3,12 @@ import React, { HTMLAttributes } from 'react';
|
|||||||
|
|
||||||
type ShipNameProps = {
|
type ShipNameProps = {
|
||||||
name: string;
|
name: string;
|
||||||
|
truncate?: boolean;
|
||||||
} & HTMLAttributes<HTMLSpanElement>;
|
} & HTMLAttributes<HTMLSpanElement>;
|
||||||
|
|
||||||
export const ShipName = ({ name, ...props }: ShipNameProps) => {
|
export const ShipName = ({ name, truncate = true, ...props }: ShipNameProps) => {
|
||||||
const separator = /([_^-])/;
|
const separator = /([_^-])/;
|
||||||
const citedName = cite(name);
|
const citedName = truncate ? cite(name) : name;
|
||||||
|
|
||||||
if (!citedName) {
|
if (!citedName) {
|
||||||
return null;
|
return null;
|
||||||
|
103
ui/src/components/SourceSetter.tsx
Normal file
103
ui/src/components/SourceSetter.tsx
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import React, { useCallback, useState } from 'react';
|
||||||
|
import { useAsyncCall } from '../logic/useAsyncCall';
|
||||||
|
import { Button } from './Button';
|
||||||
|
import { ShipName } from './ShipName';
|
||||||
|
import { Spinner } from './Spinner';
|
||||||
|
|
||||||
|
interface SourceSetterProps {
|
||||||
|
appName: string;
|
||||||
|
srcDesk: string;
|
||||||
|
srcShip?: string;
|
||||||
|
title: string;
|
||||||
|
toggleSrc: (desk: string, ship: string) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SourceSetter({
|
||||||
|
appName,
|
||||||
|
srcDesk,
|
||||||
|
srcShip,
|
||||||
|
title,
|
||||||
|
toggleSrc
|
||||||
|
}: SourceSetterProps) {
|
||||||
|
const [newSyncShip, setNewSyncShip] = useState(srcShip ?? '');
|
||||||
|
const { status: requestStatus, call: handleSubmit } = useAsyncCall(toggleSrc);
|
||||||
|
const syncDirty = newSyncShip !== srcShip;
|
||||||
|
|
||||||
|
const onUnset = useCallback(() => {
|
||||||
|
if (!srcShip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
// eslint-disable-next-line no-alert, no-restricted-globals
|
||||||
|
confirm(`Are you sure you want to unsync ${appName}? You will no longer receive updates.`)
|
||||||
|
) {
|
||||||
|
toggleSrc(srcDesk, srcShip);
|
||||||
|
}
|
||||||
|
}, [srcShip, srcDesk]);
|
||||||
|
|
||||||
|
const handleSourceChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const { target } = e;
|
||||||
|
const value = target.value.trim();
|
||||||
|
setNewSyncShip(value.startsWith('~') ? value : `~${value}`);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onSubmit = useCallback(
|
||||||
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
await handleSubmit(srcDesk, newSyncShip);
|
||||||
|
},
|
||||||
|
[srcDesk, newSyncShip]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2 className="h3 mb-7">{title}</h2>
|
||||||
|
<div className="space-y-3">
|
||||||
|
{srcShip ? (
|
||||||
|
<>
|
||||||
|
<h3 className="flex items-center h4 mb-2">Automatic Updates</h3>
|
||||||
|
<p>Automatically download and apply updates to keep {appName} up to date.</p>
|
||||||
|
<div className="flex-1 flex flex-col justify-center space-y-6">
|
||||||
|
<p>
|
||||||
|
OTA Source:{' '}
|
||||||
|
<ShipName name={srcShip} truncate={false} className="font-semibold font-mono" />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<Button onClick={onUnset} variant="destructive">
|
||||||
|
Unsync Updates for {appName}...
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<form className="inner-section relative" onSubmit={onSubmit}>
|
||||||
|
<label htmlFor="ota-source" className="h4 mb-3">
|
||||||
|
Set Update Source
|
||||||
|
</label>
|
||||||
|
<p className="mb-2">Enter a valid urbit name to receive updates for {appName}.</p>
|
||||||
|
<div className="relative">
|
||||||
|
<input
|
||||||
|
id="ota-source"
|
||||||
|
type="text"
|
||||||
|
value={newSyncShip}
|
||||||
|
onChange={handleSourceChange}
|
||||||
|
className="input font-semibold default-ring"
|
||||||
|
/>
|
||||||
|
{syncDirty && (
|
||||||
|
<Button type="submit" className="absolute top-1 right-1 py-1 px-3 text-sm">
|
||||||
|
{requestStatus !== 'loading' && 'Save'}
|
||||||
|
{requestStatus === 'loading' && (
|
||||||
|
<>
|
||||||
|
<span className="sr-only">Saving...</span>
|
||||||
|
<Spinner className="w-5 h-5" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -1,27 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Vat } from '@urbit/api';
|
|
||||||
|
|
||||||
import { Attribute } from './Attribute';
|
|
||||||
|
|
||||||
export function VatMeta(props: { vat: Vat }) {
|
|
||||||
const { vat } = props;
|
|
||||||
const { desk, arak, cass, hash } = vat;
|
|
||||||
|
|
||||||
const { desk: foreignDesk, ship, next } = arak.rail || {};
|
|
||||||
const pluralUpdates = next?.length !== 1;
|
|
||||||
return (
|
|
||||||
<div className="mt-5 sm:mt-8 space-y-5 sm:space-y-8">
|
|
||||||
<Attribute title="Desk Hash" attr="hash">
|
|
||||||
{hash}
|
|
||||||
</Attribute>
|
|
||||||
<Attribute title="Installed into" attr="local-desk">
|
|
||||||
%{desk}
|
|
||||||
</Attribute>
|
|
||||||
{next && next.length > 0 ? (
|
|
||||||
<Attribute attr="next" title="Pending Updates">
|
|
||||||
{next.length} update{pluralUpdates ? 's are' : ' is'} pending a System Update
|
|
||||||
</Attribute>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,42 +1,37 @@
|
|||||||
import { kilnBump, Vat } from '@urbit/api';
|
import { kilnBump, Pike } from '@urbit/api';
|
||||||
import { partition, pick } from 'lodash';
|
import { partition, pick } from 'lodash';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import api from '../state/api';
|
import api from '../state/api';
|
||||||
import { useCharges } from '../state/docket';
|
import { useCharges } from '../state/docket';
|
||||||
import useKilnState, { useVat } from '../state/kiln';
|
import useKilnState, { usePike } from '../state/kiln';
|
||||||
|
|
||||||
export function vatIsBlocked(newKelvin: number | undefined, vat: Vat) {
|
function pikeIsBlocked(newKelvin: number, pike: Pike) {
|
||||||
if (!newKelvin) {
|
return !pike.wefts?.find(({ kelvin }) => kelvin === newKelvin);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !(vat.arak?.rail?.next || []).find(({ weft }) => weft.kelvin === newKelvin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useSystemUpdate() {
|
export function useSystemUpdate() {
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
const base = useVat('base');
|
const base = usePike('base');
|
||||||
const update = base?.arak?.rail?.next?.[0];
|
const nextUpdate = base?.wefts[0];
|
||||||
const newKelvin = update?.weft?.kelvin;
|
const newKelvin = base?.wefts[0]?.kelvin ?? 417;
|
||||||
const charges = useCharges();
|
const charges = useCharges();
|
||||||
const [blocked] = useKilnState((s) => {
|
const [blocked] = useKilnState((s) => {
|
||||||
const [b, u] = partition(Object.entries(s.vats), ([, vat]) => vatIsBlocked(newKelvin, vat));
|
const [b, u] = partition(Object.entries(s.pikes), ([, pike]) => pikeIsBlocked(newKelvin, pike));
|
||||||
return [b.map(([d]) => d), u.map(([d]) => d)] as const;
|
return [b.map(([d]) => d), u.map(([d]) => d)] as const;
|
||||||
});
|
});
|
||||||
|
|
||||||
const systemBlocked = update && blocked;
|
const systemBlocked = nextUpdate && blocked;
|
||||||
const blockedCharges = Object.values(pick(charges, blocked));
|
const blockedCharges = Object.values(pick(charges, blocked));
|
||||||
const blockedCount = blockedCharges.length;
|
const blockedCount = blockedCharges.length;
|
||||||
|
|
||||||
const freezeApps = useCallback(async () => {
|
const freezeApps = useCallback(async () => {
|
||||||
api.poke(kilnBump(true));
|
await api.poke(kilnBump());
|
||||||
push('/leap/upgrading');
|
push('/leap/upgrading');
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
base,
|
nextUpdate,
|
||||||
update,
|
|
||||||
systemBlocked,
|
systemBlocked,
|
||||||
blockedCharges,
|
blockedCharges,
|
||||||
blockedCount,
|
blockedCount,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Handler, SubscriptionHandler, createResponse } from '@tloncorp/mock-http-api';
|
import { Handler, SubscriptionHandler, createResponse } from '@tloncorp/mock-http-api';
|
||||||
import mockContacts from './mockContacts';
|
import mockContacts from './mockContacts';
|
||||||
import { mockAllies, mockCharges, mockTreaties, mockVats } from '../state/mock-data';
|
import { mockAllies, mockCharges, mockTreaties } from '../state/mock-data';
|
||||||
|
|
||||||
const settingsSub = {
|
const settingsSub = {
|
||||||
action: 'subscribe',
|
action: 'subscribe',
|
||||||
@ -45,14 +45,6 @@ const mockHandlers: Handler[] = [
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{
|
|
||||||
action: 'scry',
|
|
||||||
app: 'hood',
|
|
||||||
path: '/kiln/vats',
|
|
||||||
func: () => ({
|
|
||||||
mockVats
|
|
||||||
})
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
action: 'scry',
|
action: 'scry',
|
||||||
app: 'hood',
|
app: 'hood',
|
||||||
|
@ -3,9 +3,9 @@ import classNames from 'classnames';
|
|||||||
import clipboardCopy from 'clipboard-copy';
|
import clipboardCopy from 'clipboard-copy';
|
||||||
import React, { HTMLAttributes, useCallback, useState } from 'react';
|
import React, { HTMLAttributes, useCallback, useState } from 'react';
|
||||||
import { Link, Route, useHistory } from 'react-router-dom';
|
import { Link, Route, useHistory } from 'react-router-dom';
|
||||||
import { Vat } from '@urbit/api';
|
import { Pike } from '@urbit/api';
|
||||||
import { Adjust } from '../components/icons/Adjust';
|
import { Adjust } from '../components/icons/Adjust';
|
||||||
import { useVat } from '../state/kiln';
|
import { usePike } from '../state/kiln';
|
||||||
import { disableDefault, handleDropdownLink } from '../state/util';
|
import { disableDefault, handleDropdownLink } from '../state/util';
|
||||||
import { useMedia } from '../logic/useMedia';
|
import { useMedia } from '../logic/useMedia';
|
||||||
import { Cross } from '../components/icons/Cross';
|
import { Cross } from '../components/icons/Cross';
|
||||||
@ -17,15 +17,15 @@ type SystemMenuProps = HTMLAttributes<HTMLButtonElement> & {
|
|||||||
shouldDim: boolean;
|
shouldDim: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function getHash(vat: Vat): string {
|
function getHash(pike: Pike): string {
|
||||||
const parts = vat.hash.split('.');
|
const parts = pike.hash.split('.');
|
||||||
return parts[parts.length - 1];
|
return parts[parts.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SystemMenu = ({ className, open, subMenuOpen, shouldDim }: SystemMenuProps) => {
|
export const SystemMenu = ({ className, open, subMenuOpen, shouldDim }: SystemMenuProps) => {
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
const garden = useVat(window.desk);
|
const garden = usePike(window.desk);
|
||||||
const hash = garden ? getHash(garden) : null;
|
const hash = garden ? getHash(garden) : null;
|
||||||
const isMobile = useMedia('(max-width: 639px)');
|
const isMobile = useMedia('(max-width: 639px)');
|
||||||
const select = useLeapStore((s) => s.select);
|
const select = useLeapStore((s) => s.select);
|
||||||
|
@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom';
|
|||||||
import { AppInfo } from '../../components/AppInfo';
|
import { AppInfo } from '../../components/AppInfo';
|
||||||
import { Spinner } from '../../components/Spinner';
|
import { Spinner } from '../../components/Spinner';
|
||||||
import useDocketState, { useCharge, useTreaty } from '../../state/docket';
|
import useDocketState, { useCharge, useTreaty } from '../../state/docket';
|
||||||
import { useVat } from '../../state/kiln';
|
import { usePike } from '../../state/kiln';
|
||||||
import { getAppName } from '../../state/util';
|
import { getAppName } from '../../state/util';
|
||||||
import { useLeapStore } from '../Nav';
|
import { useLeapStore } from '../Nav';
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ export const TreatyInfo = () => {
|
|||||||
const select = useLeapStore((state) => state.select);
|
const select = useLeapStore((state) => state.select);
|
||||||
const { host, desk } = useParams<{ host: string; desk: string }>();
|
const { host, desk } = useParams<{ host: string; desk: string }>();
|
||||||
const treaty = useTreaty(host, desk);
|
const treaty = useTreaty(host, desk);
|
||||||
const vat = useVat(desk);
|
const pike = usePike(desk);
|
||||||
const charge = useCharge(desk);
|
const charge = useCharge(desk);
|
||||||
const name = getAppName(treaty);
|
const name = getAppName(treaty);
|
||||||
|
|
||||||
@ -34,5 +34,5 @@ export const TreatyInfo = () => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <AppInfo className="dialog-inner-container" docket={charge || treaty} vat={vat} />;
|
return <AppInfo className="dialog-inner-container" docket={charge || treaty} pike={pike} />;
|
||||||
};
|
};
|
||||||
|
@ -26,8 +26,8 @@ export const Grid: FunctionComponent = () => {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
const start = performance.now();
|
const start = performance.now();
|
||||||
await useKilnState.getState().fetchVats();
|
await useKilnState.getState().fetchPikes();
|
||||||
await useKilnState.getState().fetchVats();
|
await useKilnState.getState().fetchPikes();
|
||||||
if (performance.now() - start > 5000) {
|
if (performance.now() - start > 5000) {
|
||||||
attempt(count + 1);
|
attempt(count + 1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
|
import { Pikes } from '@urbit/api';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Switch, Route, Redirect, RouteComponentProps } from 'react-router-dom';
|
import { Switch, Route, Redirect, RouteComponentProps } from 'react-router-dom';
|
||||||
import { Spinner } from '../components/Spinner';
|
import { Spinner } from '../components/Spinner';
|
||||||
import { useQuery } from '../logic/useQuery';
|
import { useQuery } from '../logic/useQuery';
|
||||||
import { useCharge } from '../state/docket';
|
import { useCharge } from '../state/docket';
|
||||||
import useKilnState, { useKilnLoaded } from '../state/kiln';
|
import { useKilnLoaded, usePikes } from '../state/kiln';
|
||||||
import { getAppHref } from '../state/util';
|
import { getAppHref } from '../state/util';
|
||||||
|
|
||||||
function getDeskByForeignRef(ship: string, desk: string): string | undefined {
|
function getDeskByForeignRef(pikes: Pikes, ship: string, desk: string): string | undefined {
|
||||||
const { vats } = useKilnState.getState();
|
const found = Object.entries(pikes).find(
|
||||||
const found = Object.entries(vats).find(
|
([, pike]) => pike.sync?.ship === ship && pike.sync?.desk === desk
|
||||||
([, vat]) => vat.arak.rail?.ship === ship && vat.arak.rail?.desk === desk
|
|
||||||
);
|
);
|
||||||
return found ? found[0] : undefined;
|
return found ? found[0] : undefined;
|
||||||
}
|
}
|
||||||
@ -22,8 +22,8 @@ type AppLinkProps = RouteComponentProps<{
|
|||||||
|
|
||||||
function AppLink({ match, history, location }: AppLinkProps) {
|
function AppLink({ match, history, location }: AppLinkProps) {
|
||||||
const { ship, desk, link = '' } = match.params;
|
const { ship, desk, link = '' } = match.params;
|
||||||
const ourDesk = getDeskByForeignRef(ship, desk);
|
const pikes = usePikes();
|
||||||
console.log(ourDesk);
|
const ourDesk = getDeskByForeignRef(pikes, ship, desk);
|
||||||
|
|
||||||
if (ourDesk) {
|
if (ourDesk) {
|
||||||
return <AppLinkRedirect desk={ourDesk} link={link} />;
|
return <AppLinkRedirect desk={ourDesk} link={link} />;
|
||||||
|
@ -1,50 +1,27 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React from 'react';
|
||||||
import { RouteComponentProps } from 'react-router-dom';
|
import { RouteComponentProps } from 'react-router-dom';
|
||||||
import { Setting } from '../components/Setting';
|
|
||||||
import { ShipName } from '../components/ShipName';
|
|
||||||
import { useCharge } from '../state/docket';
|
import { useCharge } from '../state/docket';
|
||||||
import useKilnState, { useVat } from '../state/kiln';
|
import useKilnState, { usePike } from '../state/kiln';
|
||||||
import { getAppName } from '../state/util';
|
import { getAppName } from '../state/util';
|
||||||
|
import SourceSetter from '../components/SourceSetter';
|
||||||
|
|
||||||
export const AppPrefs = ({ match }: RouteComponentProps<{ desk: string }>) => {
|
export const AppPrefs = ({ match }: RouteComponentProps<{ desk: string }>) => {
|
||||||
const { desk } = match.params;
|
const { desk } = match.params;
|
||||||
const charge = useCharge(desk);
|
const charge = useCharge(desk);
|
||||||
const vat = useVat(desk);
|
const appName = getAppName(charge);
|
||||||
const tracking = !!vat?.arak.rail;
|
const pike = usePike(desk);
|
||||||
const otasEnabled = !vat?.arak.rail?.paused;
|
const srcShip = pike?.sync?.ship;
|
||||||
const otaSource = vat?.arak.rail?.ship;
|
const { toggleSync } = useKilnState();
|
||||||
const toggleOTAs = useKilnState((s) => s.toggleOTAs);
|
|
||||||
|
|
||||||
const toggleUpdates = useCallback((on: boolean) => toggleOTAs(desk, on), [desk, toggleOTAs]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="inner-section space-y-8 relative">
|
||||||
<h2 className="h3 mb-7">{getAppName(charge)} Settings</h2>
|
<SourceSetter
|
||||||
<div className="space-y-8">
|
appName={appName}
|
||||||
{tracking ? (
|
title={`${appName} Settings`}
|
||||||
<Setting
|
toggleSrc={toggleSync}
|
||||||
on={otasEnabled}
|
srcDesk={desk}
|
||||||
toggle={toggleUpdates}
|
srcShip={srcShip}
|
||||||
name="Automatic Updates"
|
/>
|
||||||
>
|
</div>
|
||||||
<p className="mb-1 leading-5">
|
|
||||||
Automatically download and apply updates to keep{' '}
|
|
||||||
{getAppName(charge)} up to date.
|
|
||||||
</p>
|
|
||||||
{otaSource && (
|
|
||||||
<p>
|
|
||||||
OTA Source:{' '}
|
|
||||||
<ShipName
|
|
||||||
name={otaSource}
|
|
||||||
className="font-mono font-semibold"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</Setting>
|
|
||||||
) : (
|
|
||||||
<h4 className="text-gray-500">No settings</h4>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Vat } from '@urbit/api';
|
import { Pike } from '@urbit/api';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { AppList } from '../../components/AppList';
|
import { AppList } from '../../components/AppList';
|
||||||
import { Button } from '../../components/Button';
|
import { Button } from '../../components/Button';
|
||||||
@ -6,24 +6,22 @@ import { Dialog, DialogClose, DialogContent, DialogTrigger } from '../../compone
|
|||||||
import { FullTlon16Icon } from '../../components/icons/FullTlon16Icon';
|
import { FullTlon16Icon } from '../../components/icons/FullTlon16Icon';
|
||||||
import { useSystemUpdate } from '../../logic/useSystemUpdate';
|
import { useSystemUpdate } from '../../logic/useSystemUpdate';
|
||||||
import { useCharge } from '../../state/docket';
|
import { useCharge } from '../../state/docket';
|
||||||
import { useVat } from '../../state/kiln';
|
import { usePike } from '../../state/kiln';
|
||||||
import { disableDefault, pluralize } from '../../state/util';
|
import { disableDefault, pluralize } from '../../state/util';
|
||||||
import { UpdatePreferences } from './UpdatePreferences';
|
import { UpdatePreferences } from './UpdatePreferences';
|
||||||
|
|
||||||
function getHash(vat: Vat): string {
|
function getHash(pike: Pike): string {
|
||||||
const parts = vat.hash.split('.');
|
const parts = pike.hash.split('.');
|
||||||
return parts[parts.length - 1];
|
return parts[parts.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AboutSystem = () => {
|
export const AboutSystem = () => {
|
||||||
const garden = useVat('garden');
|
|
||||||
const gardenCharge = useCharge('garden');
|
const gardenCharge = useCharge('garden');
|
||||||
const { base, update, systemBlocked, blockedCharges, blockedCount, freezeApps } =
|
const gardenPike = usePike(window.desk);
|
||||||
|
const { systemBlocked, blockedCharges, blockedCount, freezeApps } =
|
||||||
useSystemUpdate();
|
useSystemUpdate();
|
||||||
const hash = base && getHash(base);
|
const hash = gardenPike && getHash(gardenPike);
|
||||||
const aeon = base ? base.arak.rail?.aeon : '';
|
|
||||||
const nextAeon = update?.aeon;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="inner-section space-y-8 relative mb-4">
|
<div className="inner-section space-y-8 relative mb-4">
|
||||||
@ -45,15 +43,6 @@ export const AboutSystem = () => {
|
|||||||
<p>
|
<p>
|
||||||
Version {gardenCharge?.version} ({hash})
|
Version {gardenCharge?.version} ({hash})
|
||||||
</p>
|
</p>
|
||||||
{systemBlocked && (
|
|
||||||
<p>
|
|
||||||
Aeon {aeon}{' '}
|
|
||||||
<span className="text-orange-500 mx-4 space-x-2">
|
|
||||||
<span>—></span> <span>/</span> <span>—></span>
|
|
||||||
</span>{' '}
|
|
||||||
Aeon {nextAeon}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{systemBlocked ? (
|
{systemBlocked ? (
|
||||||
<>
|
<>
|
||||||
@ -98,7 +87,7 @@ export const AboutSystem = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<UpdatePreferences base={base} />
|
<UpdatePreferences />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,81 +1,25 @@
|
|||||||
import { Vat } from '@urbit/api';
|
import { Vat } from '@urbit/api';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { ChangeEvent, FormEvent, useCallback, useEffect, useState } from 'react';
|
import React from 'react';
|
||||||
import { Button } from '../../components/Button';
|
import SourceSetter from '../../components/SourceSetter';
|
||||||
import { Setting } from '../../components/Setting';
|
import useKilnState, { usePike } from '../../state/kiln';
|
||||||
import { Spinner } from '../../components/Spinner';
|
|
||||||
import { useAsyncCall } from '../../logic/useAsyncCall';
|
|
||||||
import useKilnState from '../../state/kiln';
|
|
||||||
|
|
||||||
interface UpdatePreferencesProps {
|
|
||||||
base: Vat | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const UpdatePreferences = ({ base }: UpdatePreferencesProps) => {
|
|
||||||
const { changeOTASource, toggleOTAs } = useKilnState((s) =>
|
|
||||||
_.pick(s, ['toggleOTAs', 'changeOTASource'])
|
|
||||||
);
|
|
||||||
const otasEnabled = base && !(base.arak?.rail?.paused ?? true);
|
|
||||||
const otaSource = base && base.arak.rail?.ship;
|
|
||||||
|
|
||||||
const toggleBase = useCallback((on: boolean) => toggleOTAs('base', on), [toggleOTAs]);
|
|
||||||
|
|
||||||
const [source, setSource] = useState('');
|
|
||||||
const sourceDirty = source !== otaSource;
|
|
||||||
const { status: sourceStatus, call: setOTA } = useAsyncCall(changeOTASource);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (otaSource) {
|
|
||||||
setSource(otaSource);
|
|
||||||
}
|
|
||||||
}, [otaSource]);
|
|
||||||
|
|
||||||
const handleSourceChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const { target } = e;
|
|
||||||
const value = target.value.trim();
|
|
||||||
setSource(value.startsWith('~') ? value : `~${value}`);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onSubmit = useCallback(
|
|
||||||
(e: FormEvent<HTMLFormElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setOTA(source);
|
|
||||||
},
|
|
||||||
[source]
|
|
||||||
);
|
|
||||||
|
|
||||||
|
export const UpdatePreferences = () => {
|
||||||
|
const desk = 'base';
|
||||||
|
const appName = 'your Urbit';
|
||||||
|
const pike = usePike(desk);
|
||||||
|
const srcShip = pike?.sync?.ship;
|
||||||
|
const { toggleInstall } = useKilnState();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="inner-section space-y-8 relative">
|
<div className="inner-section space-y-8 relative">
|
||||||
<h2 className="h4">Update Preferences</h2>
|
<SourceSetter
|
||||||
<form onSubmit={onSubmit}>
|
appName={appName}
|
||||||
<label htmlFor="ota-source" className="block font-semibold mb-1.5">
|
toggleSrc={toggleInstall}
|
||||||
System Update Provider
|
srcDesk={desk}
|
||||||
</label>
|
srcShip={srcShip}
|
||||||
<div className="flex items-center space-x-2">
|
title="System Updates"
|
||||||
<input
|
/>
|
||||||
id="ota-source"
|
|
||||||
type="text"
|
|
||||||
value={source}
|
|
||||||
onChange={handleSourceChange}
|
|
||||||
className="input bg-gray-50 font-semibold default-ring"
|
|
||||||
/>
|
|
||||||
<Button type="submit" disabled={!sourceDirty}>
|
|
||||||
{sourceStatus !== 'loading' && 'Update'}
|
|
||||||
{sourceStatus === 'loading' && (
|
|
||||||
<>
|
|
||||||
<span className="sr-only">Saving...</span>
|
|
||||||
<Spinner className="w-5 h-5" />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<Setting on={!!otasEnabled} toggle={toggleBase} name="Automatically Update My Urbit">
|
|
||||||
<p className="text-gray-600 leading-5">
|
|
||||||
Ensure that system updates are downloaded and applied as soon as my update provider has an
|
|
||||||
update readied
|
|
||||||
</p>
|
|
||||||
</Setting>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,79 +1,76 @@
|
|||||||
import {
|
import {
|
||||||
getVats,
|
|
||||||
Vats,
|
|
||||||
scryLag,
|
scryLag,
|
||||||
getBlockers,
|
getPikes,
|
||||||
Vat,
|
Pikes,
|
||||||
kilnInstall,
|
Pike,
|
||||||
kilnPause,
|
kilnUnsync,
|
||||||
kilnResume
|
kilnSync,
|
||||||
|
kilnUninstall,
|
||||||
|
kilnInstall
|
||||||
} from '@urbit/api';
|
} from '@urbit/api';
|
||||||
import create from 'zustand';
|
import create from 'zustand';
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import api from './api';
|
import api from './api';
|
||||||
|
import { fakeRequest, useMockData } from './util';
|
||||||
|
import { mockPikes } from './mock-data';
|
||||||
|
|
||||||
interface KilnState {
|
interface KilnState {
|
||||||
vats: Vats;
|
pikes: Pikes;
|
||||||
loaded: boolean;
|
loaded: boolean;
|
||||||
fetchVats: () => Promise<void>;
|
|
||||||
lag: boolean;
|
lag: boolean;
|
||||||
fetchLag: () => Promise<void>;
|
fetchLag: () => Promise<void>;
|
||||||
changeOTASource: (ship: string) => Promise<void>;
|
fetchPikes: () => Promise<void>;
|
||||||
toggleOTAs: (desk: string, on: boolean) => Promise<void>;
|
toggleInstall: (desk: string, ship: string) => Promise<void>;
|
||||||
|
toggleSync: (desk: string, ship: string) => Promise<void>;
|
||||||
set: (s: KilnState) => void;
|
set: (s: KilnState) => void;
|
||||||
|
initializeKiln: () => Promise<void>;
|
||||||
}
|
}
|
||||||
const useKilnState = create<KilnState>((set, get) => ({
|
const useKilnState = create<KilnState>((set, get) => ({
|
||||||
vats: {},
|
pikes: useMockData ? mockPikes : {},
|
||||||
lag: false,
|
lag: false,
|
||||||
loaded: false,
|
loaded: false,
|
||||||
fetchVats: async () => {
|
fetchPikes: async () => {
|
||||||
const vats = await api.scry<Vats>(getVats);
|
if (useMockData) {
|
||||||
set({ vats, loaded: true });
|
await fakeRequest({}, 500);
|
||||||
|
set({ loaded: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pikes = await api.scry<Pikes>(getPikes);
|
||||||
|
set({ pikes, loaded: true });
|
||||||
},
|
},
|
||||||
fetchLag: async () => {
|
fetchLag: async () => {
|
||||||
const lag = await api.scry<boolean>(scryLag);
|
const lag = await api.scry<boolean>(scryLag);
|
||||||
set({ lag });
|
set({ lag });
|
||||||
},
|
},
|
||||||
changeOTASource: async (ship: string) => {
|
toggleInstall: async (desk: string, ship: string) => {
|
||||||
await api.poke(kilnInstall(ship, 'kids', 'base'));
|
const synced = !!get().pikes[desk].sync;
|
||||||
|
await (useMockData
|
||||||
|
? fakeRequest('')
|
||||||
|
: api.poke(synced ? kilnUninstall(desk) : kilnInstall(ship, 'kids', desk)));
|
||||||
|
await get().fetchPikes();
|
||||||
},
|
},
|
||||||
toggleOTAs: async (desk: string, on: boolean) => {
|
toggleSync: async (desk: string, ship: string) => {
|
||||||
set(
|
const synced = !!get().pikes[desk].sync;
|
||||||
produce((draft: KilnState) => {
|
await (useMockData
|
||||||
const { arak } = draft.vats[desk];
|
? fakeRequest('')
|
||||||
if (!arak.rail) {
|
: api.poke(synced ? kilnUnsync(ship, desk) : kilnSync(ship, desk)));
|
||||||
return;
|
await get().fetchPikes();
|
||||||
}
|
},
|
||||||
if (on) {
|
set: produce(set),
|
||||||
arak.rail.paused = false;
|
initializeKiln: async () => {
|
||||||
} else {
|
await get().fetchLag();
|
||||||
arak.rail.paused = true;
|
await get().fetchPikes();
|
||||||
}
|
}
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
await api.poke(on ? kilnResume(desk) : kilnPause(desk));
|
|
||||||
await get().fetchVats(); // refresh vat state
|
|
||||||
},
|
|
||||||
set: produce(set)
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
api.subscribe({
|
const selPikes = (s: KilnState) => s.pikes;
|
||||||
app: 'hood',
|
export function usePikes(): Pikes {
|
||||||
path: '/kiln/vats',
|
return useKilnState(selPikes);
|
||||||
event: () => {
|
|
||||||
useKilnState.getState().fetchVats();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const selBlockers = (s: KilnState) => getBlockers(s.vats);
|
|
||||||
export function useBlockers() {
|
|
||||||
return useKilnState(selBlockers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useVat(desk: string): Vat | undefined {
|
export function usePike(desk: string): Pike | undefined {
|
||||||
return useKilnState(useCallback((s) => s.vats[desk], [desk]));
|
return useKilnState(useCallback((s) => s.pikes[desk], [desk]));
|
||||||
}
|
}
|
||||||
|
|
||||||
const selLag = (s: KilnState) => s.lag;
|
const selLag = (s: KilnState) => s.lag;
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
Vat,
|
|
||||||
Vats,
|
|
||||||
Allies,
|
Allies,
|
||||||
Charges,
|
Charges,
|
||||||
DocketHrefGlob,
|
DocketHrefGlob,
|
||||||
@ -13,7 +11,8 @@ import {
|
|||||||
Contact,
|
Contact,
|
||||||
Contacts,
|
Contacts,
|
||||||
Timebox,
|
Timebox,
|
||||||
harkBinToId
|
harkBinToId,
|
||||||
|
Pikes
|
||||||
} from '@urbit/api';
|
} from '@urbit/api';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import systemUrl from '../assets/system.png';
|
import systemUrl from '../assets/system.png';
|
||||||
@ -341,37 +340,35 @@ export const mockContacts: Contacts = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mockVat = (desk: string, blockers?: boolean): Vat => ({
|
export const mockPikes: Pikes = {
|
||||||
cass: {
|
kids: {
|
||||||
da: '~2021.9.13..05.41.04..ae65',
|
sync: null,
|
||||||
ud: 1
|
zest: 'dead',
|
||||||
|
wefts: [],
|
||||||
|
hash: '0v19.q7u27.omps3.fbhf4.53rai.co157.pben7.pu94n.63v4p.3kcb7.iafj0'
|
||||||
},
|
},
|
||||||
desk,
|
garden: {
|
||||||
arak: {
|
sync: {
|
||||||
rein: {
|
desk: 'garden',
|
||||||
sub: [],
|
ship: '~mister-dister-dozzod-dozzod'
|
||||||
add: []
|
|
||||||
},
|
},
|
||||||
rail:
|
zest: 'live',
|
||||||
desk === 'uniswap'
|
wefts: [],
|
||||||
? null
|
hash: '0v18.hbbs6.onu15.skjkv.qrfgl.vf4oo.0igo5.2q0d3.6r3r8.2dkmo.oa04m'
|
||||||
: {
|
|
||||||
aeon: 3,
|
|
||||||
desk,
|
|
||||||
publisher: '~zod',
|
|
||||||
next: blockers ? [{ aeon: 3, weft: { name: 'zuse', kelvin: 419 } }] : [],
|
|
||||||
ship: '~zod',
|
|
||||||
paused: desk === 'groups'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
hash: '0vh.lhfn6.julg1.fs52d.g2lqj.q5kp0.2o7j3.2bljl.jdm34.hd46v.9uv5v'
|
landscape: {
|
||||||
});
|
sync: {
|
||||||
|
desk: 'landscape',
|
||||||
const badVats = ['inbox', 'system', 'terminal', 'base'];
|
ship: '~lander-dister-dozzod-dozzod'
|
||||||
export const mockVats = _.reduce(
|
},
|
||||||
mockCharges,
|
zest: 'live',
|
||||||
(vats, charge, desk) => {
|
wefts: [],
|
||||||
return { ...vats, [desk]: mockVat(desk, !badVats.includes(desk)) };
|
hash: '0v1t.qln8k.cskmt.cn6lv.gu335.jfba6.kte90.iqqn3.aj67b.t389a.8imuo'
|
||||||
},
|
},
|
||||||
{ base: mockVat('base', true) } as Vats
|
base: {
|
||||||
);
|
sync: null,
|
||||||
|
zest: 'live',
|
||||||
|
wefts: [],
|
||||||
|
hash: '0v1e.b5auh.6u82i.hqk1r.22kli.4ubef.a1cbo.3g532.6l49k.g0i8e.t6eid'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -2,6 +2,16 @@ import { Docket, DocketHref, Treaty } from '@urbit/api';
|
|||||||
import { hsla, parseToHsla } from 'color2k';
|
import { hsla, parseToHsla } from 'color2k';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
export const useMockData = import.meta.env.MODE === 'mock';
|
||||||
|
|
||||||
|
export async function fakeRequest<T>(data: T, time = 300): Promise<T> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(data);
|
||||||
|
}, time);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function getAppHref(href: DocketHref) {
|
export function getAppHref(href: DocketHref) {
|
||||||
return 'site' in href ? href.site : `/apps/${href.glob.base}/`;
|
return 'site' in href ? href.site : `/apps/${href.glob.base}/`;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import { getAppHref } from '../state/util';
|
|||||||
import { useRecentsStore } from '../nav/search/Home';
|
import { useRecentsStore } from '../nav/search/Home';
|
||||||
import { ChargeWithDesk } from '../state/docket';
|
import { ChargeWithDesk } from '../state/docket';
|
||||||
import { useTileColor } from './useTileColor';
|
import { useTileColor } from './useTileColor';
|
||||||
import { useVat } from '../state/kiln';
|
import { usePike } from '../state/kiln';
|
||||||
import { Bullet } from '../components/icons/Bullet';
|
import { Bullet } from '../components/icons/Bullet';
|
||||||
import { dragTypes } from './TileGrid';
|
import { dragTypes } from './TileGrid';
|
||||||
|
|
||||||
@ -21,11 +21,12 @@ type TileProps = {
|
|||||||
export const Tile: FunctionComponent<TileProps> = ({ charge, desk, disabled = false }) => {
|
export const Tile: FunctionComponent<TileProps> = ({ charge, desk, disabled = false }) => {
|
||||||
const addRecentApp = useRecentsStore((state) => state.addRecentApp);
|
const addRecentApp = useRecentsStore((state) => state.addRecentApp);
|
||||||
const { title, image, color, chad, href } = charge;
|
const { title, image, color, chad, href } = charge;
|
||||||
const vat = useVat(desk);
|
const pike = usePike(desk);
|
||||||
const { lightText, tileColor, menuColor, suspendColor, suspendMenuColor } = useTileColor(color);
|
const { lightText, tileColor, menuColor, suspendColor, suspendMenuColor } = useTileColor(color);
|
||||||
const loading = !disabled && 'install' in chad;
|
const loading = !disabled && 'install' in chad;
|
||||||
const suspended = disabled || 'suspend' in chad;
|
const suspended = disabled || 'suspend' in chad;
|
||||||
const hung = 'hung' in chad;
|
const hung = 'hung' in chad;
|
||||||
|
// TODO should held zest be considered inactive? suspended? also, null sync?
|
||||||
const active = !disabled && chadIsRunning(chad);
|
const active = !disabled && chadIsRunning(chad);
|
||||||
const link = getAppHref(href);
|
const link = getAppHref(href);
|
||||||
const backgroundColor = suspended ? suspendColor : active ? tileColor || 'purple' : suspendColor;
|
const backgroundColor = suspended ? suspendColor : active ? tileColor || 'purple' : suspendColor;
|
||||||
@ -56,6 +57,9 @@ export const Tile: FunctionComponent<TileProps> = ({ charge, desk, disabled = fa
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div className="absolute z-10 top-4 left-4 sm:top-6 sm:left-6 flex items-center">
|
<div className="absolute z-10 top-4 left-4 sm:top-6 sm:left-6 flex items-center">
|
||||||
|
{pike?.zest === 'held' && !disabled && (
|
||||||
|
<Bullet className="w-4 h-4 text-orange-500 dark:text-black" />
|
||||||
|
)}
|
||||||
{!active && (
|
{!active && (
|
||||||
<>
|
<>
|
||||||
{loading && <Spinner className="h-6 w-6 mr-2" />}
|
{loading && <Spinner className="h-6 w-6 mr-2" />}
|
||||||
@ -65,9 +69,6 @@ export const Tile: FunctionComponent<TileProps> = ({ charge, desk, disabled = fa
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{vat?.arak.rail?.paused && !disabled && (
|
|
||||||
<Bullet className="absolute z-10 top-5 left-5 sm:top-7 sm:left-7 w-4 h-4 text-orange-500 dark:text-black" />
|
|
||||||
)}
|
|
||||||
<TileMenu
|
<TileMenu
|
||||||
desk={desk}
|
desk={desk}
|
||||||
chad={chad}
|
chad={chad}
|
||||||
|
@ -3,13 +3,13 @@ import { useHistory, useParams } from 'react-router-dom';
|
|||||||
import { Dialog, DialogContent } from '../components/Dialog';
|
import { Dialog, DialogContent } from '../components/Dialog';
|
||||||
import { AppInfo } from '../components/AppInfo';
|
import { AppInfo } from '../components/AppInfo';
|
||||||
import { useCharge } from '../state/docket';
|
import { useCharge } from '../state/docket';
|
||||||
import { useVat } from '../state/kiln';
|
import { usePike } from '../state/kiln';
|
||||||
|
|
||||||
export const TileInfo = () => {
|
export const TileInfo = () => {
|
||||||
const { desk } = useParams<{ desk: string }>();
|
const { desk } = useParams<{ desk: string }>();
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
const charge = useCharge(desk);
|
const charge = useCharge(desk);
|
||||||
const vat = useVat(desk);
|
const pike = usePike(desk);
|
||||||
|
|
||||||
if (!charge) {
|
if (!charge) {
|
||||||
return null;
|
return null;
|
||||||
@ -18,7 +18,7 @@ export const TileInfo = () => {
|
|||||||
return (
|
return (
|
||||||
<Dialog open onOpenChange={(open) => !open && push('/')}>
|
<Dialog open onOpenChange={(open) => !open && push('/')}>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<AppInfo vat={vat} docket={charge} />
|
<AppInfo pike={pike} docket={charge} />
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user