Merge branch 'dist' of github.com:urbit/urbit into dist

This commit is contained in:
Hunter Miller 2021-09-29 14:11:46 -05:00
commit 3dbfe480c9
56 changed files with 491 additions and 7677 deletions

3
bin/multi-brass.pill Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5159d6516c0b3d12b3c7f39f434ab769e99392dc94aa43add32bb2a91455c73a
size 6121099

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:12b01b31df6d806b27415fd2d944a54927f78e757af2b92f8cedf3c70a4fa582
size 14548075
oid sha256:4427b6e4a925502fe2e63087e190dfe0c77f75644dfe31a306de64d269b128f2
size 14661883

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9992ace45834a781c2f8094b2ce37fdc55a5e9dca530f42f8905052fd9087a64
size 12720975
oid sha256:8baf284490d8c7cfbad2481f1ef0d17a6bb05200bc179b78c1a8718461756a06
size 12941119

View File

@ -151,7 +151,7 @@
.^ (list cord)
%cx
(scot %p our.bowl)
%home
%base
(scot %da now.bowl)
path
==

View File

@ -2,8 +2,8 @@
/+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln
|%
+$ state
$~ [%20 *state:drum *state:helm *state:kiln]
$>(%20 any-state)
$~ [%21 *state:drum *state:helm *state:kiln]
$>(%21 any-state)
::
+$ any-state
$% [ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)]
@ -21,6 +21,7 @@
[%18 drum=state-4:drum helm=state:helm kiln=state-5:kiln]
[%19 drum=state-4:drum helm=state:helm kiln=state-6:kiln]
[%20 drum=state-4:drum helm=state:helm kiln=state-7:kiln]
[%21 drum=state-4:drum helm=state:helm kiln=state-8:kiln]
==
+$ any-state-tuple
$: drum=any-state:drum

View File

@ -9,17 +9,43 @@
!:
:- %say
|= $: [now=@da eny=@uvJ bec=beak]
arg=$@(~ [top=path ~])
::
:: arg: desks to build pill from
::
:: list of desks. defaults to [%base]~.
:: the first desk in this list will become the pill's base desk.
:: optionally, the first desk may be replaced with a fully
:: qualified path to the new boot system (typically in sys).
:: the rest of the desks will be installed through kiln.
::
$= arg
$@ ~
$: base=$@(desk [@ta @ta @ta path])
rest=(list desk)
==
::
~
==
:- %boot-pill
^- pill:pill
::
:: sys: root path to boot system, `/~me/[desk]/now/sys`
:: bas: root path to boot system' desk
:: dez: secondary desks and their root paths
::
=/ sys=path
?^ arg top.arg
/(scot %p p.bec)/[q.bec]/(scot %da now)/sys
?: ?=([^ *] arg)
`path`base.arg
=/ =desk
?~ arg %base
?>(?=(@ base.arg) base.arg)
/(scot %p p.bec)/[desk]/(scot %da now)/sys
=/ bas=path
(scag 3 sys)
=/ dez=(list [desk path])
?~ arg ~
%+ turn rest.arg
|= =desk
[desk /(scot %p p.bec)/[desk]/(scot %da now)]
::
:: compiler-source: hoon source file producing compiler, `sys/hoon`
::
@ -52,10 +78,11 @@
==
:: a pill is a 3-tuple of event-lists: [boot kernel userspace]
::
=/ bas=path (flop (tail (flop sys)))
:+ %pill %brass
:+ boot-ova
:~ (boot-ovum:pill compiler-source arvo-source)
(file-ovum2:pill bas)
==
[(file-ovum:pill %base bas) ~]
%+ turn
(snoc dez [%base bas])
file-ovum:pill

View File

@ -351,6 +351,6 @@
++ note-write-csv-to-clay
|= [pax=path file-content=wain]
?> =(%csv (snag (dec (lent pax)) pax))
[%c [%info %home %& [pax %ins %csv !>(file-content)]~]]
[%c [%info %base %& [pax %ins %csv !>(file-content)]~]]
::
--

View File

@ -4,16 +4,20 @@
|= [our=ship =desk now=@da]
~> %slog.0^leaf/"jamming desk {<desk>}"
%- jam
%- ?:(=(%base desk) remove-tmp-dir same)
%- ?:(=(%base desk) remove-misc-dirs same)
%- ankh-to-map
=< ank
.^(dome:clay %cv /(scot %p our)/[desk]/(scot %da now))
::
++ remove-tmp-dir
++ remove-misc-dirs
|= fiz=(map path page)
^- (map path page)
%- ~(gas by *(map path page))
(skip ~(tap by fiz) |=([p=path *] ?=([%tmp *] p)))
%+ skip ~(tap by fiz)
|= [p=path *]
?| ?=([%tmp *] p)
?=([%tests *] p)
==
::
++ ankh-to-map
=| res=(map path page)

View File

@ -4,7 +4,8 @@
=, format
=* dude dude:gall
|%
+$ state state-7
+$ state state-8
+$ state-8 [%8 pith-8]
+$ state-7 [%7 pith-7]
+$ state-6 [%6 pith-6]
+$ state-5 [%5 pith-5]
@ -15,7 +16,8 @@
+$ state-0 [%0 pith-0]
+$ any-state
$~ *state
$% state-7
$% state-8
state-7
state-6
state-5
state-4
@ -25,7 +27,7 @@
state-0
==
::
+$ pith-7
+$ pith-8
$: wef=(unit weft)
rem=(map desk per-desk) ::
syn=(map kiln-sync let=@ud) ::
@ -39,7 +41,35 @@
:: ensure they're unique even when the same
:: request is made multiple times.
hxs=(map desk @ud)
==
::
+$ pith-7
$: wef=(unit weft)
rem=(map desk per-desk) ::
syn=(map kiln-sync let=@ud) ::
ark=(map desk arak-7) ::
commit-timer=[way=wire nex=@da tim=@dr mon=term] ::
:: map desk to the currently ongoing fuse request
:: and the latest version numbers for beaks to
fus=(map desk per-fuse)
:: used for fuses - every time we get a fuse we
:: bump this. used when calculating hashes to
:: ensure they're unique even when the same
:: request is made multiple times.
hxs=(map desk @ud)
== ::
+$ arak-7
$: rail=(unit rail-7)
=rein
==
::
+$ rail-7
$: paused=?
=ship
=desk
=aeon
next=(list rung)
==
::
+$ pith-6
$: wef=(unit weft)
@ -262,8 +292,9 @@
%- emit
:^ %pass /kiln/permission %arvo
[%c %perm i.dez / %r `[%black ~]]
=? ..on-init !=(sop our)
abet:(install:vats i.dez sop i.dez)
=/ src (get-publisher our i.dez now)
=? ..on-init &(?=(^ src) !=(our u.src))
abet:(install:vats i.dez u.src i.dez)
$(dez t.dez)
::
++ on-load
@ -332,12 +363,24 @@
=- +.old(ark -)
%- ~(run by ark.old)
|= a=arak-6
^- arak
^- arak-7
:_ rein.a
^- (unit rail)
^- (unit rail-7)
`[paused.rail ship.rail desk.rail aeon.rail next]:a
::
?> ?=(%7 -.old)
=? old ?=(%7 -.old)
:- %8
=- +.old(ark -)
%- ~(gas by *(map desk arak))
%+ turn ~(tap by ark.old)
|= [d=desk a=arak-7]
^- [desk arak]
:- d
:_ rein.a
?~ rail.a ~
`[(get-publisher our d now) u.rail.a]
::
?> ?=(%8 -.old)
=. state old
::
=? kiln (lth old-version %7)
@ -347,7 +390,6 @@
=? kiln (lth old-version %7)
abet:gall-lyv:vats
=? kiln ?=(^ wef)
:: $% is a hack to workaround an initialization bug
=/ except=(set desk) (sy %base %kids ~)
(bump:vats u.wef except force=%.n)
=. wef ~
@ -493,7 +535,7 @@
=. rak (need got)
~> %slog.(fmt "already tracking {here:(abed lac)}, ignoring")
vats
=. rak [`[paused=| her rem *aeon next=~] rein:(fall got *arak)]
=. rak [`[~ paused=| her rem *aeon next=~] rein:(fall got *arak)]
~> %slog.(fmt "beginning install into {here}")
(emil find:pass listen:pass ~)
:: +install-local: install from a local desk, with no remote
@ -836,7 +878,11 @@
=< abet
=. vats (from-wire wire)
~> %slog.(fmt "commit detected at {here}")
=. rail.rak
?~ rail.rak ~
`[(get-publisher our loc now) +.u.rail.rak]
=. vats (emil listen:pass (diff:give %commit loc rak) ~)
?. liv.rein.rak
~> %slog.(fmt "{<loc>} not running")
vats

View File

@ -1303,7 +1303,7 @@
(sort ~(tap by van.mod) |=([[a=@tas *] [b=@tas *]] (aor a b)))
::
:~ :+ %reports %|
=/ bem=beam [[our %home da+now] /whey]
=/ bem=beam [[our %home da+now] /whey] ::TODO %base?
%+ turn von
|= [nam=term =vane]
=/ met (peek [~ ~] nam bem)

View File

@ -317,7 +317,10 @@
$>(%flog task:dill) ::
== ::
$: %g :: to %gall
$>(%deal task:gall) ::
$> $? %deal
%jolt
==
task:gall
== ::
$: %j :: by %jael
$>(%public-keys task:jael) ::
@ -344,7 +347,8 @@
gift ::
== ::
$: %gall
$> $? %unto
$> $? %onto
%unto
==
gift:gall
==
@ -1596,7 +1600,13 @@
++ migrate-dist
~> %slog.0^'clay: migrating for third-party software distribution'
|^ ^+ ..park
:: first make sure gall has molted and has :hood running
::
=. ..park (emit hen %pass /dist/hood %g %jolt %home %hood)
:: now ask :hood to install all the new desks
::
:: NOTE: reverse order, since we're prepending moves each time
::
=. ..park (install-from-tmp %bitcoin)
=. ..park (install-from-tmp %webterm)
=. ..park (install-from-tmp %landscape)
@ -1625,7 +1635,7 @@
++ create-desk ^- move
:^ hen %pass /dist/create/[desk]
%^ new-desk:cloy desk
(latest-tako desk)
(latest-tako %home)
;;((map path page) (cue (get-tmp-jam desk)))
::
++ publish-desk ^- move
@ -4803,6 +4813,8 @@
?^ dud
~|(%clay-take-dud (mean tang.u.dud))
?: ?=([%dist *] tea)
?: ?=(%onto +<.hin)
[~ ..^$]
?> ?=(%unto +<.hin)
?> ?=(%poke-ack -.p.hin)
?~ p.p.hin
@ -4962,6 +4974,7 @@
::
%boon !!
%lost !!
%onto !!
%unto !!
%writ
%- (slog leaf+"clay: strange writ (expected on upgrade to Fusion)" ~)

View File

@ -254,7 +254,6 @@
%- ~(urn by eggs.old)
|= [a=term e=egg]
::NOTE kiln will kick off appropriate app revival
?: =(%hood a) e(q.beak %base)
e(old-state [%| p.old-state.e])
+>.old
--
@ -387,13 +386,14 @@
=. mo-core (mo-abed system-duct.state)
::
=/ sources=(jug desk [care:clay path])
%+ ~(put by *(jug desk [care:clay path])) %home
%+ ~(put by *(jug desk [care:clay path])) %base
%- sy
:~ [%z /sys/hoon/hoon]
[%z /sys/arvo/hoon]
[%z /sys/lull/hoon]
[%z /sys/zuse/hoon]
[%z /sys/vane/gall/hoon]
[%z /sys/kelvin]
==
::
=. sources
@ -577,7 +577,7 @@
=/ nex=(list [=care:clay =path]) ~(tap in q.sign-arvo)
~> %slog.[0 leaf+"gall: reloading agents"]
~< %slog.[0 leaf+"gall: reloaded agents"]
=; cor (mo-subscribe-to-agent-builds:cor p.p.sign-arvo)
=; cor (mo-subscribe-to-agent-builds:cor now)
%+ roll nex
|= [[=care:clay =path] cor=_mo-core]
^+ cor
@ -596,8 +596,8 @@
?: ?=(%| -.agent.u.yok)
~> %slog.[0 leaf+"gall: dead agent reload: {<dap>}"]
cor
=/ bek=beak [our q.beak.u.yok p.sign-arvo]
=/ rag (mo-scry-agent-cage dap q.bek p.sign-arvo)
=/ bek=beak [our q.beak.u.yok da+now]
=/ rag (mo-scry-agent-cage dap q.bek da+now)
?: ?=(%| -.rag)
(mean p.rag)
(mo-receive-core:cor dap bek p.rag)

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bc01def532f4ba21029ced6132e0ccc6b187dffb75e8b542b2482704d58ef89c
size 3437512
oid sha256:3671bda05d32a7eaff82855fb629a8a8eb0db219ffa0cf3efdbe8866a04f7c0b
size 3440443

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9835f80c0d06712dead98bb58d8b1910a5ee03c60473b48de63f58ded179320f
size 460606
oid sha256:877de2dc23a9a5302aa3bb3f784e55c22c37b7aa90252f0d73ae3ba3df7cb1d1
size 461163

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a692eaeb7c0cf0b42ae535ae2d3624aa1744ad5af753987444a56394f06900c8
size 374578
oid sha256:3baad90b2de7ceb1c89d15e33e736ece8fb16318b144a7b717a1d29d6aec5d61
size 376408

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7e0034736055e6853d7c6341e1871b89c3d1f98092b766162c9fe1fa66e877db
size 1810260
oid sha256:3b44ae7a7ca5eb70cbcd17745ddf61ade28862e668080dd2f0edd71bcd9ef08c
size 1812454

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c54660b1712714a5008c33da8158247b2bf04a19668b7de12107ccadb52d84a7
size 305825
oid sha256:a9ce3350d300bb07aec52886c3c92c9766a4785c48d9e8db65690b0e8b90ef66
size 306379

View File

@ -44,7 +44,6 @@
/sur :: structures
/sys :: system files
/ted :: :spider strands
/tests :: unit tests
/web :: %eyre web content
/desk :: desk manifest
==

View File

@ -430,8 +430,10 @@
=/ m (strand ,cord)
^- form:m
?> ?=(%finished -.client-response)
?> ?=(^ full-file.client-response)
(pure:m q.data.u.full-file.client-response)
%- pure:m
?~ full-file.client-response ''
q.data.u.full-file.client-response
::
++ fetch-cord
|= url=tape

View File

@ -4,10 +4,17 @@
|%
++ noun s
++ json s+(scot %p s)
++ mime
^- ^mime
[/text/x-ship (as-octt:mimes:html (scow %p s))]
--
++ grab
|%
++ noun ship
++ json (su:dejs:format ;~(pfix sig fed:ag))
++ mime
|= [=mite len=@ tex=@]
(slav %p (snag 0 (to-wain:format tex)))
--
--

View File

@ -26,6 +26,7 @@
==
:: $rail: upstream tracking state
::
:: .publisher: Ship that originally published desk, if available
:: .paused: is tracking paused? or live
:: .ship: upstream ship (could be .our)
:: .desk: name of upstream desk
@ -33,7 +34,8 @@
:: .next: list of pending commits with future kelvins
::
+$ rail
$: paused=?
$: publisher=(unit ship)
paused=?
=ship
=desk
=aeon
@ -94,6 +96,7 @@
leaf/"force on: {?:(=(~ add.rein.arak) "~" <add.rein.arak>)}"
leaf/"force off: {?:(=(~ sub.rein.arak) "~" <sub.rein.arak>)}"
::
leaf/"publishing ship: {?~(rail.arak <~> <publisher.u.rail.arak>)}"
leaf/"updates: {poz}"
leaf/"source ship: {?~(rail.arak <~> <ship.u.rail.arak>)}"
leaf/"source desk: {?~(rail.arak <~> <desk.u.rail.arak>)}"
@ -105,6 +108,7 @@
++ read-kelvin-foreign
|= [=ship =desk =aeon]
^- weft
~| read-foreign-kelvin/+<
=/ her (scot %p ship)
=/ syd (scot %tas desk)
=/ yon (scot %ud aeon)
@ -186,6 +190,13 @@
=+ .^(her-hash=@uv cz/[(scot %p her) there (scot %ud when) ~])
!=(our-hash her-hash)
::
++ get-publisher
|= [our=ship =desk now=@da]
^- (unit ship)
=/ pax /(scot %p our)/[desk]/(scot %da now)/desk/ship
?. .^(? %cu pax) ~
`.^(ship %cx pax)
::
++ get-apps-live
|= [our=ship =desk now=@da]
^- (list dude)
@ -281,6 +292,7 @@
|= r=^rail
%- pairs
:~ ship+s+(scot %p ship.r)
publisher+?~(publisher.r ~ s+(scot %p u.publisher.r))
desk+s+desk.r
paused+b+paused.r
aeon+(numb aeon.r)

View File

@ -2,7 +2,7 @@
title+'Bitcoin'
info+'A Bitcoin Wallet that lets you send and receive Bitcoin directly to and from other Urbit users'
color+0xf9.8e40
glob-http+['https://bootstrap.urbit.org/glob-0v4.ghaim.of1as.9ucee.uj93f.a9nbs.glob' 0v4.ghaim.of1as.9ucee.uj93f.a9nbs]
glob-http+['https://bootstrap.urbit.org/glob-0v5.bt7ee.0scvi.e7na0.mhibg.97hvn.glob' 0v5.bt7ee.0scvi.e7na0.mhibg.97hvn]
image+'https://urbit.ewr1.vultrobjects.com/hastuc-dibtux/2021.8.24..02.57.38-bitcoin.svg'
base+'bitcoin'
version+[0 0 1]

1
pkg/bitcoin/desk.ship Normal file
View File

@ -0,0 +1 @@
~mister-dister-dozzod-dozzod

View File

@ -159,7 +159,7 @@ export const SettingsProvider: React.FC<Props> = ({ channel, children }) => {
const initializeSettings = () => {
let app = 'settings-store';
let path = `/bucket/${window.desk}btc-wallet`;
let path = `/bucket/${window.desk}/btc-wallet`;
fetch(`/~/scry/${app}${path}.json`)
.then((res) => res.json())

View File

@ -100,7 +100,7 @@
%site (spud path.clause)
::
%glob-http
"[{(trip url.clause)} {(scow %uv hash.clause)}]"
"['{(trip url.clause)}' {(scow %uv hash.clause)}]"
::
%glob-ames
"[{(scow %p ship.clause)} {(scow %uv hash.clause)}]"

View File

@ -236,7 +236,7 @@
=. 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))
?: &(?=(^ 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)
@ -677,7 +677,10 @@
(poke-our:(pass (glob-wire ref)) %spider cage)
==
++ docket-loc `path`/desk/docket-0
++ docket-exists .^(? %cu (scry:io desk docket-loc))
++ docket-exists
?: =(0 ud:.^(cass:clay %cw (scry:io desk ~))) %.n
.^(? %cu (scry:io desk docket-loc))
::
++ docket .^(^docket %cx (scry:io desk docket-loc))
--
--

View File

@ -71,7 +71,7 @@
=* state -
::
=<
%+ verb &
%+ verb |
%- agent:dbug
^- agent:gall
~% %hark-store-agent ..card ~

View File

@ -6,7 +6,7 @@
::
++ lag-interval ~m10
--
%+ verb &
%+ verb |
%- agent:dbug
^- agent:gall
=| state-0

View File

@ -39,7 +39,7 @@
|-
?- -.old
%0 $(old [%1 +.old])
%1 $(old [%2 (~(put by *^settings) q.byk.bol settings.old)])
%1 $(old [%2 (~(put by *^settings) %landscape settings.old)])
%2 `this(state old)
==
::

View File

@ -1,8 +1,7 @@
/- docket, *treaty
/+ default-agent, agentio, verb, dbug
|%
:: TODO: update before livenet deploy
++ default-ally ~zod
++ default-ally ~dister-dozzod-dozzod
::
+$ card card:agent:gall
+$ state-0
@ -14,7 +13,7 @@
==
--
^- agent:gall
%+ verb &
%+ verb |
%- agent:dbug
=| state-0
=* state -
@ -197,7 +196,14 @@
++ take-treaty
|= =desk
?+ -.sign (on-agent:def wire sign)
%kick :_(this ~[~(watch tr:cc ship desk)])
::
:: rewatch only if we aren't source
:: this would cause a potential kick-rewatch loop otherwise
::
%kick
:_ this
?: =(our.bowl src.bowl) ~
~(watch tr:cc ship desk)^~
::
%watch-ack
?~ p.sign `this
@ -205,7 +211,8 @@
direct (~(del in direct) ship desk)
==
%- (slog leaf+"Withdrew from treaty {<ship>}/{<desk>}" u.p.sign)
`this
:_ this
(kick-only:io our.bowl /treaty/(scot %p ship)/[desk] ~)^~
::
%fact
?. =(%treaty-0 p.cage.sign) `this
@ -289,7 +296,7 @@
++ dock [ship dap.bowl]
++ watch (watch:pass dock path)
++ watching (~(has by wex.bowl) [path dock])
++ safe-watch `(unit card)`?:(watching ~ `watch)
++ safe-watch `(unit card)`?:(|(watching =(our.bowl ship)) ~ `watch)
++ leave (leave:pass dock)
++ give
=/ t=treaty (~(got by treaties) ship desk)

View File

@ -1,7 +1,7 @@
:~ title+'System'
info+'An app launcher for Urbit.'
color+0xee.5432
glob-http+['https://bootstrap.urbit.org/glob-0v6.lum6t.bgb7b.7hm52.vdr84.3dlpv.glob' 0v6.lum6t.bgb7b.7hm52.vdr84.3dlpv]
glob-http+['https://bootstrap.urbit.org/glob-0v6.l4fil.upa5d.0ak43.aqhsq.l99o4.glob' 0v6.l4fil.upa5d.0ak43.aqhsq.l99o4]
::glob-ames+~zod^0v0
base+'grid'
version+[0 0 1]

1
pkg/garden/desk.ship Normal file
View File

@ -0,0 +1 @@
~mister-dister-dozzod-dozzod

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,7 @@
"@types/react-router-dom": "^5.1.8",
"@typescript-eslint/eslint-plugin": "^4.26.1",
"@typescript-eslint/parser": "^4.26.1",
"@urbit/vite-plugin-urbit": "^0.5.1",
"@urbit/vite-plugin-urbit": "^0.6.0",
"@vitejs/plugin-react-refresh": "^1.3.1",
"autoprefixer": "^10.3.1",
"eslint": "^7.28.0",

View File

@ -50,6 +50,7 @@ function getRemoteDesk(docket: App, vat?: Vat) {
export const AppInfo: FC<AppInfoProps> = ({ docket, vat, className }) => {
const installStatus = getInstallStatus(docket);
const [ship, desk] = getRemoteDesk(docket, vat);
const publisher = vat?.arak?.rail?.publisher ?? ship;
const [copied, setCopied] = useState(false);
const installApp = async () => {
@ -61,12 +62,12 @@ export const AppInfo: FC<AppInfoProps> = ({ docket, vat, className }) => {
const copyApp = useCallback(() => {
setCopied(true);
clipboardCopy(`web+urbitgraph://${ship}/${desk}`);
clipboardCopy(`web+urbitgraph://${publisher}/${desk}`);
setTimeout(() => {
setCopied(false);
}, 1250);
}, []);
}, [publisher, desk]);
const installing = installStatus === 'installing';

View File

@ -16,7 +16,7 @@ function renderNotification(notification: Notification, key: string, lid: HarkLi
return <BaseBlockedNotification key={key} />;
}
if (notification.bin.place.path === '/onboard') {
return <OnboardingNotification key={key} unread={false} />;
return <OnboardingNotification key={key} lid={lid} />;
}
}
return <BasicNotification key={key} notification={notification} lid={lid} />;

View File

@ -1,56 +1,76 @@
import React from 'react';
import cn from 'classnames';
import { Link } from 'react-router-dom';
import { HarkLid, Vats, getVatPublisher } from '@urbit/api';
import { Button } from '../../components/Button';
import { useCurrentTheme } from '../../state/local';
import { useCurrentTheme, useProtocolHandling } from '../../state/local';
import { getDarkColor } from '../../state/util';
import useKilnState from '../../state/kiln';
import {useHarkStore} from '../../state/hark';
const cards: OnboardingCardProps[] = [
{
title: 'Terminal',
body: "A web interface to your Urbit's command line (the dojo).",
button: 'Install',
color: '#9CA4B1',
href: '/leap/search/direct/apps/~zod/webterm'
},
{
title: 'Groups',
body: 'A suite of applications to communicate on Urbit',
button: 'Install',
color: '#D1DDD3',
href: '/leap/search/direct/apps/~zod/landscape'
},
{
title: 'Bitcoin',
body: ' A Bitcoin Wallet that lets you send and receive Bitcoin directly to and from other Urbit users',
button: 'Install',
color: '#F6EBDB',
href: '/leap/search/direct/apps/~zod/bitcoin'
const getCards = (vats: Vats, protocol: boolean): OnboardingCardProps[] => {
const cards = [
{
title: 'Terminal',
body: "A web interface to your Urbit's command line (the dojo).",
button: 'Install',
color: '#9CA4B1',
href: '/leap/search/direct/apps/~mister-dister-dozzod-dozzod/webterm',
ship: '~mister-dister-dozzod-dozzod',
desk: 'webterm'
},
{
title: 'Groups',
body: 'A suite of applications to communicate on Urbit',
button: 'Install',
color: '#D1DDD3',
href: '/leap/search/direct/apps/~lander-dister-dozzod-dozzod/landscape',
ship: '~lander-dister-dozzod-dozzod',
desk: 'landscape'
},
{
title: 'Bitcoin',
body: ' A Bitcoin Wallet that lets you send and receive Bitcoin directly to and from other Urbit users',
button: 'Install',
color: '#F6EBDB',
href: '/leap/search/direct/apps/~mister-dister-dozzod-dozzod/bitcoin',
ship: '~mister-dister-dozzod-dozzod',
desk: 'bitcoin'
}
// Commenting out until we have something real
// {
// title: 'Debug',
// body: "Install a debugger. You can inspect your ship's internals using this interface",
// button: 'Install',
// color: '#E5E5E5',
// href: '/leap/search/direct/apps/~zod/debug'
// }
// {
// title: 'Build an app',
// body: 'You can instantly get started building new things on Urbit. Just right click your Landscape and select “New App”',
// button: 'Learn more',
// color: '#82A6CA'
// }
];
if('registerProtocolHandler' in window.navigator && !protocol) {
cards.push({
title: 'Open Urbit-Native Links',
body: 'Enable your Urbit to open links you find in the wild',
button: 'Enable Link Handler',
color: '#82A6CA',
href: '/leap/system-preferences/interface',
desk: '',
ship: ''
});
}
// Commenting out until we have something real
// {
// title: 'Debug',
// body: "Install a debugger. You can inspect your ship's internals using this interface",
// button: 'Install',
// color: '#E5E5E5',
// href: '/leap/search/direct/apps/~zod/debug'
// }
// {
// title: 'Build an app',
// body: 'You can instantly get started building new things on Urbit. Just right click your Landscape and select “New App”',
// button: 'Learn more',
// color: '#82A6CA'
// }
];
return cards.filter(card => {
return !Object.values(vats).find(vat => getVatPublisher(vat) == card.ship && vat?.arak?.rail?.desk === card.desk);
});
};
if ('registerProtocolHandler' in window.navigator) {
cards.push({
title: 'Open Urbit-Native Links',
body: 'Enable your Urbit to open links you find in the wild',
button: 'Enable Link Handler',
color: '#82A6CA',
href: '/leap/system-preferences/interface'
});
}
interface OnboardingCardProps {
@ -59,6 +79,8 @@ interface OnboardingCardProps {
href: string;
body: string;
color: string;
ship: string;
desk: string;
}
const OnboardingCard = ({ title, button, href, body, color }: OnboardingCardProps) => (
@ -77,11 +99,27 @@ const OnboardingCard = ({ title, button, href, body, color }: OnboardingCardProp
);
interface OnboardingNotificationProps {
unread: boolean;
unread?: boolean;
lid: HarkLid;
}
export const OnboardingNotification = ({ unread }: OnboardingNotificationProps) => {
export const OnboardingNotification = ({ unread = false, lid }: OnboardingNotificationProps) => {
const theme = useCurrentTheme();
const vats = useKilnState((s) => s.vats);
const protocolHandling = useProtocolHandling();
const cards = getCards(vats, protocolHandling);
if(cards.length === 0 && !('time' in lid)) {
useHarkStore.getState().archiveNote({
path: '/',
place: {
path: '/onboard',
desk: window.desk
}
}, lid);
return null;
}
return (
<section

View File

@ -64,7 +64,7 @@ function AppLinkRedirect({ desk, link }: { desk: string; link: string }) {
}
const LANDSCAPE_DESK = 'landscape';
const LANDSCAPE_HOST = '~zod';
const LANDSCAPE_HOST = '~lander-dister-dozzod-dozzod';
function LandscapeLink({ match }: RouteComponentProps<{ link: string }>) {
const { link } = match.params;

View File

@ -348,6 +348,7 @@ export const mockVat = (desk: string, blockers?: boolean): Vat => ({
: {
aeon: 3,
desk,
publisher: '~zod',
next: blockers ? [{ aeon: 3, weft: { name: 'zuse', kelvin: 419 } }] : [],
ship: '~zod',
paused: desk === 'groups'

View File

@ -59,7 +59,7 @@ export const Tile: FunctionComponent<TileProps> = ({ charge, desk }) => {
)}
<TileMenu
desk={desk}
active={active}
chad={chad}
menuColor={active ? menuColor : suspendMenuColor}
lightText={lightText}
className="absolute z-10 top-3 right-3 sm:top-5 sm:right-5 opacity-0 pointer-coarse:opacity-100 hover-none:opacity-100 focus:opacity-100 group-hover:opacity-100"

View File

@ -3,6 +3,7 @@ import type * as Polymorphic from '@radix-ui/react-polymorphic';
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import classNames from 'classnames';
import { Link } from 'react-router-dom';
import { Chad, chadIsRunning } from '@urbit/api';
import useDocketState from '../state/docket';
import { disableDefault, handleDropdownLink } from '../state/util';
@ -10,7 +11,7 @@ export interface TileMenuProps {
desk: string;
lightText: boolean;
menuColor: string;
active: boolean;
chad: Chad;
className?: string;
}
@ -37,11 +38,13 @@ const Item = React.forwardRef(({ children, ...props }, ref) => (
</DropdownMenu.Item>
)) as ItemComponent;
export const TileMenu = ({ desk, active, menuColor, lightText, className }: TileMenuProps) => {
export const TileMenu = ({ desk, chad, menuColor, lightText, className }: TileMenuProps) => {
const [open, setOpen] = useState(false);
const toggleDocket = useDocketState((s) => s.toggleDocket);
const menuBg = { backgroundColor: menuColor };
const linkOnSelect = useCallback(handleDropdownLink(setOpen), []);
const active = chadIsRunning(chad);
const suspended = 'suspend' in chad;
return (
<DropdownMenu.Root open={open} onOpenChange={(isOpen) => setOpen(isOpen)}>
@ -80,7 +83,7 @@ export const TileMenu = ({ desk, active, menuColor, lightText, className }: Tile
Suspend App
</Item>
)}
{!active && <Item onSelect={() => toggleDocket(desk)}>Resume App</Item>}
{suspended && <Item onSelect={() => toggleDocket(desk)}>Resume App</Item>}
<Item as={Link} to={`/app/${desk}/remove`} onSelect={linkOnSelect}>
Remove App
</Item>

View File

@ -1,5 +1,5 @@
import { BaseState } from '../state/base';
import { GroupState as State } from '../state/group';
import useGroupState, { GroupState as State } from '../state/group';
type GroupState = State & BaseState<State>;
@ -27,7 +27,9 @@ const progress = (json: any, state: GroupState): GroupState => {
state.pendingJoin[resource].progress = progress;
if(progress === 'done') {
setTimeout(() => {
delete state.pendingJoin[resource];
useGroupState.getState().set((state) => {
delete state.pendingJoin[resource];
});
}, 10000);
}
}

View File

@ -1,4 +1,4 @@
import { Association, Group, JoinRequests } from '@urbit/api';
import { Association, Group, hideGroup, JoinRequests } from '@urbit/api';
import { useCallback } from 'react';
import { reduce } from '../reducers/group-update';
import _ from 'lodash';
@ -8,21 +8,29 @@ import {
createSubscription,
reduceStateN
} from './base';
import api from '~/logic/api';
export interface GroupState {
groups: {
[group: string]: Group;
};
pendingJoin: JoinRequests;
hidePending: (group: string) => Promise<void>;
}
// @ts-ignore investigate zustand types
const useGroupState = createState<GroupState>(
'Group',
{
(set, get) => ({
groups: {},
pendingJoin: {}
},
pendingJoin: {},
hidePending: async (group) => {
get().set((draft) => {
delete draft.pendingJoin[group];
});
await api.poke(hideGroup(group));
}
}),
['groups'],
[
(set, get) =>

View File

@ -206,7 +206,7 @@ export const LaunchApp = (props: LaunchAppProps): ReactElement | null => {
color="black"
text="Join Group"
>
<JoinGroup />
{dismiss => <JoinGroup dismiss={dismiss} />}
</ModalButton>
</>}
{!hideGroups &&

View File

@ -1,20 +1,19 @@
import { LoadingSpinner } from "@tlon/indigo-react";
import React, { useState } from "react";
import { Box, Row, Col, Text } from "@tlon/indigo-react";
import { PropFunc } from "~/types";
import _ from "lodash";
import * as Dialog from "@radix-ui/react-dialog";
import { StatusBarItem } from "./StatusBarItem";
import useGroupState from "~/logic/state/group";
import { JoinRequest, joinProgress } from "@urbit/api";
import { usePreview } from "~/logic/state/metadata";
import { Dropdown } from "./Dropdown";
import { MetadataIcon } from "../landscape/components/MetadataIcon";
import { LoadingSpinner, Button } from '@tlon/indigo-react';
import React from 'react';
import { Box, Row, Col, Text } from '@tlon/indigo-react';
import { PropFunc } from '~/types';
import _ from 'lodash';
import { StatusBarItem } from './StatusBarItem';
import useGroupState from '~/logic/state/group';
import { JoinRequest, joinProgress } from '@urbit/api';
import { usePreview } from '~/logic/state/metadata';
import { Dropdown } from './Dropdown';
import { MetadataIcon } from '../landscape/components/MetadataIcon';
function Elbow(
props: { size?: number; color?: string } & PropFunc<typeof Box>
) {
const { size = 12, color = "lightGray", ...rest } = props;
const { size = 12, color = 'lightGray', ...rest } = props;
return (
<Box
@ -39,10 +38,9 @@ function Elbow(
}
export function StatusBarJoins() {
const pendingJoin = useGroupState((s) => s.pendingJoin);
const [isOpen, setIsOpen] = useState(false);
const pendingJoin = useGroupState(s => s.pendingJoin);
if (
Object.keys(_.omitBy(pendingJoin, (j) => j.progress === "done")).length ===
Object.keys(_.omitBy(pendingJoin, j => j.progress === 'done')).length ===
0
) {
return null;
@ -50,25 +48,24 @@ export function StatusBarJoins() {
return (
<Dropdown
dropWidth="256px"
dropWidth="325px"
options={
<Col
left="0px"
top="120%"
position="absolute"
zIndex={10}
alignItems="center"
alignItems="flex-start"
p="2"
gapY="4"
gapY="3"
border="1"
borderColor="lightGray"
borderRadius="1"
backgroundColor="white"
>
<Col>
{Object.keys(pendingJoin).map((g) => (
{Object.keys(pendingJoin).map(g => (
<JoinStatus key={g} group={g} join={pendingJoin[g]} />
))}
</Col>
</Col>
}
alignX="left"
@ -82,24 +79,28 @@ export function StatusBarJoins() {
}
const description: string[] = [
"Contacting host...",
"Retrieving data...",
"Finished join",
"Unable to join, you do not have the correct permissions",
"Internal error, please file an issue",
'Contacting host...',
'Retrieving data...',
'Finished join',
'Unable to join, you do not have the correct permissions',
'Internal error, please file an issue'
];
export function JoinStatus({
group,
join,
join
}: {
group: string;
join: JoinRequest;
}) {
const { preview, error } = usePreview(group);
const { preview } = usePreview(group);
const current = join && joinProgress.indexOf(join.progress);
const desc = _.isNumber(current) && description[current];
const onHide = () => {
useGroupState.getState().hidePending(group);
};
return (
<Row alignItems="center" gapX="3">
<Col gapY="2">
<Row alignItems="center" gapX="2">
{preview ? (
@ -112,5 +113,9 @@ export function JoinStatus({
<Text>{desc}</Text>
</Row>
</Col>
<Button onClick={onHide}>
Hide
</Button>
</Row>
);
}

View File

@ -94,6 +94,10 @@ function getDmRedirect(link: string) {
const [,,ship] = link.split('/');
return `/~landscape/messages/dm/${ship}`;
}
function getGroupRedirect(link: string) {
const [,,ship,name] = link.split('/');
return `/~landscape/ship/${ship}/${name}`;
}
function getNotificationRedirect(link: string) {
if(link.startsWith('/graph-validator')) {
@ -102,6 +106,8 @@ function getNotificationRedirect(link: string) {
return getInviteRedirect(link);
} else if (link.startsWith('/dm')) {
return getDmRedirect(link);
} else if (link.startsWith('/groups')) {
return getGroupRedirect(link);
}
}

View File

@ -1,8 +1,9 @@
import {
Box, Col,
Icon,
ManagedTextInputField as Input, Row,
Text
Box, Col,
Icon,
ManagedTextInputField as Input, Row,
Text,
Button
} from '@tlon/indigo-react';
import { join, MetadataUpdatePreview } from '@urbit/api';
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
@ -42,6 +43,7 @@ interface FormSchema {
interface JoinGroupProps {
autojoin?: string;
dismiss?: () => void;
}
function Autojoin(props: { autojoin: string | null }) {
@ -57,8 +59,9 @@ function Autojoin(props: { autojoin: string | null }) {
}
export function JoinGroup(props: JoinGroupProps): ReactElement {
const { autojoin } = props;
const { autojoin, dismiss } = props;
const { associations, getPreview } = useMetadataState();
const [timedOut, setTimedOut] = useState(false);
const groups = useGroupState(state => state.groups);
const history = useHistory();
const initialValues: FormSchema = {
@ -104,6 +107,7 @@ export function JoinGroup(props: JoinGroupProps): ReactElement {
history.push(`/~landscape${group}`);
}
} catch (e) {
setTimedOut(true);
console.error(e);
}
}, [waiter, history, associations, groups]);
@ -143,7 +147,17 @@ export function JoinGroup(props: JoinGroupProps): ReactElement {
Join a Group
</Text>
</Box>
{_.isString(preview) ? (
{ timedOut ? (
<Col width="100%" gapY={4}>
<Text>The host is not responding. You will receive a notification when the join requests succeeds
</Text>
<Button primary onClick={dismiss}>
Dismiss
</Button>
</Col>
) : _.isString(preview) ? (
<Col width="100%" gapY={4}>
<Text>The host appears to be offline. Join anyway?</Text>
<StatelessAsyncButton

View File

@ -1,4 +1,4 @@
/- view-sur=group-view, group-store, *group, metadata=metadata-store
/- view-sur=group-view, group-store, *group, metadata=metadata-store, hark=hark-store
/+ default-agent, agentio, mdl=metadata,
resource, dbug, grpl=group, conl=contact, verb
|%
@ -327,13 +327,66 @@
%- (slog u.err)
(cleanup %strange)
::
++ notify
%- emit
%+ poke-our:(jn-pass-io /hark) %hark-store
=- hark-action+!>(-)
^- action:hark
|^
[%add-note bin body]
++ bin
^- bin:hark
[/ [q.byk.bowl /join/(scot %p entity.rid)/[name.rid]]]
++ title
|= [name=@t rest=@t]
text/(rap 3 'Joining group: "' name '" ' rest ~)
++ body
^- body:hark
=/ =request:view (~(got by joining) rid)
?> ?=(final:view progress.request)
=/ name (rap 3 (scot %p entity.rid) '/' name.rid ~)
?- progress.request
::
%done
=/ =metadatum:metadata (need (peek-metadatum:met %groups rid))
:* ~[(title title.metadatum 'succeeded')]
~
now.bowl
/
/groups/(scot %p entity.rid)/[name.rid]
==
::
%strange
:* ~[(title name 'errored unexpectedly')]
~
now.bowl
/
/
==
::
%no-perms
:* ~[(title name 'failed, you are not permitted to join the group')]
~
now.bowl
/
/
==
==
--
::
++ cleanup
|= =progress:view
=. jn-core
(tx-progress progress)
=. jn-core
(emit (leave-our:(jn-pass-io /groups) %group-store))
(emit (leave-our:(jn-pass-io /md) %metadata-store))
=. jn-core
(emit (leave-our:(jn-pass-io /md) %metadata-store))
=/ =request:view (~(got by joining) rid)
=? jn-core (lte (sub now.bowl started.request) ~s30)
notify
=. joining (~(del by joining) rid)
jn-core
--
--
--

View File

@ -10,11 +10,8 @@
$: blocked=(jug resource [uid=serial:invite =invite:invite])
~
==
--
%+ verb &
%+ verb |
%- agent:dbug
^- agent:gall
=| state-0

View File

@ -1,7 +1,7 @@
:~ title+'Groups'
info+'A suite of applications to communicate on Urbit'
color+0xee.5432
glob-http+['https://bootstrap.urbit.org/glob-0v3.odd1i.nkejh.s9h63.apm7g.da8qe.glob' 0v3.odd1i.nkejh.s9h63.apm7g.da8qe]
glob-http+['https://bootstrap.urbit.org/glob-0v7.5oj2f.78bi6.enb3s.o2ji8.l4366.glob' 0v7.5oj2f.78bi6.enb3s.o2ji8.l4366]
base+'landscape'
version+[1 3 5]
website+'https://tlon.io'

1
pkg/landscape/desk.ship Normal file
View File

@ -0,0 +1 @@
~lander-dister-dozzod-dozzod

View File

@ -0,0 +1,12 @@
|_ ver=@ud
++ grad %noun
++ grow
|%
++ noun ver
++ json (numb:enjs:format ver)
--
++ grab
|%
++ noun @ud
--
--

View File

@ -1,5 +1,5 @@
import { Poke, Scry } from '../lib';
import { Vats } from './types';
import { Vats, Vat } from './types';
import _ from 'lodash';
export const getVats: Scry = {
@ -108,3 +108,11 @@ export function getBlockers(vats: Vats): string[] {
return blockers;
}
export function getVatPublisher(vat: Vat): string | undefined {
if (vat.arak.rail) {
const { rail } = vat.arak;
return (rail?.publisher || rail?.ship || undefined);
}
return undefined;
}

View File

@ -19,6 +19,10 @@ interface Rein {
}
export interface Rail {
/**
* Original publisher of desk, if available
*/
publisher: string | null;
/**
* Ship of foreign vat
*/

View File

@ -1,7 +1,7 @@
:~ title+'Terminal'
info+'A web interface to your Urbit\'s command line (the dojo).'
color+0x2e.4347
glob-http+['https://bootstrap.urbit.org/glob-0v4.8ui32.ui10d.t0v4d.n9g1s.1ftua.glob' 0v4.8ui32.ui10d.t0v4d.n9g1s.1ftua]
glob-http+['https://bootstrap.urbit.org/glob-0v6.ak34j.nao8k.dhqs4.s2atf.td1lc.glob' 0v6.ak34j.nao8k.dhqs4.s2atf.td1lc]
base+'webterm'
version+[0 0 1]
website+'https://tlon.io'

1
pkg/webterm/desk.ship Normal file
View File

@ -0,0 +1 @@
~mister-dister-dozzod-dozzod