Merge branch 'master' into langserver-rpc-rewrite

This commit is contained in:
Liam Fitzgerald 2020-01-27 12:11:19 +10:00
commit 3c74888c9d
148 changed files with 1098 additions and 1894 deletions

View File

@ -10,7 +10,7 @@ A personal server operating function.
[azim]: https://etherscan.io/address/0x223c067f8cf28ae173ee5cafea60ca44c335fecb
[aens]: https://etherscan.io/address/azimuth.eth
[brid]: https://github.com/urbit/bridge/releases
[brid]: https://github.com/urbit/bridge
[arvo]: https://github.com/urbit/urbit/tree/master/pkg/arvo
## Install

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:23ec7d497dd53f180b8753bd196f92695c7d60dad52f2b57061fc8642cdae4e2
size 9645510
oid sha256:e6232e5bcb64be057ccd9b4c23bbd636814d50778e4f3a01fbf2ee0042fe3d44
size 9635072

View File

@ -256,8 +256,8 @@
%- zing
%+ turn ufs
|= uf=unix-effect
:~ [%give %fact `/effect %aqua-effect !>(`aqua-effect`[ship uf])]
[%give %fact `/effect/[-.q.uf] %aqua-effect !>(`aqua-effect`[ship uf])]
:~ [%give %fact ~[/effect] %aqua-effect !>(`aqua-effect`[ship uf])]
[%give %fact ~[/effect/[-.q.uf]] %aqua-effect !>(`aqua-effect`[ship uf])]
==
::
=. this
@ -265,7 +265,7 @@
%- emit-cards
%+ turn ~(tap by unix-effects)
|= [=ship ufs=(list unix-effect)]
[%give %fact `path %aqua-effects !>(`aqua-effects`[ship (flop ufs)])]
[%give %fact ~[path] %aqua-effects !>(`aqua-effects`[ship (flop ufs)])]
::
=. this
%- emit-cards
@ -275,28 +275,28 @@
=/ =path /effect/(scot %p ship)
%+ turn ufs
|= uf=unix-effect
[%give %fact `path %aqua-effect !>(`aqua-effect`[ship uf])]
[%give %fact ~[path] %aqua-effect !>(`aqua-effect`[ship uf])]
::
=. this
%- emit-cards
%+ turn ~(tap by unix-effects)
|= [=ship ufs=(list unix-effect)]
=/ =path /effects/(scot %p ship)
[%give %fact `path %aqua-effects !>(`aqua-effects`[ship (flop ufs)])]
[%give %fact ~[path] %aqua-effects !>(`aqua-effects`[ship (flop ufs)])]
::
=. this
%- emit-cards
%+ turn ~(tap by unix-events)
|= [=ship ve=(list unix-timed-event)]
=/ =path /events/(scot %p ship)
[%give %fact `path %aqua-events !>(`aqua-events`[ship (flop ve)])]
[%give %fact ~[path] %aqua-events !>(`aqua-events`[ship (flop ve)])]
::
=. this
%- emit-cards
%+ turn ~(tap by unix-boths)
|= [=ship bo=(list unix-both)]
=/ =path /boths/(scot %p ship)
[%give %fact `path %aqua-boths !>(`aqua-boths`[ship (flop bo)])]
[%give %fact ~[path] %aqua-boths !>(`aqua-boths`[ship (flop bo)])]
::
[(flop cards) all-state]
::

View File

@ -78,8 +78,8 @@
?~ udiffs
~
=/ =path /(scot %p ship.i.udiffs)
:* [%give %fact `/ %azimuth-udiff !>(i.udiffs)]
[%give %fact `path %azimuth-udiff !>(i.udiffs)]
:* [%give %fact ~[/] %azimuth-udiff !>(i.udiffs)]
[%give %fact ~[path] %azimuth-udiff !>(i.udiffs)]
$(udiffs t.udiffs)
==
::

View File

@ -122,7 +122,7 @@
?- -.sign
%poke-ack [- all-state]:(on-agent:def wire sign)
%watch-ack [- all-state]:(on-agent:def wire sign)
%kick [?:(?=([%chat-store ~] wire) ~[connect] ~) all-state]
%kick [?:(?=([%chat-store ~] wire) ~[connect:tc] ~) all-state]
%fact
?+ p.cage.sign ~|([%chat-cli-bad-sub-mark wire p.cage.sign] !!)
%chat-update (diff-chat-update:tc wire !<(chat-update q.cage.sign))
@ -1044,7 +1044,7 @@
|= fec=sole-effect:sole-sur
^- card
::TODO don't hard-code session id 'drum' here
[%give %fact `/sole/drum %sole-effect !>(fec)]
[%give %fact ~[/sole/drum] %sole-effect !>(fec)]
:: +tab: print tab-complete list
::
++ tab

View File

@ -77,7 +77,7 @@
?+ -.sign (on-agent:def wire sign)
%watch-ack
=^ cards state
(watch-ack:cc wire p.sign)
(watch-ack:cc wire p.sign)
[cards this]
::
%kick
@ -186,7 +186,7 @@
:~ (pull-wire [%backlog (weld path.act /0)])
(pull-wire [%mailbox path.act])
(delete-permission [%chat path.act])
[%give %kick `[%mailbox path.act] ~]~
[%give %kick [%mailbox path.act]~ ~]~
==
?. |(=(u.ship src.bol) (team:title our.bol src.bol))
:: if neither ship = source or source = us, do nothing
@ -229,7 +229,7 @@
?: ?&(?=(^ backlog-start) (~(got by allow-history) pas))
(paginate-messages pas u.box u.backlog-start)
~
[%give %kick `[%backlog pax] `src.bol]~
[%give %kick [%backlog pax]~ `src.bol]~
==
::
++ paginate-messages
@ -302,7 +302,7 @@
:: if ship is not permitted, kick their subscription
=/ mail-path
(oust [(dec (lent t.pax)) (lent t.pax)] `(list @t)`t.pax)
[%give %kick `[%mailbox mail-path] `ship]~
[%give %kick [%mailbox mail-path]~ `ship]~
::
++ fact-chat-update
|= [wir=wire fact=chat-update]
@ -327,11 +327,11 @@
::
%message
:_ state
[%give %fact `[%mailbox path.fact] %chat-update !>(fact)]~
[%give %fact [%mailbox path.fact]~ %chat-update !>(fact)]~
::
%messages
:_ state
[%give %fact `[%mailbox path.fact] %chat-update !>(fact)]~
[%give %fact [%mailbox path.fact]~ %chat-update !>(fact)]~
==
::
++ handle-foreign

View File

@ -245,7 +245,7 @@
++ update-subscribers
|= [pax=path update=chat-update]
^- (list card)
[%give %fact `pax %chat-update !>(update)]~
[%give %fact ~[pax] %chat-update !>(update)]~
::
++ send-diff
|= [pax=path upd=chat-update]

View File

@ -137,7 +137,7 @@
==
==
::
++ on-arvo
++ on-arvo
|= [=wire =sign-arvo]
^- (quip card _this)
?. ?=(%bound +<.sign-arvo)
@ -176,7 +176,7 @@
=/ pax t.t.t.t.site.url
=/ envelopes (envelope-scry [(scot %ud start) (scot %ud end) pax])
%- json-response:gen
%- json-to-octs
%- json-to-octs
%- update-to-json
[%messages pax start end envelopes]
::
@ -239,8 +239,8 @@
^- (list card)
=/ updates-json (update-to-json upd)
=/ configs-json (configs-to-json configs-scry)
:~ [%give %fact `/primary %json !>(updates-json)]
[%give %fact `/configs %json !>(configs-json)]
:~ [%give %fact ~[/primary] %json !>(updates-json)]
[%give %fact ~[/configs] %json !>(configs-json)]
==
::
:: +utilities

File diff suppressed because one or more lines are too long

View File

@ -12,12 +12,12 @@
<link rel="stylesheet" href="/~chat/css/index.css" />
<link rel="icon" type="image/png" href="/~launch/img/Favicon.png">
<link rel="manifest"
href='data:application/manifest+json,{
"name": "Chat",
"short_name": "Chat",
"description": "A%20Chat%20application%20for%20your%20Urbit%20ship.",
"display": "standalone",
"background_color": "%23FFFFFF",
href='data:application/manifest+json,{
"name": "Chat",
"short_name": "Chat",
"description": "A%20Chat%20application%20for%20your%20Urbit%20ship.",
"display": "standalone",
"background_color": "%23FFFFFF",
"theme_color": "%23000000"}' />
</head>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,7 +28,7 @@
++ give-result
|= [=the=path =cage]
^- card
[%give %fact `the-path cage]
[%give %fact ~[the-path] cage]
--
::
^- agent:gall

View File

@ -538,7 +538,7 @@
$poke
%- he-card(poy ~)
:* %pass
/poke
/poke
%agent
p.p.mad
%poke
@ -830,7 +830,7 @@
++ he-diff :: emit update
|= fec/sole-effect
^+ +>
(he-card %give %fact `/sole/[id] %sole-effect !>(fec))
(he-card %give %fact ~[/sole/[id]] %sole-effect !>(fec))
::
++ he-stop :: abort work
^+ .
@ -1141,11 +1141,11 @@
:: If couldn't search (eg cursor not in appropriate position), do
:: nothing.
::
?: ?=(~ tl)
?: ?=(~ tl)
res
:: If no options, ring the bell
::
?: =([~ ~] tl)
?: =([~ ~] tl)
(he-diff %bel ~)
:: If only one option, don't print unless the option is already
:: typed in.

View File

@ -337,7 +337,7 @@
:_ dog(history actual-history)
%+ turn actual-vows
|= =id:block
[%give %fact `[%logs path] %eth-watcher-diff !>([%disavow id])]
[%give %fact [%logs path]~ %eth-watcher-diff !>([%disavow id])]
::
++ release-logs
|= [=path dog=watchdog]
@ -362,7 +362,7 @@
%+ turn loglist
|= =event-log:rpc:ethereum
^- card
[%give %fact `[%logs path] %eth-watcher-diff !>([%log event-log])]
[%give %fact [%logs path]~ %eth-watcher-diff !>([%log event-log])]
=^ cards-2 dog $(numbers t.numbers)
[(weld cards-1 cards-2) dog]
--

View File

@ -126,7 +126,7 @@
:_ state(synced (~(del by synced.state) path.act))
%+ snoc
(pull-wire group-wire path.act)
[%give %kick `[%group path.act] ~]
[%give %kick [%group path.act]~ ~]
?: |(=(u.ship src.bol) (team:title our.bol src.bol))
:: delete a foreign ship's path
=/ group-wire [(scot %p u.ship) %group path.act]
@ -150,7 +150,7 @@
:_ state(synced (~(del by synced.state) pax.diff))
%+ snoc
(update-subscribers [%group pax.diff] diff)
[%give %kick `[%group pax.diff] ~]
[%give %kick [%group pax.diff]~ ~]
==
::
++ handle-foreign
@ -212,7 +212,7 @@
++ update-subscribers
|= [pax=path diff=group-update]
^- (list card)
[%give %fact `pax %group-update !>(diff)]~
[%give %fact ~[pax] %group-update !>(diff)]~
::
++ pull-wire
|= [wir=wire pax=path]

View File

@ -1,4 +1,4 @@
:: group-store: data store for groups of ships
:: group-store: data store for groups of ships
::
/- *group-store
/+ default-agent
@ -27,7 +27,7 @@
|_ =bowl:gall
+* this .
group-core +>
gc ~(. group-core bowl)
gc ~(. group-core bowl)
def ~(. (default-agent this %|) bowl)
::
++ on-init on-init:def
@ -75,9 +75,9 @@
[%x *] ``noun+!>((~(get by groups) t.path))
==
::
++ on-agent on-agent:def
++ on-arvo on-arvo:def
++ on-fail on-fail:def
++ on-agent on-agent:def
++ on-arvo on-arvo:def
++ on-fail on-fail:def
--
::
|_ bol=bowl:gall
@ -148,7 +148,7 @@
++ update-subscribers
|= [pax=path act=group-action]
^- (list card)
[%give %fact `pax %group-update !>(act)]~
[%give %fact ~[pax] %group-update !>(act)]~
::
++ send-diff
|= [pax=path act=group-action]

View File

@ -54,7 +54,7 @@
?: (team:title our.bowl src.bowl)
:: outgoing. we must be inviting another ship. send them the invite.
::
?> !(team:title our.bowl ship.invite.act)
?> !(team:title our.bowl recipient.invite.act)
[(invite-hook-poke:do recipient.invite.act act)]~
:: else incoming. ensure invitatory exists and invite is not a duplicate.
::

View File

@ -169,7 +169,7 @@
++ update-subscribers
|= [pax=path upd=invite-update]
^- card
[%give %fact `pax %invite-update !>(upd)]
[%give %fact ~[pax] %invite-update !>(upd)]
::
++ send-diff
|= [pax=path upd=invite-update]

View File

@ -59,7 +59,7 @@
?> ?=(%invite-update p.cage.sign)
:~ :*
%give %fact
`/primary %json
~[/primary] %json
!>((update-to-json !<(invite-update q.cage.sign)))
== ==
==

View File

@ -153,7 +153,7 @@
=/ dat=(unit [json url=@t]) (~(get by data) name)
?~ dat [~ this]
:_ this(data (~(put by data) name [jon url.u.dat]))
[%give %fact `/main %json !>((frond:enjs:format name jon))]~
[%give %fact ~[/main] %json !>((frond:enjs:format name jon))]~
::
++ on-arvo
|= [wir=wire sin=sign-arvo]

View File

@ -83,7 +83,7 @@
%+ give-simple-payload:app eyre-id.u.job.state
[[200 ~] `(as-octt:mimes:html "\"Imported data\"")]
::
[%export ~]
[%export ~]
?+ -.sign (on-agent:def wire sign)
%watch-ack
?~ p.sign
@ -94,7 +94,8 @@
::
%fact
=^ cards this (take-export !<(* q.cage.sign))
:_ this :_ cards
:_ this(job.state ~)
:_ cards
?> ?=(^ job.state)
?> ?=(%export -.source.com.u.job.state)
[%pass /export %agent [our.bowl app.source.com.u.job.state] %leave ~]
@ -135,7 +136,7 @@
=/ enc (en:base64 octs)
(pairs:enjs:format file+s+output data+s+enc ~)
::
:_ this(job.state ~)
:_ this
%+ give-simple-payload:app eyre-id.u.job.state
(json-response:gen (json-to-octs jon))
::

View File

@ -165,14 +165,14 @@
++ kick-proxy
|= [who=ship =path]
^- card
[%give %kick `path `who]
[%give %kick ~[path] `who]
::
++ handle-proxy-sign
|= [=path =sign:agent:gall]
^- (quip card _state)
?- -.sign
%poke-ack ~|([dap.bowl %unexpected-poke-ack path] !!)
%fact [[%give %fact `path cage.sign]~ state]
%fact [[%give %fact ~[path] cage.sign]~ state]
%kick [[(proxy-pass-link-store path %watch path)]~ state]
::
%watch-ack

View File

@ -131,7 +131,7 @@
:_ state
:_ cards
:+ %give %fact
:+ `[%local-pages path]
:+ [%local-pages path]~
%link-update
!>([%local-pages path [page]~])
:: +hear-submission: record page someone else saved
@ -154,7 +154,7 @@
:_ state
:_ ~
:+ %give %fact
:+ `[%submissions path]
:+ [%submissions path]~
%link-update
!>([%submissions path [submission]~])
::

View File

@ -140,7 +140,7 @@
==
:: delete the permission path and its subscriptions from this hook.
::
:- :- [%give %kick `[%permission path.act] ~]
:- :- [%give %kick [%permission path.act]~ ~]
(leave-permission path.act)
%_ state
synced (~(del by synced) path.act)
@ -278,7 +278,7 @@
^- (list card)
%+ turn ~(tap in access-paths)
|= access-path=path
[%give %kick `[%permission access-path] `check-ship]
[%give %kick [%permission access-path]~ `check-ship]
::
++ permission-scry
|= pax=path
@ -313,7 +313,7 @@
++ update-subscribers
|= [=path upd=permission-update]
^- card
[%give %fact `path %permission-update !>(upd)]
[%give %fact ~[path] %permission-update !>(upd)]
::
++ leave-permission
|= =path

View File

@ -184,7 +184,7 @@
++ update-subscribers
|= [pax=path upd=permission-update]
^- (list card)
[%give %fact `pax %permission-update !>(upd)]~
[%give %fact ~[pax] %permission-update !>(upd)]~
::
++ send-diff
|= [pax=path upd=permission-update]

View File

@ -243,7 +243,7 @@
++ write-file
=, space:userlib
|= [pax=path cay=cage]
^- card
^- card
=. pax (weld our-beak pax)
[%pass (weld /write-file pax) %arvo %c %info (foal pax cay)]
::
@ -730,15 +730,15 @@
++ affection-primary
|= del=delta
^- (list card)
[%give %fact `/primary %publish-rumor !>(del)]~
[%give %fact ~[/primary] %publish-rumor !>(del)]~
:: +affection: rumors to interested
::
++ affection
|= del=delta
^- (list card)
=/ wir=wire /collection/[col.del]
:~ [%give %fact `/primary %publish-rumor !>(del)]
[%give %fact `wir %publish-rumor !>(del)]
:~ [%give %fact ~[/primary] %publish-rumor !>(del)]
[%give %fact ~[wir] %publish-rumor !>(del)]
==
::
++ get-post-by-index
@ -1263,7 +1263,7 @@
=/ upd=update [%invite %.y src.bol coll.act title.act]
:_ state
%+ welp make-tile-moves
[%give %fact `/primary %publish-update !>(upd)]~
[%give %fact ~[/primary] %publish-update !>(upd)]~
::
:: %reject-invite: remove invite from list, acceptance is handled by
:: %subscribe action
@ -1276,7 +1276,7 @@
=/ upd=update [%invite %.n who.act coll.act u.title]
:_ state
%+ welp make-tile-moves
[%give %fact `/primary %publish-update !>(upd)]~
[%give %fact ~[/primary] %publish-update !>(upd)]~
::
:: %serve:
::
@ -1406,7 +1406,7 @@
[%pass wir %agent [who.act %publish] %watch wir]~
?~ title ~
=/ upd=update [%invite %.n who.act coll.act u.title]
[%give %fact `/primary %publish-update !>(upd)]~
[%give %fact ~[/primary] %publish-update !>(upd)]~
==
::
:: %unsubscribe: unsub from a foreign blog, delete all state related to it
@ -1435,7 +1435,7 @@
:- [%pass wir %agent [who.act %publish] %leave ~]
%+ welp make-tile-moves
=/ rum=rumor [%remove who.act coll.act ~]
[%give %fact `/primary %publish-rumor !>(rum)]~
[%give %fact ~[/primary] %publish-rumor !>(rum)]~
::
:: %read: notify that we've seen a post
::
@ -1445,7 +1445,7 @@
%+ welp make-tile-moves
::
=/ upd=update [%unread %.n (sy [who.act coll.act post.act] ~)]
[%give %fact `/primary %publish-update !>(upd)]~
[%give %fact ~[/primary] %publish-update !>(upd)]~
::
==
::
@ -1597,7 +1597,7 @@
::
++ make-tile-moves
^- (list card)
[%give %fact `/publishtile %json !>(make-tile-json)]~
[%give %fact ~[/publishtile] %json !>(make-tile-json)]~
::
++ make-tile-json
^- json

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,3 @@
:: Thread manager
::
/- spider
/+ libstrand=strand, default-agent, verb
=, strand=strand:libstrand
@ -127,9 +125,6 @@
|- ^- (quip card _this)
?~ yarns
`this
?. ?=([@ ~] i.yarns)
$(yarns t.yarns)
~| killing=i.yarns
=^ cards-1 state
(handle-stop-thread:sc (yarn-to-tid i.yarns) |)
=^ cards-2 this
@ -139,8 +134,6 @@
++ on-poke
|= [=mark =vase]
^- (quip card _this)
?: ?=(%spider-kill mark)
(on-load on-save)
=^ cards state
?+ mark (on-poke:def mark vase)
%spider-input (on-poke-input:sc !<(input vase))
@ -357,15 +350,12 @@
^- ^card
?+ card card
[%pass * *] [%pass [%thread tid p.card] q.card]
[%give %fact *]
?~ path.p.card
card
card(path.p `[%thread tid u.path.p.card])
::
[%give %kick *]
?~ path.p.card
card
card(path.p `[%thread tid u.path.p.card])
[%give ?(%fact %kick) *]
=- card(paths.p -)
%+ turn paths.p.card
|= =path
^- ^path
[%thread tid path]
==
=. cards (weld cards cards.r)
=^ final-cards=(list card) state
@ -391,13 +381,14 @@
++ thread-say-fail
|= [=tid =term =tang]
^- (list card)
:~ [%give %fact `/thread-result/[tid] %thread-fail !>([term tang])]
[%give %kick `/thread-result/[tid] ~]
:~ [%give %fact ~[/thread-result/[tid]] %thread-fail !>([term tang])]
[%give %kick ~[/thread-result/[tid]] ~]
==
::
++ thread-fail
|= [=yarn =term =tang]
^- (quip card ^state)
%- (slog leaf+"strand {<yarn>} failed" leaf+<term> tang)
=/ =tid (yarn-to-tid yarn)
=/ fail-cards (thread-say-fail tid term tang)
=^ cards state (thread-clean yarn)
@ -409,8 +400,8 @@
:: %- (slog leaf+"strand {<yarn>} finished" (sell vase) ~)
=/ =tid (yarn-to-tid yarn)
=/ done-cards=(list card)
:~ [%give %fact `/thread-result/[tid] %thread-done vase]
[%give %kick `/thread-result/[tid] ~]
:~ [%give %fact ~[/thread-result/[tid]] %thread-done vase]
[%give %kick ~[/thread-result/[tid]] ~]
==
=^ cards state (thread-clean yarn)
[(weld done-cards cards) state]

View File

@ -101,7 +101,7 @@
=/ lismov [%pass /[(scot %da now.bol)] %arvo %i %request req out]~
?~ timer
:- [[%pass /timer %arvo %b %wait (add now.bol ~h3)] lismov]
%= state
%= state
location str
timer `(add now.bol ~h3)
==
@ -135,7 +135,7 @@
currently+(~(got by p.u.ujon) 'currently')
daily+(~(got by p.u.ujon) 'daily')
==
:- [%give %fact `/weathertile %json !>(jon)]~
:- [%give %fact ~[/weathertile] %json !>(jon)]~
%= state
data jon
time now.bol

View File

@ -291,7 +291,7 @@
?~ biz (flop moz)
:_ (flop moz)
=/ =dill-blit:dill ?~(t.biz i.biz [%mor (flop biz)])
[%give %fact `/drum %dill-blit !>(dill-blit)]
[%give %fact ~[/drum] %dill-blit !>(dill-blit)]
::
++ se-adit :: update servers
^+ .
@ -478,7 +478,7 @@
::
++ se-blit-sys :: output to system
|= bil/dill-blit:dill ^+ +>
(se-emit %give %fact `/drum %dill-blit !>(bil))
(se-emit %give %fact ~[/drum] %dill-blit !>(bil))
::
++ se-show :: show buffer, raw
|= lin/(pair @ud stub)

View File

@ -312,11 +312,11 @@
++ take-agent
|= [=wire =sign:agent:gall]
?+ wire ~|([%kiln-bad-take-agent wire -.sign] !!)
[%kiln %fancy *] ?> ?=(%poke-ack -.sign)
[%kiln %fancy *] ?> ?=(%poke-ack -.sign)
(take-coup-fancy t.t.wire p.sign)
[%kiln %reload *] ?> ?=(%poke-ack -.sign)
(take-coup-reload t.t.wire p.sign)
[%kiln %spam *] ?> ?=(%poke-ack -.sign)
[%kiln %spam *] ?> ?=(%poke-ack -.sign)
(take-coup-spam t.t.wire p.sign)
==
::

View File

@ -117,7 +117,7 @@
:- "%_"
"""
$\{1:target}
$\{2:wing} $\{3:new-value}
$\{2:wing} $\{3:new-value}
==
"""
:- "%."
@ -139,7 +139,7 @@
:- "%*"
"""
$\{1:target-wing} $\{2:from}
$\{3:wing} $\{4:new-value}
$\{3:wing} $\{4:new-value}
==
"""
:- "%^"
@ -164,7 +164,7 @@
:- "%="
"""
$\{1:target}
$\{2:wing} $\{3:new-value}
$\{2:wing} $\{3:new-value}
==
"""
::
@ -422,7 +422,7 @@
:- "?-"
"""
$\{1:case}
$\{2:type} $\{3:value}
$\{2:type} $\{3:value}
==
"""
:- "?:"
@ -455,8 +455,8 @@
"""
:- "?+"
"""
$\{1:case} $\{2:else}
$\{3:type} $\{4:value}
$\{1:case} $\{2:else}
$\{3:type} $\{4:value}
==
"""
:- "?&"

View File

@ -49,9 +49,9 @@
[%http-response-header !>(response-header.simple-payload)]
=/ data-cage
[%http-response-data !>(data.simple-payload)]
:~ [%give %fact `/http-response/[eyre-id] header-cage]
[%give %fact `/http-response/[eyre-id] data-cage]
[%give %kick `/http-response/[eyre-id] ~]
:~ [%give %fact ~[/http-response/[eyre-id]] header-cage]
[%give %fact ~[/http-response/[eyre-id]] data-cage]
[%give %kick ~[/http-response/[eyre-id]] ~]
==
--
++ gen

View File

@ -83,7 +83,7 @@
++ wush
|= [wid=@u tan=tang]
^- tape
%- of-wall:format
%- of-wall:format
%+ turn (flop tan)
|= =tank
~! wid

View File

@ -4,7 +4,7 @@
++ grab
|%
++ noun chat-action
++ json
++ json
|= jon=^json
(json-to-action jon)
--

View File

@ -19,7 +19,7 @@
++ add-owned
%- ot
:~ [%path pa]
[%security sec]
[%security sec]
[%allow-history bo]
==
::

View File

@ -4,7 +4,7 @@
++ grab
|%
++ noun chat-view-action
++ json
++ json
|= jon=^json
(json-to-view-action jon)
--

View File

@ -4,7 +4,7 @@
++ grab
|%
++ noun invite-action
++ json
++ json
|= jon=^json
(json-to-action jon)
--

View File

@ -4,7 +4,7 @@
++ grab
|%
++ noun permission-action
++ json
++ json
|= jon=^json
=< (parse-permission-action jon)
|%

View File

@ -4,7 +4,7 @@
++ grab
|%
++ noun permission-group-hook-action
++ json
++ json
|= jon=^json
(json-to-perm-group-hook-action jon)
--

View File

@ -43,10 +43,10 @@
:* %+ rash creator.txs
;~(pfix (jest 'creator: ~') fed:ag)
::
%+ rash collection.txs
%+ rash collection.txs
;~(pfix (jest 'collection: ') (cook crip (star next)))
::
%+ rash post.txs
%+ rash post.txs
;~(pfix (jest 'post: ') (cook crip (star next)))
::
%+ rash date-created.txs

View File

@ -46,10 +46,10 @@
:* %+ rash owner.txs
;~(pfix (jest 'owner: ~') fed:ag)
::
%+ rash title.txs
%+ rash title.txs
;~(pfix (jest 'title: ') (cook crip (star next)))
::
%+ rash filename.txs
%+ rash filename.txs
;~(pfix (jest 'filename: ') (cook crip (star next)))
::
%+ rash comments.txs

View File

@ -13,14 +13,14 @@
%+ frond -.rum
?- -.rum
%collection
%- pairs
%- pairs
:~ [%coll s+col.rum]
[%who (ship who.rum)]
[%data (collection-build-to-json dat.rum)]
==
::
%post
%- pairs
%- pairs
:~ [%coll s+col.rum]
[%post s+pos.rum]
[%who (ship who.rum)]
@ -28,7 +28,7 @@
==
::
%comments
%- pairs
%- pairs
:~ [%coll s+col.rum]
[%post s+pos.rum]
[%who (ship who.rum)]

View File

@ -2,7 +2,7 @@
/+ publish
/= result
/^ (list comment:publish)
/;
/;
|= comments=(map knot comment:publish)
^- (list [comment-info:publish @t])
%+ sort ~(val by comments)

View File

@ -3,7 +3,7 @@
/= args /$ ,[beam *]
/= result
/^ [post-info:publish manx @t]
/;
/;
|= $: post-front=(map knot cord)
post-content=manx
post-raw=wain

View File

@ -5,7 +5,7 @@
:: if ship is foreign, delete any local
:: group at that path and mirror the
:: foreign group at our local path
::
::
[%remove =path] :: remove the path.
==
--

View File

@ -1,55 +1,89 @@
:: Ames extends Arvo's %pass/%give move semantics across the network.
::
:: A "forward flow" message, which is like a request, is passed to
:: Ames from a local vane. Ames transmits the message to the peer's
:: Ames, which passes the message to the destination vane.
:: Ames receives packets as Arvo events and emits packets as Arvo
:: effects. The runtime is responsible for transferring the bytes in
:: an Ames packet across a physical network to another ship.
::
:: Once the peer has processed the "forward flow" message, it sends a
:: message acknowledgment over the wire back to the local Ames. This
:: ack can either be positive or negative, in which case we call it a
:: "nack". (Don't confuse Ames nacks with TCP nacks, which are a
:: different concept).
:: The runtime tells Ames which physical address a packet came from,
:: represented as an opaque atom. Ames can emit a packet effect to
:: one of those opaque atoms or to the Urbit address of a galaxy
:: (root node), which the runtime is responsible for translating to a
:: physical address. One runtime implementation sends UDP packets
:: using IPv4 addresses for ships and DNS lookups for galaxies, but
:: other implementations may overlay over other kinds of networks.
::
:: When the local Ames receives either a positive message ack or a
:: combination of a nack and nack-trace (explained in more detail
:: A local vane can pass Ames a %plea request message. Ames
:: transmits the message over the wire to the peer ship's Ames, which
:: passes the message to the destination vane.
::
:: Once the peer has processed the %plea message, it sends a
:: message-acknowledgment packet over the wire back to the local
:: Ames. This ack can either be positive to indicate the request was
:: processed, or negative to indicate the request failed, in which
:: case it's called a "nack". (Don't confuse Ames nacks with TCP
:: nacks, which are a different concept).
::
:: When the local Ames receives either a positive message-ack or a
:: combination of a nack and naxplanation (explained in more detail
:: below), it gives an %done move to the local vane that had
:: requested the original "forward flow" message be sent.
:: requested the original %plea message be sent.
::
:: A "backward flow" message, which is similar to a response or a
:: subscription update, is given to Ames from a local vane. Ames
:: transmits the message to the peer's Ames, which gives the message
:: to the destination vane.
:: A local vane can give Ames zero or more %boon response messages in
:: response to a %plea, on the same duct that Ames used to pass the
:: %plea to the vane. Ames transmits a %boon over the wire to the
:: peer's Ames, which gives it to the destination vane on the same
:: duct the vane had used to pass the original %plea to Ames.
::
:: Ames will give a %memo to a vane upon hearing the message from a
:: remote. This message is a "backward flow" message, forming one of
:: potentially many responses to a "forward flow" message that a
:: local vane had passed to our local Ames, and which local Ames had
:: relayed to the remote. Ames gives the %memo on the same duct the
:: local vane had originally used to pass Ames the "forward flow"
:: message.
:: %boon messages are acked automatically by the receiver Ames. They
:: cannot be nacked, and Ames only uses the ack internally, without
:: notifying the client vane that gave Ames the %boon.
::
:: Backward flow messages are acked automatically by the receiver.
:: They cannot be nacked, and Ames only uses the ack internally,
:: without notifying the client vane.
:: If the Arvo event that completed receipt of a %boon message
:: crashes, Ames instead sends the client vane a %lost message
:: indicating the %boon was missed.
::
:: Forward flow messages can be nacked, in which case the peer will
:: send both a message-nack packet and a nack-trace message, which is
:: sent on a special diagnostic flow so as not to interfere with
:: normal operation. The nack-trace is sent as a full Ames message,
:: instead of just a packet, because the contained error information
:: can be arbitrarily large.
:: %plea messages can be nacked, in which case the peer will send
:: both a message-nack packet and a naxplanation message, which is
:: sent in a way that does not interfere with normal operation. The
:: naxplanation is sent as a full Ames message, instead of just a
:: packet, because the contained error information can be arbitrarily
:: large. A naxplanation can only give rise to a positive ack --
:: never ack an ack, and never nack a naxplanation.
::
:: Once the local Ames has received the nack-trace, it knows the peer
:: has received the full message and failed to process it. This
:: means if we later hear an ack packet on the failed message, we can
:: ignore it.
:: Ames guarantees a total ordering of messages within a "flow",
:: identified in other vanes by a duct and over the wire by a "bone":
:: an opaque number. Each flow has a FIFO queue of %plea requests
:: from the requesting ship to the responding ship and a FIFO queue
:: of %boon's in the other direction.
::
:: Also, due to Ames's exactly-once delivery semantics, we know that
:: when we receive a nack-trace for message n, we know the peer has
:: positively acked all messages m+1 through n-1, where m is the last
:: message for which we heard a nack-trace. If we haven't heard acks
:: on all those messages, we apply positive acks when we hear the
:: nack-trace.
:: Message order across flows is not specified and may vary based on
:: network conditions.
::
:: Ames guarantees that a message will only be delivered once to the
:: destination vane.
::
:: Ames encrypts every message using symmetric-key encryption by
:: performing an elliptic curve Diffie-Hellman using our private key
:: and the public key of the peer. For ships in the Jael PKI
:: (public-key infrastructure), Ames looks up the peer's public key
:: from Jael. Comets (128-bit ephemeral addresses) are not
:: cryptographic assets and must self-attest over Ames by sending a
:: single self-signed packet containing their public key.
::
:: When a peer suffers a continuity breach, Ames removes all
:: messaging state related to it. Ames does not guarantee that all
:: messages will be fully delivered to the now-stale peer. From
:: Ames's perspective, the newly restarted peer is a new ship.
:: Ames's guarantees are not maintained across a breach.
::
:: A vane can pass Ames a %heed $task to request Ames track a peer's
:: responsiveness. If our %boon's to it start backing up locally,
:: Ames will give a %clog back to the requesting vane containing the
:: unresponsive peer's urbit address. This interaction does not use
:: ducts as unique keys. Stop tracking a peer by sending Ames a
:: %jilt $task.
::
:: Debug output can be adjusted using %sift and %spew $task's.
::
:: protocol-version: current version of the ames wire protocol
::
@ -530,7 +564,15 @@
:: The first bone is 0. They increment by 4, since each flow includes
:: a bit for each message determining forward vs. backward and a
:: second bit for whether the message is on the normal flow or the
:: associated diagnostic flow (for nack-traces).
:: associated diagnostic flow (for naxplanations).
::
:: The least significant bit of a $bone is:
:: 1 if "forward", i.e. we send %plea's on this flow, or
:: 0 if "backward", i.e. we receive %plea's on this flow.
::
:: The second-least significant bit is 1 if the bone is a
:: naxplanation bone, and 0 otherwise. Only naxplanation
:: messages can be sent on a naxplanation bone, as %boon's.
::
+$ ossuary
$: =next=bone
@ -542,43 +584,40 @@
:: Messages queue up in |message-pump's .unsent-messages until they
:: can be packetized and fed into |packet-pump for sending. When we
:: pop a message off .unsent-messages, we push as many fragments as
:: we can into |packet-pump, then place the remaining in
:: .unsent-fragments.
:: we can into |packet-pump, which sends every packet it eats.
:: Packets rejected by |packet-pump are placed in .unsent-fragments.
::
:: When we hear a packet ack, we send it to |packet-pump. If we
:: haven't seen it before, |packet-pump reports the fresh ack.
:: When we hear a packet ack, we send it to |packet-pump to be
:: removed from its queue of unacked packets.
::
:: When we hear a message ack (positive or negative), we treat that
:: as though all fragments have been acked. If this message is not
:: .current, then it's a future message and .current has not yet been
:: acked, so we place the ack in .queued-message-acks.
:: .current, then this ack is for a future message and .current has
:: not yet been acked, so we place the ack in .queued-message-acks.
::
:: If we hear a message ack before we've sent all the
:: fragments for that message, clear .unsent-fragments. If the
:: message ack was positive, print it out because it indicates the
:: peer is not behaving properly.
:: If we hear a message ack before we've sent all the fragments for
:: that message, clear .unsent-fragments and have |packet-pump delete
:: all sent fragments from the message. If this early message ack was
:: positive, print it out because it indicates the peer is not
:: behaving properly.
::
:: If the ack is for the current message, emit the message ack,
:: increment .current, and check if this next message is in
:: .queued-message-acks. If it is, emit the message (n)ack,
:: increment .current, and check the next message. Repeat until
:: .current is not fully acked.
::
:: When we hear a message nack, we send it to |packet-pump, which
:: deletes all packets from that message. If .current gets nacked,
:: clear .unsent-fragments and go into the same flow as when we hear
:: the last packet ack on a message.
:: If the ack is for the current message, have |packet-pump delete
:: all packets from the message, give the message ack back
:: to the client vane, increment .current, and check if this next
:: message is in .queued-message-acks. If it is, emit the message
:: (n)ack, increment .current, and check the next message. Repeat
:: until .current is not fully acked.
::
:: The following equation is always true:
:: .next - .current == number of messages in flight
::
:: At the end of a task, |message-pump sends a %halt task to
:: |packet-pump, which can trigger a timer to be set or cleared based
:: on congestion control calculations. When it fires, the timer will
:: generally cause one or more packets to be resent.
:: on congestion control calculations. When the timer fires, it will
:: generally cause a packet to be re-sent.
::
:: Message sequence numbers start at 1 so the first message will be
:: greater than .last-acked.message-sink-state on the receiver.
:: Message sequence numbers start at 1 so that the first message will
:: be greater than .last-acked.message-sink-state on the receiver.
::
:: current: sequence number of earliest message sent or being sent
:: next: sequence number of next message to send
@ -618,7 +657,14 @@
:: algorithm. The information signals and their responses are
:: identical to those of the "NewReno" variant of Reno; the
:: implementation differs because Ames acknowledgments differ from
:: TCP's and because we're using functional data structures.
:: TCP's, because this code uses functional data structures, and
:: because TCP's sequence numbers reset when a peer becomes
:: unresponsive, whereas Ames sequence numbers only change when a
:: ship breaches.
::
:: A deviation from Reno is +fast-resend-after-ack, which re-sends
:: timed-out packets when a peer starts responding again after a
:: period of unresponsiveness.
::
:: If .skips reaches 3, we perform a fast retransmit and fast
:: recovery. This corresponds to Reno's handling of "three duplicate
@ -697,8 +743,6 @@
==
:: $note: request to other vane
::
:: TODO: specialize gall interface for subscription management
::
:: Ames passes a %plea note to another vane when it receives a
:: message on a "forward flow" from a peer, originally passed from
:: one of the peer's vanes to the peer's Ames.
@ -729,13 +773,6 @@
== == ==
:: $sign: response from other vane
::
:: A vane gives a %boon sign to Ames on a duct on which it had
:: previously received a message on a "forward flow". Ames will
:: transmit the message to the peer that had originally sent the
:: message on the forward flow. The peer's Ames will then give the
:: message to the remote vane from which the forward flow message
:: originated.
::
+$ sign
$~ [%b %wake ~]
$% $: %b
@ -1126,11 +1163,70 @@
--
:: +scry: dereference namespace
::
:: The ones producing vases are expected to be used like this:
::
:: &tang [(sell .^(vase %a /=peer=/~zod)) ~]
::
++ scry
|= [fur=(unit (set monk)) ren=@tas why=shop syd=desk lot=coin tyl=path]
^- (unit (unit cage))
?. =(lot [%$ %da now]) ~
?. =(%$ ren) [~ ~]
?. =([%& our] why)
[~ ~]
?+ syd ~
%peer
?. ?=([@ ~] tyl) [~ ~]
=/ who (slaw %p i.tyl)
?~ who [~ ~]
=/ per (~(get by peers.ames-state) u.who)
=/ res
?- per
~ %unknown
[~ %alien *] %alien
[~ %known *]
=, u.per
:* %known
symkeymug=(mug symmetric-key)
life=life
pubkey=public-key
sponsor=sponsor
route=route
qos=qos
ossuary=ossuary
snd=~(key by snd)
rcv=~(key by rcv)
nax=nax
heeds=heeds
==
==
``noun+!>(!>(res))
::
[~ ~]
%bones
?. ?=([@ ~] tyl) [~ ~]
=/ who (slaw %p i.tyl)
?~ who [~ ~]
=/ per (~(get by peers.ames-state) u.who)
?. ?=([~ %known *] per) [~ ~]
=/ res
=, u.per
[snd=~(key by snd) rcv=~(key by rcv)]
``noun+!>(res)
::
%snd-bone
?. ?=([@ @ ~] tyl) [~ ~]
=/ who (slaw %p i.tyl)
?~ who [~ ~]
=/ ost (slaw %ud i.t.tyl)
?~ ost [~ ~]
=/ per (~(get by peers.ames-state) u.who)
?. ?=([~ %known *] per) [~ ~]
=/ mps (~(get by snd.u.per) u.ost)
?~ mps [~ ~]
=/ res
u.mps
``noun+!>(!>(res))
==
--
:: helpers
::
@ -1381,10 +1477,15 @@
?> =(rcvr-life.shut-packet our-life.channel)
:: non-galaxy: update route with heard lane or forwarded lane
::
=? route.peer-state
?& !=(%czar (clan:title her.channel))
!=([~ %& *] route.peer-state)
==
=? route.peer-state
?: =(%czar (clan:title her.channel))
%.n
=/ is-old-direct=? ?=([~ %& *] route.peer-state)
=/ is-new-direct=? ?=(~ origin.packet)
:: old direct takes precedence over new indirect
::
|(is-new-direct !is-old-direct)
::
?~ origin.packet
`[direct=%.y lane]
`[direct=%.n u.origin.packet]
@ -1512,6 +1613,7 @@
::
:: Abandon all pretense of continuity and delete all messaging state
:: associated with .ship, including sent and unsent messages.
:: Also cancel all timers related to .ship.
::
++ on-publ-breach
|= =ship
@ -2053,7 +2155,11 @@
++ send-shut-packet
|= =shut-packet
^+ peer-core
:: swizzle bone just before sending; TODO document
:: swizzle last bone bit before sending
::
:: The peer has the opposite perspective from ours about what
:: kind of flow this is (forward/backward), so flip the bit
:: here.
::
=. bone.shut-packet (mix 1 bone.shut-packet)
::
@ -2201,7 +2307,7 @@
:: +on-sink-boon: handle response message received by |message-sink
::
:: .bone must be mapped in .ossuary.peer-state, or we crash.
:: This means a malformed message will kill a channel. We
:: This means a malformed message will kill a flow. We
:: could change this to a no-op if we had some sort of security
:: reporting.
::
@ -2491,7 +2597,7 @@
^+ message-pump
=/ top-live
(peek:packet-queue:*make-packet-pump live.packet-pump-state.state)
?. |(?=(~ top-live) (gte current.state message-num.key.u.top-live))
?. |(?=(~ top-live) (lte current.state message-num.key.u.top-live))
~| [%strange-current current=current.state key.u.top-live]
!!
message-pump
@ -2654,7 +2760,7 @@
:: +on-hear: handle ack on a live packet
::
:: If the packet was in our queue, delete it and update our
:: metrics. Otherwise, no-op.
:: metrics, possibly re-sending skipped packets. Otherwise, no-op.
::
++ on-hear
|= [=message-num =fragment-num]

View File

@ -44,12 +44,13 @@
::
:: Type of request.
::
:: %d produces a set of desks, %p gets file permissions, %u checks for
:: existence, %v produces a ++dome of all desk data, %w gets @ud and @da
:: variants for the given case, %x gets file contents, %y gets a directory
:: listing, and %z gets a recursive hash of the file contents and children.
:: %d produces a set of desks, %p gets file permissions, %t gets all paths
:: with the specified prefix, %u checks for existence, %v produces a ++dome
:: of all desk data, %w gets @ud and @da variants for the given case, %x
:: gets file contents, %y gets a directory listing, and %z gets a recursive
:: hash of the file contents and children.
::
:: ++ care ?($d $p $u $v $w $x $y $z)
:: ++ care ?($d $p $t $u $v $w $x $y $z)
::
:: Keeps track of subscribers.
::

View File

@ -637,7 +637,7 @@
this.outstandingSubscriptions.set(
id,
{
err: connectionErrFunc,
err: connectionErrFunc,
event: eventFunc,
quit: quitFunc
}

View File

@ -54,7 +54,7 @@
++ state
$: :: state version
::
%2
%3
:: agents by ship
::
=agents
@ -904,7 +904,7 @@
%give
=/ =gift:agent p.card
?: ?=(%kick -.gift)
=/ ducts=(list duct) (ap-ducts-from-path path.gift ship.gift)
=/ ducts=(list duct) (ap-ducts-from-paths paths.gift ship.gift)
%+ turn ducts
|= =duct
~? &(=(duct system-duct.agents.state) !=(agent-name %hood))
@ -914,7 +914,7 @@
?. ?=(%fact -.gift)
[agent-duct %give %unto gift]~
::
=/ ducts=(list duct) (ap-ducts-from-path path.gift ~)
=/ ducts=(list duct) (ap-ducts-from-paths paths.gift ~)
=/ =cage cage.gift
%+ turn ducts
|= =duct
@ -1010,6 +1010,17 @@
::
++ ap-agent-core
~(. agent.current-agent ap-construct-bowl)
:: +ap-ducts-from-paths: get ducts subscribed to paths
::
++ ap-ducts-from-paths
|= [target-paths=(list path) target-ship=(unit ship)]
^- (list duct)
?: &(?=(~ target-paths) ?=(~ target-ship))
~[agent-duct]
%- zing
%+ turn target-paths
|= =path
(ap-ducts-from-path `path target-ship)
:: +ap-ducts-from-path: get ducts subscribed to path
::
++ ap-ducts-from-path
@ -1567,16 +1578,177 @@
=? all-state ?=(%1 -.all-state)
(state-1-to-2 all-state)
::
?> ?=(%2 -.all-state)
=? all-state ?=(%2 -.all-state)
(state-2-to-3 all-state)
::
?> ?=(%3 -.all-state)
gall-payload(state all-state)
::
:: +all-state: upgrade path
::
++ all-state $%(state-0 state-1 ^state)
++ all-state $%(state-0 state-1 state-2 ^state)
::
++ state-2-to-3
|= =state-2
^- ^state
%= state-2
- %3
running.agents-2
%- ~(run by running.agents-2.state-2)
|= =running-agent-2
^- running-agent
%= running-agent-2
agent-2 (agent-2-to-3 agent-2.running-agent-2)
==
==
::
++ agent-2-to-3
|= =agent-2
^- agent
=> |%
++ cards-2-to-3
|= cards=(list card:^agent-2)
^- (list card:agent)
%+ turn cards
|= =card:^agent-2
^- card:agent
?. ?=([%give ?(%fact %kick) *] card) card
%=(card path.p (drop path.p.card))
--
|_ =bowl:gall
+* this .
pass ~(. agent-2 bowl)
++ on-init
=^ cards agent-2 on-init:pass
[(cards-2-to-3 cards) this]
::
++ on-save
on-save:pass
::
++ on-load
|= old-state=vase
=^ cards agent-2 (on-load:pass old-state)
[(cards-2-to-3 cards) this]
::
++ on-poke
|= [=mark =vase]
=^ cards agent-2 (on-poke:pass mark vase)
[(cards-2-to-3 cards) this]
::
++ on-watch
|= =path
=^ cards agent-2 (on-watch:pass path)
[(cards-2-to-3 cards) this]
::
++ on-leave
|= =path
=^ cards agent-2 (on-leave:pass path)
[(cards-2-to-3 cards) this]
::
++ on-peek
|= =path
(on-peek:pass path)
::
++ on-agent
|= [=wire =sign:agent:gall]
=^ cards agent-2 (on-agent:pass wire sign)
[(cards-2-to-3 cards) this]
::
++ on-arvo
|= [=wire =sign-arvo]
=^ cards agent-2 (on-arvo:pass wire sign-arvo)
[(cards-2-to-3 cards) this]
::
++ on-fail
|= [=term =tang]
=^ cards agent-2 (on-fail:pass term tang)
[(cards-2-to-3 cards) this]
--
::
++ state-2
$: %2
=agents-2
==
::
++ agents-2
$: system-duct=duct
outstanding=(map [wire duct] (qeu remote-request))
contacts=(set ship)
running=(map term running-agent-2)
blocked=(map term blocked)
==
::
++ running-agent-2
$: cache=worm
control-duct=duct
live=?
=stats
=subscribers
=agent-2
=beak
marks=(map duct mark)
==
::
++ agent-2
=< form
|%
+$ step (quip card form)
+$ card (wind note gift)
+$ note note:agent
+$ task task:agent
+$ sign sign:agent
+$ gift
$% [%fact path=(unit path) =cage]
[%kick path=(unit path) ship=(unit ship)]
[%watch-ack p=(unit tang)]
[%poke-ack p=(unit tang)]
==
++ form
$_ ^|
|_ bowl
++ on-init
*(quip card _^|(..on-init))
::
++ on-save
*vase
::
++ on-load
|~ old-state=vase
*(quip card _^|(..on-init))
::
++ on-poke
|~ [mark vase]
*(quip card _^|(..on-init))
::
++ on-watch
|~ path
*(quip card _^|(..on-init))
::
++ on-leave
|~ path
*(quip card _^|(..on-init))
::
++ on-peek
|~ path
*(unit (unit cage))
::
++ on-agent
|~ [wire sign]
*(quip card _^|(..on-init))
::
++ on-arvo
|~ [wire sign-arvo]
*(quip card _^|(..on-init))
::
++ on-fail
|~ [term tang]
*(quip card _^|(..on-init))
--
--
::
++ state-1-to-2
|= =state-1
^- ^state
^- state-2
%= state-1
- %2
+.agents-1 [~ +.agents-1.state-1]
@ -1590,7 +1762,7 @@
++ agents-1
$: system-duct=duct
contacts=(set ship)
running=(map term running-agent)
running=(map term running-agent-2)
blocked=(map term blocked)
==
::
@ -1602,7 +1774,7 @@
running.agents-0
%- ~(run by running.agents-0.state-0)
|= =running-agent-0
^- running-agent
^- running-agent-2
%= running-agent-0
agent-0 (agent-0-to-1 agent-0.running-agent-0)
==
@ -1610,7 +1782,7 @@
::
++ agent-0-to-1
|= =agent-0
^- agent
^- agent-2
|_ =bowl:gall
+* this .
pass ~(. agent-0 bowl)
@ -1692,7 +1864,7 @@
+$ card (wind note gift)
+$ note note:agent
+$ task task:agent
+$ gift gift:agent
+$ gift gift:agent-2
+$ sign sign:agent
++ form
$_ ^|

File diff suppressed because it is too large Load Diff

View File

@ -1887,8 +1887,8 @@
[%poke-as =mark =cage]
==
+$ gift
$% [%fact path=(unit path) =cage]
[%kick path=(unit path) ship=(unit ship)]
$% [%fact paths=(list path) =cage]
[%kick paths=(list path) ship=(unit ship)]
[%watch-ack p=(unit tang)]
[%poke-ack p=(unit tang)]
==

View File

@ -120,8 +120,8 @@
(pure:m ~)
=/ =path /(scot %p ship.i.udiffs)
=/ cards
:~ [%give %fact `/ %azimuth-udiff !>(i.udiffs)]
[%give %fact `path %azimuth-udiff !>(i.udiffs)]
:~ [%give %fact ~[/] %azimuth-udiff !>(i.udiffs)]
[%give %fact ~[path] %azimuth-udiff !>(i.udiffs)]
==
;< ~ bind:m (send-raw-cards:strandio cards)
loop(udiffs t.udiffs)

View File

@ -141,8 +141,8 @@
++ test-list-murn
%+ expect-eq
!> ~[6 10]
!> %+ murn `(list @)`~[2 3 4 5]
|= [x=@]
!> %+ murn `(list @)`~[2 3 4 5]
|= [x=@]
^- (unit)
?: =((mod x 2) 0) ~
(some (mul x 2))

View File

@ -308,7 +308,7 @@
:~ :* duct=~[/http-blah] %give %response
[%start [200 ['content-type' 'text/html']~] ~ %.n]
== == ==
;: weld
results1
results2

View File

@ -144,7 +144,7 @@ gulp.task('urbit-copy', function () {
gulp.task('js-bundle-dev', gulp.series('jsx-transform', 'js-imports'));
gulp.task('tile-js-bundle-dev', gulp.series('tile-jsx-transform', 'tile-js-imports'));
gulp.task('js-bundle-prod', gulp.series('jsx-transform', 'js-imports', 'js-minify'))
gulp.task('tile-js-bundle-prod',
gulp.task('tile-js-bundle-prod',
gulp.series('tile-jsx-transform', 'tile-js-imports', 'tile-js-minify'));
gulp.task('bundle-dev',

View File

@ -99,6 +99,21 @@ h2 {
word-break: break-all;
}
/* embeds */
.embed-container {
position: relative;
height: 0;
overflow: hidden;
}
.embed-container iframe, .embed-container object, .embed-container embed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* responsive */
@media all and (max-width: 34.375em) {
@ -114,6 +129,9 @@ h2 {
.h-100-minus-96-s {
height: calc(100% - 96px);
}
.embed-container {
padding-bottom: 56.25%;
}
}
@media all and (min-width: 34.375em) and (max-width: 46.875em) {
@ -123,6 +141,9 @@ h2 {
.h-100-minus-48-m {
height: calc(100% - 48px);
}
.embed-container {
padding-bottom: 56.25%;
}
}
@media all and (min-width: 46.875em) and (max-width: 60em) {
@ -132,6 +153,9 @@ h2 {
.h-100-minus-48-l {
height: calc(100% - 48px);
}
.embed-container {
padding-bottom: 37.5%;
}
}
@media all and (min-width: 60em) {
@ -141,4 +165,52 @@ h2 {
.h-100-minus-48-xl {
height: calc(100% - 48px);
}
}
.embed-container {
padding-bottom: 28.125%;
}
}
/* dark */
@media (prefers-color-scheme: dark) {
.bg-black-d {
background-color: black;
}
.white-d {
color: white;
}
.gray1-d {
color: #4d4d4d;
}
.gray2-d {
color: #7f7f7f;
}
.gray3-d {
color: #b1b2b3;
}
.gray4-d {
color: #e6e6e6;
}
.bg-gray0-d {
background-color: #333;
}
.b--gray0-d {
border-color: #333;
}
.b--gray2-d {
border-color: #7f7f7f;
}
.bb-d {
border-bottom-width: 1px;
border-bottom-style: solid;
}
.invert-d {
filter: invert(1);
}
.o-60-d {
opacity: .6;
}
a {
color: #fff;
}
}

View File

@ -14,7 +14,7 @@ class UrbitApi {
add: this.groupAdd.bind(this),
remove: this.groupRemove.bind(this)
};
this.chat = {
message: this.chatMessage.bind(this),
read: this.chatRead.bind(this)
@ -25,7 +25,7 @@ class UrbitApi {
delete: this.chatViewDelete.bind(this),
join: this.chatViewJoin.bind(this),
};
this.invite = {
accept: this.inviteAccept.bind(this),
decline: this.inviteDecline.bind(this),
@ -36,7 +36,7 @@ class UrbitApi {
bind(path, method, ship = this.authTokens.ship, app, success, fail, quit) {
this.bindPaths = _.uniq([...this.bindPaths, path]);
window.subscriptionId = window.urb.subscribe(ship, app, path,
window.subscriptionId = window.urb.subscribe(ship, app, path,
(err) => {
fail(err);
},
@ -59,7 +59,7 @@ class UrbitApi {
window.urb.poke(ship, appl, mark, data,
(json) => {
resolve(json);
},
},
(err) => {
reject(err);
});
@ -142,7 +142,7 @@ class UrbitApi {
}
chatViewJoin(ship, path, askHistory) {
this.chatViewAction({
this.chatViewAction({
join: {
ship, path,
'ask-history': askHistory
@ -153,9 +153,9 @@ class UrbitApi {
inviteAction(data) {
this.action("invite-store", "json", data);
}
inviteInvite(path, ship) {
this.action("invite-hook", "json",
this.action("invite-hook", "json",
{
invite: {
path: '/chat',
@ -180,7 +180,7 @@ class UrbitApi {
}
});
}
inviteDecline(uid) {
this.inviteAction({
decline: {

View File

@ -230,14 +230,15 @@ export class ChatScreen extends Component {
<Link to="/~chat/">{"⟵ All Chats"}</Link>
</div>
<div
className="pl3 pt2 bb b--gray4 flex relative overflow-x-scroll overflow-x-auto-l overflow-x-auto-xl flex-shrink-0"
className={`pl3 pt2 bb b--gray4 b--gray2-d bg-black-d flex relative overflow-x-scroll
overflow-x-auto-l overflow-x-auto-xl flex-shrink-0`}
style={{ height: 48 }}>
<SidebarSwitcher
sidebarShown={this.props.sidebarShown}
popout={this.props.popout}
/>
<Link to={`/~chat/` + isinPopout + `room` + state.station}
className="pt2">
className="pt2 white-d">
<h2
className="mono dib f8 fw4 v-top"
style={{ width: "max-content" }}>
@ -253,7 +254,7 @@ export class ChatScreen extends Component {
/>
</div>
<div
className="overflow-y-scroll pt3 pb2 flex flex-column-reverse"
className="overflow-y-scroll bg-black-d pt3 pb2 flex flex-column-reverse"
style={{ height: "100%", resize: "vertical" }}
onScroll={this.onScroll}>
<div

View File

@ -80,9 +80,9 @@ export class JoinScreen extends Component {
render() {
const { props } = this;
let joinClasses = "db f9 green2 ba pa2 b--green2 pointer";
let joinClasses = "db f9 green2 ba pa2 b--green2 bg-gray0-d pointer";
if ((!this.state.station) || (this.state.station === "/")) {
joinClasses = 'db f9 gray2 ba pa2 b--gray3 pointer';
joinClasses = 'db f9 gray2 ba pa2 b--gray3 bg-gray0-d pointer';
}
let errElem = (<span />);
@ -95,7 +95,8 @@ export class JoinScreen extends Component {
}
return (
<div className="h-100 w-100 pa3 pt2 overflow-x-hidden flex flex-column">
<div className={`h-100 w-100 pa3 pt2 overflow-x-hidden flex flex-column
bg-black-d white-d`}>
<div
className="w-100 dn-m dn-l dn-xl inter pt1 pb6 f8">
<Link to="/~chat/">{"⟵ All Chats"}</Link>
@ -106,7 +107,7 @@ export class JoinScreen extends Component {
<p className="f9 gray2 mb4">Chat names use lowercase, hyphens, and slashes.</p>
<textarea
ref={ e => { this.textarea = e; } }
className="f7 mono ba b--gray3 pa3 mb2 db"
className="f7 mono ba b--gray3 b--gray2-d bg-black-d white-d pa3 mb2 db"
placeholder="~zod/chatroom"
spellCheck="false"
rows={1}

View File

@ -64,7 +64,7 @@ export class ChatInput extends Component {
}
});
}
bindShortcuts() {
Mousetrap(this.textareaRef.current).bind('enter', e => {
e.preventDefault();
@ -173,9 +173,9 @@ export class ChatInput extends Component {
const { props, state } = this;
this.bindShortcuts();
return (
<div className="pa3 cf flex black bt b--gray4" style={{ flexGrow: 1 }}>
<div className="pa3 cf flex black white-d bt b--gray4 b--gray2-d bg-black-d" style={{ flexGrow: 1 }}>
<div
className="fl"
style={{
@ -185,9 +185,9 @@ export class ChatInput extends Component {
}}>
<Sigil ship={window.ship} size={24} color="#4330FC" />
</div>
<div className="fr h-100 flex" style={{ flexGrow: 1 }}>
<div className="fr h-100 flex bg-black-d" style={{ flexGrow: 1 }}>
<textarea
className={"pl3 bn"}
className={"pl3 bn bg-black-d white-d"}
style={{ flexGrow: 1, height: 28, paddingTop: 6, resize: "none" }}
autoCapitalize="none"
autoFocus={(

View File

@ -14,21 +14,21 @@ export class ChatTabBar extends Component {
if (props.location.pathname.includes('/settings')) {
memColor = 'gray3';
setColor = 'black';
setColor = 'black white-d';
} else if (props.location.pathname.includes('/members')) {
memColor = 'black';
memColor = 'black white-d';
setColor = 'gray3';
} else {
memColor = 'gray3';
setColor = 'gray3';
}
(props.location.pathname.includes('/popout'))
(props.location.pathname.includes('/popout'))
? popout = "popout/"
: popout = "";
let hidePopoutIcon = (this.props.popout)
? "dn-m dn-l dn-xl"
let hidePopoutIcon = (this.props.popout)
? "dn-m dn-l dn-xl"
: "dib-m dib-l dib-xl";
@ -55,7 +55,7 @@ export class ChatTabBar extends Component {
<a href={`/~chat/popout/room` + props.station} target="_blank"
className="dib fr">
<img
className={`flex-shrink-0 pr2 dn ` + hidePopoutIcon}
className={`flex-shrink-0 pr2 dn invert-d ` + hidePopoutIcon}
src="/~chat/img/popout.png"
height="16"
width="16"/>

View File

@ -17,7 +17,7 @@ export class HeaderBar extends Component {
: "dn db-m db-l db-xl";
return (
<div className={`bg-black w-100 justify-between ` + popoutHide}
<div className={`bg-black bb-d b--gray2-d w-100 justify-between ` + popoutHide}
style={{ height: 48, padding: 8}}>
<a className="db"
style={{ background: '#1A1A1A',

View File

@ -7,7 +7,7 @@ export class SidebarSwitcher extends Component {
let popoutSwitcher = this.props.popout
? "dn-m dn-l dn-xl"
: "dib-m dib-l dib-xl";
return (
<div className="pt2">
<a
@ -16,7 +16,7 @@ export class SidebarSwitcher extends Component {
api.sidebarToggle();
}}>
<img
className={`pr3 dn ` + popoutSwitcher}
className={`pr3 dn invert-d ` + popoutSwitcher}
src={
this.props.sidebarShown
? "/~chat/img/ChatSwitcherLink.png"

View File

@ -3,7 +3,7 @@ import React, { Component } from 'react';
export class IconSpinner extends Component {
render() {
return (
<div className="spinner-pending"></div>
<div className="spinner-pending"></div>
);
}
}

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { sigil, reactRenderer } from 'urbit-sigil-js';
export class Sigil extends Component {
render() {
const { props } = this;

View File

@ -80,7 +80,7 @@ export class InviteElement extends Component {
<div></div>
);
let modifyButtonClasses = "db f9 ba pa2 b--black pointer";
let modifyButtonClasses = "db f9 ba pa2 white-d bg-gray0-d b--black b--gray2-d pointer";
if (state.error) {
modifyButtonClasses = modifyButtonClasses + ' gray3';
}
@ -96,7 +96,7 @@ export class InviteElement extends Component {
<div>
<textarea
ref={ e => { this.textarea = e; } }
className="f7 mono ba b--gray3 pa3 mb4 db w-100"
className="f7 mono ba b--gray3 bg-black-d white-d pa3 mb4 db w-100"
style={{
resize: 'none',
height: 50

View File

@ -16,14 +16,14 @@ export class MemberElement extends Component {
let actionElem;
if (props.ship === props.owner) {
actionElem = (
<p className="w-20 dib list-ship black f8 c-default">
<p className="w-20 dib list-ship black white-d f8 c-default">
Host
</p>
);
} else if (window.ship !== props.ship && window.ship === props.owner) {
actionElem = (
<a onClick={this.onRemove.bind(this)}
className="w-20 dib list-ship black f8 pointer">
className="w-20 dib list-ship black white-d f8 pointer">
Ban
</a>
);
@ -38,7 +38,7 @@ export class MemberElement extends Component {
<Sigil ship={props.ship} size={32} />
<p
className={
"w-70 mono list-ship dib v-mid black ml2 nowrap f8"
"w-70 mono list-ship dib v-mid black white-d ml2 nowrap f8"
}>
~{props.ship}
</p>

View File

@ -8,14 +8,29 @@ import _ from 'lodash';
export class Message extends Component {
constructor() {
super();
this.state = {
unfold: false
};
this.unFoldEmbed = this.unFoldEmbed.bind(this);
}
unFoldEmbed(id) {
let unfoldState = this.state.unfold;
unfoldState = !unfoldState;
this.setState({unfold: unfoldState});
let iframe = this.refs.iframe;
iframe.setAttribute('src', iframe.getAttribute('data-src'));
}
renderContent() {
const { props } = this;
let letter = props.msg.letter;
if ('code' in letter) {
let outputElement =
(!!letter.code.output &&
let outputElement =
(!!letter.code.output &&
letter.code.output.length && letter.code.output.length > 0) ?
(
<pre className="clamp-attachment pa1 mt0 mb0">
@ -34,10 +49,20 @@ export class Message extends Component {
let imgMatch =
/(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF|GIF|webp|WEBP|webm|WEBM)$/
.exec(letter.url);
// this is jank
// TODO do we know ID lenght?
let youTubeRegex = new RegExp(''
+ /(?:https?:\/\/(?:[a-z]+.)?)/.source // protocol
+ /(?:youtu\.?be(?:\.com)?\/)(?:embed\/)?/.source // short and long-links
+ /(?:(?:(?:(?:watch\?)?(?:time_continue=(?:[0-9]+))?.+v=)?([a-zA-Z0-9_-]+))(?:\?t\=(?:[0-9a-zA-Z]+))?)/.source // id
)
let ytMatch =
youTubeRegex.exec(letter.url);
let contents = letter.url;
if (imgMatch) {
contents = (
<img
className="o-60-d"
src={letter.url}
style={{
width: "50%",
@ -45,18 +70,58 @@ export class Message extends Component {
}}
></img>
);
}
return (
<a className="f7 lh-copy v-top bb b--black word-break-all"
return (
<a className="f7 lh-copy v-top bb word-break-all"
href={letter.url}
target="_blank"
rel="noopener noreferrer">
{contents}
</a>
);
} else if (ytMatch) {
contents = (
<div className={'embed-container mb2 w-100 w-75-l w-50-xl ' +
((this.state.unfold === true)
? "db"
: "dn")}>
<iframe
ref="iframe"
width="560"
height="315"
data-src={`https://www.youtube.com/embed/${ytMatch[1]}`}
frameBorder="0" allow="picture-in-picture, fullscreen">
</iframe>
</div>
)
return (
<div>
<a href={letter.url}
className="f7 lh-copy v-top bb word-break-all"
href={letter.url}
target="_blank"
rel="noopener noreferrer">
{contents}
{letter.url}
</a>
);
<a className="f7 pointer pl2 lh-copy v-top word-break-all"
onClick={e => this.unFoldEmbed()}>
[embed]
</a>
{contents}
</div>
)
} else {
return (
<a className="f7 lh-copy v-top bb b--black word-break-all"
href={letter.url}
target="_blank"
rel="noopener noreferrer">
{contents}
</a>
);
}
} else if ('me' in letter) {
return (
<p className='f7 lh-copy v-top'>
<p className='f7 i lh-copy v-top'>
{letter.me}
</p>
);
@ -70,7 +135,7 @@ export class Message extends Component {
&& (chatroom[0] === letter.text))) { // entire message is room name?
return (
<Link
className="bb b--black f7 mono lh-copy v-top"
className="bb b--black f7 mono lh-copy v-top"
to={"/~chat/join/" + chatroom.input}>
{letter.text}
</Link>
@ -89,7 +154,7 @@ export class Message extends Component {
render() {
const { props } = this;
let pending = !!props.msg.pending ? ' o-40' : '';
let datestamp = "~" + moment.unix(props.msg.when / 1000).format('YYYY.MM.D');
let datestamp = "~" + moment.unix(props.msg.when / 1000).format('YYYY.M.D');
let paddingTop = props.paddingTop ? {'paddingTop': '6px'} : '';
@ -108,22 +173,22 @@ export class Message extends Component {
<Sigil
ship={props.msg.author}
size={24}
color={((props.msg.author === window.ship)
color={((props.msg.author === window.ship)
|| (props.msg.author.substr(1) === window.ship))
? "#4330FC"
? "#4330FC"
: "#000000"}
/>
</div>
<div
className="fr clamp-message"
className="fr clamp-message white-d"
style={{ flexGrow: 1, marginTop: -8 }}>
<div className="hide-child" style={paddingTop}>
<p className="v-mid mono f9 gray dib mr3">
<p className="v-mid mono f9 gray2 dib mr3">
{props.msg.author.slice(0, 1) === "~" ? "" : "~"}
{props.msg.author}
</p>
<p className="v-mid mono f9 gray dib">{timestamp}</p>
<p className="v-mid mono f9 ml2 gray dib child dn-s">{datestamp}</p>
<p className="v-mid mono f9 gray2 dib">{timestamp}</p>
<p className="v-mid mono f9 ml2 gray2 dib child dn-s">{datestamp}</p>
</div>
{this.renderContent()}
</div>
@ -138,9 +203,9 @@ export class Message extends Component {
style={{
minHeight: "min-content"
}}>
<p className="child pt2 pl2 pr1 mono f9 gray dib">{timestamp}</p>
<div className="fr f7 clamp-message" style={{ flexGrow: 1 }}>
{this.renderContent()}
<p className="child pt2 pl2 pr1 mono f9 gray2 dib">{timestamp}</p>
<div className="fr f7 clamp-message white-d pr3" style={{ flexGrow: 1 }}>
{this.renderContent()}
</div>
</div>
);

View File

@ -18,7 +18,7 @@ export class SidebarInvite extends Component {
return (
<div className='pa3'>
<div className='w-100 v-mid'>
<p className="dib f8 mono">
<p className="dib f8 mono gray4-d">
{props.invite.text}
</p>
</div>
@ -28,7 +28,7 @@ export class SidebarInvite extends Component {
Accept Invite
</a>
<a
className="dib pointer ml4 pa2 f9 bg-black white mt4"
className="dib pointer ml4 pa2 f9 bg-black bg-gray0-d white mt4"
onClick={this.onDecline.bind(this)}>
Decline
</a>

View File

@ -37,7 +37,7 @@ export class SidebarItem extends Component {
getLetter(lett) {
if ('text' in lett) {
return lett.text;
return lett.text;
} else if ('url' in lett) {
return lett.url;
} else if ('code' in lett) {
@ -50,23 +50,23 @@ export class SidebarItem extends Component {
render() {
const { props, state } = this;
let unreadElem = !!props.unread
? "fw7 green2"
let unreadElem = !!props.unread
? "fw7 green2"
: "";
let title = props.title.substr(1);
let description = this.getLetter(props.description);
let selectedCss = !!props.selected ? 'bg-gray5' : 'bg-white pointer';
let selectedCss = !!props.selected ? 'bg-gray5 bg-gray0-d gray3-d' : 'bg-white bg-black-d gray3-d pointer';
return (
<div
className={"z1 pa3 pt4 pb4 bb b--gray4 " + selectedCss}
className={"z1 pa3 pt4 pb4 bb b--gray4 b--gray2-d " + selectedCss}
onClick={this.onClick.bind(this)}>
<div className="w-100 v-mid">
<p className={"dib mono f8 " + unreadElem }>
<span className={(unreadElem === "") ? "gray3" : ""}>
<span className={(unreadElem === "") ? "gray3 gray2-d" : ""}>
{title.substr(0, title.indexOf("/"))}/
</span>
{title.substr(title.indexOf("/") + 1)}

View File

@ -51,8 +51,8 @@ export class MemberScreen extends Component {
let writeListMembers = writeGroup.map((mem) => {
return (
<MemberElement
key={mem}
<MemberElement
key={mem}
owner={deSig(props.match.params.ship)}
ship={mem}
path={`/chat${state.station}/write`}
@ -63,8 +63,8 @@ export class MemberScreen extends Component {
let readListMembers = readGroup.map((mem) => {
return (
<MemberElement
key={mem}
<MemberElement
key={mem}
owner={deSig(props.match.params.ship)}
ship={mem}
path={`/chat${state.station}/read`}
@ -76,21 +76,21 @@ export class MemberScreen extends Component {
let isinPopout = this.props.popout ? "popout/" : "";
return (
<div className="h-100 w-100 overflow-x-hidden flex flex-column">
<div className="h-100 w-100 overflow-x-hidden flex flex-column white-d">
<div
className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8"
style={{ height: "1rem" }}>
<Link to="/~chat/">{"⟵ All Chats"}</Link>
</div>
<div
className="pl3 pt2 bb b--gray4 flex relative overflow-x-scroll overflow-x-auto-l overflow-x-auto-xl flex-shrink-0"
className="pl3 pt2 bb b--gray4 b--gray2-d bg-black-d flex relative overflow-x-scroll overflow-x-auto-l overflow-x-auto-xl flex-shrink-0"
style={{ height: 48 }}>
<SidebarSwitcher
sidebarShown={this.props.sidebarShown}
popout={this.props.popout}
/>
<Link to={`/~chat/` + isinPopout + `room` + state.station}
className="pt2">
className="pt2 white-d">
<h2
className="mono dib f8 fw4 v-top"
style={{ width: "max-content" }}>

View File

@ -28,7 +28,7 @@ export class NewScreen extends Component {
componentDidUpdate(prevProps, prevState) {
const { props, state } = this;
if (prevProps !== props) {
if (prevProps !== props) {
let station = `/~${window.ship}/${state.idName}`;
if (station in props.inbox) {
props.history.push('/~chat/room' + station);
@ -81,7 +81,7 @@ export class NewScreen extends Component {
let invalidChara = new RegExp(/[^a-z0-9/-]/);
let invalid = (
(!state.idName) || (state.idName.startsWith("/")) ||
(!state.idName) || (state.idName.startsWith("/")) ||
(state.idName.includes("//")) || (invalidChara.test(state.idName))
);
@ -132,7 +132,7 @@ export class NewScreen extends Component {
// TODO: don't do this, it's shitty
let writeAud;
let readAud;
let readAud;
if (state.security === 'village') {
aud.push(`~${window.ship}`);
@ -168,9 +168,9 @@ export class NewScreen extends Component {
}
render() {
let createClasses = "pointer db f9 green2 ba pa2 b--green2";
let createClasses = "pointer db f9 green2 bg-gray0-d ba pa2 b--green2";
if (!this.state.idName) {
createClasses = 'pointer db f9 gray2 ba pa2 b--gray3';
createClasses = 'pointer db f9 gray2 ba bg-gray0-d pa2 b--gray3';
}
let idErrElem = (<span />);
@ -192,7 +192,8 @@ export class NewScreen extends Component {
}
return (
<div className="h-100 w-100 w-50-l w-50-xl pa3 pt2 overflow-x-hidden flex flex-column">
<div className={`h-100 w-100 w-50-l w-50-xl pa3 pt2 overflow-x-hidden
bg-black-d white-d flex flex-column`}>
<div className="w-100 dn-m dn-l dn-xl inter pt1 pb6 f8">
<Link to="/~chat/">{"⟵ All Chats"}</Link>
</div>
@ -202,8 +203,8 @@ export class NewScreen extends Component {
<p className="f9 gray2 db mb4">
Lowercase alphanumeric characters, dashes, and slashes only
</p>
<textarea
className="f7 ba b--gray3 pa3 db w-100"
<textarea
className="f7 ba b--gray3 b--gray2-d bg-black-d white-d pa3 db w-100"
placeholder="secret-chat"
rows={1}
style={{
@ -216,7 +217,7 @@ export class NewScreen extends Component {
<div className="dropdown relative">
<select
style={{WebkitAppearance: "none"}}
className="pa3 f8 bg-white br0 w-100 inter"
className="pa3 f8 bg-white bg-black-d white-d br0 w-100 inter"
value={this.state.securityValue}
onChange={this.securityChange}>
<option value="village">Village</option>
@ -232,7 +233,7 @@ export class NewScreen extends Component {
</p>
<textarea
ref={e => { this.textarea = e; }}
className="f7 mono ba b--gray3 pa3 mb4 db w-100"
className="f7 mono ba b--gray3 b--gray2-d bg-black-d white-d pa3 mb4 db w-100"
placeholder="~zod, ~bus"
spellCheck="false"
style={{

View File

@ -37,7 +37,7 @@ export class Root extends Component {
let unreads = {};
Object.keys(state.inbox).forEach((stat) => {
let envelopes = state.inbox[stat].envelopes;
if (envelopes.length === 0) {
messagePreviews[stat] = false;
} else {
@ -47,7 +47,7 @@ export class Root extends Component {
unreads[stat] =
state.inbox[stat].config.length > state.inbox[stat].config.read;
});
let invites = '/chat' in state.invites ?
state.invites['/chat'] : {};

View File

@ -49,7 +49,7 @@ export class SettingsScreen extends Component {
let chatOwner = (deSig(props.match.params.ship) === window.ship);
let deleteButtonClasses = (chatOwner) ? 'b--red2 red2 pointer' : 'b--grey3 grey3 c-default';
let deleteButtonClasses = (chatOwner) ? 'b--red2 red2 pointer bg-gray0-d' : 'b--grey3 grey3 bg-gray0-d c-default';
let leaveButtonClasses = (!chatOwner) ? "pointer" : "c-default";
return (
@ -58,7 +58,7 @@ export class SettingsScreen extends Component {
<p className="f8 mt3 lh-copy db">Leave Chat</p>
<p className="f9 gray2 db mb4">Remove this chat from your chat list. You will need to request for access again.</p>
<a onClick={(!chatOwner) ? this.deleteChat.bind(this) : null}
className={"dib f9 black ba pa2 b--black " + leaveButtonClasses}>Leave this chat</a>
className={"dib f9 black gray4-d bg-gray0-d ba pa2 b--black b--gray2-d " + leaveButtonClasses}>Leave this chat</a>
</div>
<div className={"w-100 fl mt3 " + ((!chatOwner) ? 'o-30' : '')}>
<p className="f8 mt3 lh-copy db">Delete Chat</p>
@ -83,21 +83,21 @@ export class SettingsScreen extends Component {
}
return (
<div className="h-100 w-100 overflow-x-hidden flex flex-column">
<div className="h-100 w-100 overflow-x-hidden flex flex-column white-d">
<div
className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8"
style={{ height: "1rem" }}>
<Link to="/~chat/">{"⟵ All Chats"}</Link>
</div>
<div
className="pl3 pt2 bb b--gray4 flex relative overflow-x-scroll overflow-x-auto-l overflow-x-auto-xl flex-shrink-0"
className="pl3 pt2 bb b--gray4 b--gray2-d bg-black-d flex relative overflow-x-scroll overflow-x-auto-l overflow-x-auto-xl flex-shrink-0"
style={{ height: 48 }}>
<SidebarSwitcher
sidebarShown={this.props.sidebarShown}
popout={this.props.popout}
/>
<Link to={`/~chat/` + isinPopout + `room` + state.station}
className="pt2">
className="pt2 white-d">
<h2
className="mono dib f8 fw4 v-top"
style={{ width: "max-content" }}>
@ -118,7 +118,7 @@ export class SettingsScreen extends Component {
}
return (
<div className="h-100 w-100 overflow-x-hidden flex flex-column">
<div className="h-100 w-100 overflow-x-hidden flex flex-column white-d">
<div
className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8"
style={{ height: "1rem" }}>

View File

@ -71,18 +71,19 @@ export class Sidebar extends Component {
});
return (
<div className="h-100-minus-96-s h-100 w-100 overflow-x-hidden flex flex-column relative z1">
<div className={`h-100-minus-96-s h-100 w-100 overflow-x-hidden flex
bg-black-d flex-column relative z1`}>
<div className="overflow-y-auto h-100">
{sidebarInvites}
{sidebarItems}
</div>
<div className="absolute z2 tc w-100 bg-transparent"
style={{ bottom: 10 }}>
<a className="dib f9 pa3 bt bb bl br tc pointer bg-white"
<a className="dib f9 pa3 bt bb bl br tc pointer bg-white bg-gray0-d gray4-d b--gray2-d"
onClick={this.onClickNew.bind(this)}>
Create New Chat
</a>
<a className="dib f9 pa3 bt bb br tl pointer bg-white"
<a className="dib f9 pa3 bt bb br tl pointer bg-white bg-gray0-d gray4-d b--gray2-d"
onClick={this.onClickJoin.bind(this)}>
Join Existing Chat
</a>

View File

@ -6,12 +6,12 @@ import { HeaderBar } from '/components/lib/header-bar.js';
export class Skeleton extends Component {
render() {
let sidebarHide = (!this.props.sidebarShown || this.props.popout)
? "dn"
let sidebarHide = (!this.props.sidebarShown || this.props.popout)
? "dn"
: "";
let sidebarHideOnMobile = this.props.sidebarHideOnMobile
? "dn-s"
let sidebarHideOnMobile = this.props.sidebarHideOnMobile
? "dn-s"
: "";
let chatHideOnMobile = this.props.chatHideonMobile
@ -19,18 +19,18 @@ export class Skeleton extends Component {
: "";
return (
<div className="h-100 w-100 absolute">
<div className="h-100 w-100 absolute bg-black-d">
<HeaderBar spinner={this.props.spinner} popout={this.props.popout} />
<div className={`cf w-100 absolute flex ` +
((this.props.chatHideonMobile)
<div className={`cf w-100 absolute flex ` +
((this.props.chatHideonMobile)
? "h-100 "
: "h-100-minus-48-s ") +
: "h-100-minus-48-s ") +
((this.props.popout)
? "h-100"
: "h-100-minus-48-m h-100-minus-48-l h-100-minus-48-xl")}>
<div className={
`fl h-100 br b--gray4 overflow-x-hidden
flex-basis-full-s flex-basis-300-m flex-basis-300-l
`fl h-100 br b--gray4 b--gray2-d overflow-x-hidden
flex-basis-full-s flex-basis-300-m flex-basis-300-l
flex-basis-300-xl ` +
sidebarHide + " " +
sidebarHideOnMobile
@ -43,7 +43,7 @@ export class Skeleton extends Component {
<a className="pl3 pb6" href="/">
{"⟵ Landscape"}
</a>
<div className="bb b--gray4 inter f8 pl3 pt6 pb3">All Chats</div>
<div className="bb b--gray4 white-d inter f8 pl3 pt6 pb3">All Chats</div>
</div>
{this.props.sidebar}
</div>

View File

@ -26,9 +26,9 @@ export class ChatUpdateReducer {
messages(json, state) {
let data = _.get(json, 'messages', false);
if (data) {
state.inbox[data.path].envelopes =
state.inbox[data.path].envelopes =
data.envelopes.concat(state.inbox[data.path].envelopes);
state.inbox[data.path].config.length =
state.inbox[data.path].config.length =
state.inbox[data.path].config.length + data.envelopes.length;
}
}
@ -60,7 +60,7 @@ export class ChatUpdateReducer {
delete state.inbox[data.path];
}
}
pending(json, state) {
let msg = _.get(json, 'message', false);
if (!msg || !state.pendingMessages.has(msg.path)) {
@ -76,6 +76,6 @@ export class ChatUpdateReducer {
}
}
}
}

View File

@ -46,6 +46,6 @@ export class PermissionUpdateReducer {
}
}
}
}

View File

@ -18,12 +18,12 @@ export default class App extends Component {
return (
<BrowserRouter>
<div>
<Route exact path="/"
<Route exact path="/"
render={ (props) => {
return (
<Home
<Home
{...props}
data={this.state}
data={this.state}
keys={new Set(Object.keys(this.state))}
/>
);

View File

@ -12,7 +12,7 @@ export default class Header extends Component {
super(props);
this.interval = null;
this.timeout = null;
this.state = {
moment: moment()
};
@ -20,7 +20,7 @@ export default class Header extends Component {
componentDidMount() {
let sec = parseInt(moment().format("s"), 10);
this.timeout = setTimeout(() => {
this.setState({
moment: moment()
@ -32,7 +32,7 @@ export default class Header extends Component {
}, 60000);
}, (60 - sec) * 1000);
}
componentWillUnmount() {
clearTimeout(this.timeout);
clearInterval(this.interval);

View File

@ -15,7 +15,7 @@ export default class Tile extends Component {
return (
<div className="fl ma2 bg-white overflow-hidden"
style={{ height: '234px', width: '234px' }}>
{ !!SpecificTile ?
{ !!SpecificTile ?
<SpecificTile data={this.props.data} />
: <div></div>
}

View File

@ -1,7 +1,7 @@
class Api {
bind(app, path, success, fail, ship) {
window.urb.subscribe(ship, app, path,
window.urb.subscribe(ship, app, path,
(err) => {
fail(err, app, path, ship);
},
@ -25,7 +25,7 @@ class Api {
window.urb.poke(ship, appl, mark, data,
(json) => {
resolve(json);
},
},
(err) => {
reject(err);
});

View File

@ -145,7 +145,7 @@ gulp.task('urbit-copy', function () {
gulp.task('js-bundle-dev', gulp.series('jsx-transform', 'js-imports'));
gulp.task('tile-js-bundle-dev', gulp.series('tile-jsx-transform', 'tile-js-imports'));
gulp.task('js-bundle-prod', gulp.series('jsx-transform', 'js-imports', 'js-minify'))
gulp.task('tile-js-bundle-prod',
gulp.task('tile-js-bundle-prod',
gulp.series('tile-jsx-transform', 'tile-js-imports', 'tile-js-minify'));
gulp.task('bundle-dev',

View File

@ -12,7 +12,7 @@ class UrbitApi {
bind(path, method, ship = this.authTokens.ship, appl = "publish", success, fail) {
this.bindPaths = _.uniq([...this.bindPaths, path]);
window.urb.subscribe(ship, appl, path,
window.urb.subscribe(ship, appl, path,
(err) => {
fail(err);
},

View File

@ -54,7 +54,7 @@ export class Blog extends Component {
awaiting: false,
pathData: [
{ text: "Home", url: "/~publish/recent" },
{ text: blog.info.title,
{ text: blog.info.title,
url: `/~publish/${blog.info.owner}/${blog.info.filename}` }
],
});
@ -62,7 +62,7 @@ export class Blog extends Component {
this.props.setSpinner(false);
} else if (diff.data.remove) {
if (diff.data.remove.post) {
// XX TODO
// XX TODO
} else {
this.props.history.push("/~publish/recent");
}
@ -203,7 +203,7 @@ export class Blog extends Component {
blogHost: blog.info.owner,
pathData: [
{ text: "Home", url: "/~publish/recent" },
{ text: blog.info.title,
{ text: blog.info.title,
url: `/~publish/${blog.info.owner}/${blog.info.filename}` }
],
};
@ -279,7 +279,7 @@ export class Blog extends Component {
let viewSettings = (this.props.ship === window.ship)
? this.viewSettings
: null;
if (this.state.view === 'notes') {
return (
<div>

View File

@ -10,7 +10,7 @@ export class BlogNotes extends Component {
render() {
if (!this.props.posts ||
((this.props.posts.length === 0) &&
((this.props.posts.length === 0) &&
(this.props.ship === window.ship))) {
let link = {
pathname: "/~publish/new-post",

View File

@ -79,7 +79,7 @@ export class BlogSettings extends Component {
render() {
let back = '<- Back to notes'
let enableSave = ((this.state.title !== '') &&
let enableSave = ((this.state.title !== '') &&
(this.state.title !== this.props.title) &&
!this.state.awaitingTitleChange);
return (
@ -93,7 +93,7 @@ export class BlogSettings extends Component {
</p>
<div className="flex">
<div className="flex-col w-100">
<p className="body-regular-400">Delete Notebook</p>
<p className="body-regular-400">Delete Notebook</p>
<p className="gray-50 label-small-2" style={{marginTop:12, marginBottom:8}}>
Permanently delete this notebook
</p>
@ -102,7 +102,7 @@ export class BlogSettings extends Component {
</button>
</div>
<div className="flex-col w-100">
<p className="body-regular-400">Rename</p>
<p className="body-regular-400">Rename</p>
<p className="gray-50 label-small-2" style={{marginTop:12, marginBottom:23}}>
Change the name of this notebook
</p>

View File

@ -51,7 +51,7 @@ export class BlogSubs extends Component {
.split(/[\s,]+/)
.map(t => t.trim());
let valid = tokens.reduce((valid, s) =>
let valid = tokens.reduce((valid, s) =>
valid && ((s !== '~') && urbitOb.isValidPatp(s) && s.includes('~')), true);
if (valid) {
@ -86,7 +86,7 @@ export class BlogSubs extends Component {
render() {
let back = '<- Back to notes'
let subscribers = this.props.subs.map((sub, i) => {
return (
<div className="flex w-100" key={i+1}>
@ -113,7 +113,7 @@ export class BlogSubs extends Component {
</p>
<div className="flex">
<div className="flex-col w-100">
<p className="body-regular-400">Members</p>
<p className="body-regular-400">Members</p>
<p className="gray-50 label-small-2"
style={{marginTop:12, marginBottom: 23}}>
Everyone subscribed to this notebook
@ -121,7 +121,7 @@ export class BlogSubs extends Component {
{subscribers}
</div>
<div className="flex-col w-100">
<p className="body-regular-400">Invite</p>
<p className="body-regular-400">Invite</p>
<p className="gray-50 label-small-2"
style={{marginTop:12, marginBottom: 23}}>
Invite people to subscribe to this notebook

View File

@ -52,7 +52,7 @@ export class CommentBox extends Component {
? "body-regular-400 w-100"
: "body-regular-400 w-100 gray-30";
return (
<div className="cb w-100 flex"
<div className="cb w-100 flex"
style={{paddingBottom: 8, marginTop: 32}}>
<div className="fl" style={{marginRight: 10}}>
<Sigil ship={this.props.our} size={36}/>
@ -67,10 +67,10 @@ export class CommentBox extends Component {
onChange={this.commentChange}
disabled={(!this.props.enabled)}>
</textarea>
<PostButton
post={this.props.post}
<PostButton
post={this.props.post}
enabled={(Boolean(this.props.content) && this.props.enabled)}
/>
/>
</div>
</div>
);

View File

@ -12,7 +12,7 @@ export class Comments extends Component {
commentBody: '',
awaiting: false,
}
this.toggleDisplay = this.toggleDisplay.bind(this);
this.commentChange = this.commentChange.bind(this);
this.postComment = this.postComment.bind(this);

View File

@ -30,7 +30,7 @@ export class HeaderMenu extends Component {
<div className="fl bb b-gray-30 w-16" >
</div>
<NavLink exact
<NavLink exact
className="header-menu-item"
to="/~publish/recent"
activeStyle={{
@ -44,7 +44,7 @@ export class HeaderMenu extends Component {
<div className="fl bb b-gray-30 w-16" >
</div>
<NavLink exact
<NavLink exact
className="header-menu-item"
to="/~publish/subs"
activeStyle={{
@ -58,7 +58,7 @@ export class HeaderMenu extends Component {
<div className="fl bb b-gray-30 w-16" >
</div>
<NavLink exact
<NavLink exact
className="header-menu-item"
to="/~publish/pubs"
activeStyle={{

View File

@ -3,7 +3,7 @@ import React, { Component } from 'react';
export class IconSpinner extends Component {
render() {
return (
<div className="spinner-pending"></div>
<div className="spinner-pending"></div>
);
}
}

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { sigil, reactRenderer } from 'urbit-sigil-js';
export class Sigil extends Component {
render() {
const { props } = this;

View File

@ -57,7 +57,7 @@ class Preview extends Component {
let date = moment(previewProps.date).fromNow();
let authorDate = `${previewProps.author}${date}`
let collLink = "/~publish/" +
let collLink = "/~publish/" +
previewProps.blogOwner + "/" +
previewProps.collectionName;
let postLink = collLink + "/" + previewProps.postName;

View File

@ -32,7 +32,7 @@ export class PathControl extends Component {
(last.lastMatch === '/~publish/:ship/:blog')){
blog = (last.lastParams.ship.slice(1) == window.ship)
? _.get(this.props, `pubs["${last.lastParams.blog}"]`, false)
: _.get(this.props,
: _.get(this.props,
`subs["${last.lastParams.ship.slice(1)}"]["${last.lastParams.blog}"]`, false);
}
}

View File

@ -101,7 +101,7 @@ export class PostBody extends Component {
let page = this.parseContent(this.props.body.c,
this.props.body.gn,
this.props.body.ga,
null);
null);
return page;
}
}

View File

@ -38,7 +38,7 @@ export class PostPreview extends Component {
: `${this.props.post.numComments} comments`;
let date = moment(this.props.post.date).fromNow();
let authorDate = `${this.props.post.author}${date}`
let collLink = "/~publish/" +
let collLink = "/~publish/" +
this.props.post.blogOwner + "/" +
this.props.post.collectionName;
let postLink = collLink + "/" + this.props.post.postName;

Some files were not shown because too many files have changed in this diff Show More