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 [azim]: https://etherscan.io/address/0x223c067f8cf28ae173ee5cafea60ca44c335fecb
[aens]: https://etherscan.io/address/azimuth.eth [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 [arvo]: https://github.com/urbit/urbit/tree/master/pkg/arvo
## Install ## Install

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -137,7 +137,7 @@
== ==
== ==
:: ::
++ on-arvo ++ on-arvo
|= [=wire =sign-arvo] |= [=wire =sign-arvo]
^- (quip card _this) ^- (quip card _this)
?. ?=(%bound +<.sign-arvo) ?. ?=(%bound +<.sign-arvo)
@ -176,7 +176,7 @@
=/ pax t.t.t.t.site.url =/ pax t.t.t.t.site.url
=/ envelopes (envelope-scry [(scot %ud start) (scot %ud end) pax]) =/ envelopes (envelope-scry [(scot %ud start) (scot %ud end) pax])
%- json-response:gen %- json-response:gen
%- json-to-octs %- json-to-octs
%- update-to-json %- update-to-json
[%messages pax start end envelopes] [%messages pax start end envelopes]
:: ::
@ -239,8 +239,8 @@
^- (list card) ^- (list card)
=/ updates-json (update-to-json upd) =/ updates-json (update-to-json upd)
=/ configs-json (configs-to-json configs-scry) =/ configs-json (configs-to-json configs-scry)
:~ [%give %fact `/primary %json !>(updates-json)] :~ [%give %fact ~[/primary] %json !>(updates-json)]
[%give %fact `/configs %json !>(configs-json)] [%give %fact ~[/configs] %json !>(configs-json)]
== ==
:: ::
:: +utilities :: +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="stylesheet" href="/~chat/css/index.css" />
<link rel="icon" type="image/png" href="/~launch/img/Favicon.png"> <link rel="icon" type="image/png" href="/~launch/img/Favicon.png">
<link rel="manifest" <link rel="manifest"
href='data:application/manifest+json,{ href='data:application/manifest+json,{
"name": "Chat", "name": "Chat",
"short_name": "Chat", "short_name": "Chat",
"description": "A%20Chat%20application%20for%20your%20Urbit%20ship.", "description": "A%20Chat%20application%20for%20your%20Urbit%20ship.",
"display": "standalone", "display": "standalone",
"background_color": "%23FFFFFF", "background_color": "%23FFFFFF",
"theme_color": "%23000000"}' /> "theme_color": "%23000000"}' />
</head> </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 ++ give-result
|= [=the=path =cage] |= [=the=path =cage]
^- card ^- card
[%give %fact `the-path cage] [%give %fact ~[the-path] cage]
-- --
:: ::
^- agent:gall ^- agent:gall

View File

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

View File

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

View File

@ -126,7 +126,7 @@
:_ state(synced (~(del by synced.state) path.act)) :_ state(synced (~(del by synced.state) path.act))
%+ snoc %+ snoc
(pull-wire group-wire path.act) (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)) ?: |(=(u.ship src.bol) (team:title our.bol src.bol))
:: delete a foreign ship's path :: delete a foreign ship's path
=/ group-wire [(scot %p u.ship) %group path.act] =/ group-wire [(scot %p u.ship) %group path.act]
@ -150,7 +150,7 @@
:_ state(synced (~(del by synced.state) pax.diff)) :_ state(synced (~(del by synced.state) pax.diff))
%+ snoc %+ snoc
(update-subscribers [%group pax.diff] diff) (update-subscribers [%group pax.diff] diff)
[%give %kick `[%group pax.diff] ~] [%give %kick [%group pax.diff]~ ~]
== ==
:: ::
++ handle-foreign ++ handle-foreign
@ -212,7 +212,7 @@
++ update-subscribers ++ update-subscribers
|= [pax=path diff=group-update] |= [pax=path diff=group-update]
^- (list card) ^- (list card)
[%give %fact `pax %group-update !>(diff)]~ [%give %fact ~[pax] %group-update !>(diff)]~
:: ::
++ pull-wire ++ pull-wire
|= [wir=wire pax=path] |= [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 /- *group-store
/+ default-agent /+ default-agent
@ -27,7 +27,7 @@
|_ =bowl:gall |_ =bowl:gall
+* this . +* this .
group-core +> group-core +>
gc ~(. group-core bowl) gc ~(. group-core bowl)
def ~(. (default-agent this %|) bowl) def ~(. (default-agent this %|) bowl)
:: ::
++ on-init on-init:def ++ on-init on-init:def
@ -75,9 +75,9 @@
[%x *] ``noun+!>((~(get by groups) t.path)) [%x *] ``noun+!>((~(get by groups) t.path))
== ==
:: ::
++ on-agent on-agent:def ++ on-agent on-agent:def
++ on-arvo on-arvo:def ++ on-arvo on-arvo:def
++ on-fail on-fail:def ++ on-fail on-fail:def
-- --
:: ::
|_ bol=bowl:gall |_ bol=bowl:gall
@ -148,7 +148,7 @@
++ update-subscribers ++ update-subscribers
|= [pax=path act=group-action] |= [pax=path act=group-action]
^- (list card) ^- (list card)
[%give %fact `pax %group-update !>(act)]~ [%give %fact ~[pax] %group-update !>(act)]~
:: ::
++ send-diff ++ send-diff
|= [pax=path act=group-action] |= [pax=path act=group-action]

View File

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

View File

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

View File

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

View File

@ -153,7 +153,7 @@
=/ dat=(unit [json url=@t]) (~(get by data) name) =/ dat=(unit [json url=@t]) (~(get by data) name)
?~ dat [~ this] ?~ dat [~ this]
:_ this(data (~(put by data) name [jon url.u.dat])) :_ 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 ++ on-arvo
|= [wir=wire sin=sign-arvo] |= [wir=wire sin=sign-arvo]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -243,7 +243,7 @@
++ write-file ++ write-file
=, space:userlib =, space:userlib
|= [pax=path cay=cage] |= [pax=path cay=cage]
^- card ^- card
=. pax (weld our-beak pax) =. pax (weld our-beak pax)
[%pass (weld /write-file pax) %arvo %c %info (foal pax cay)] [%pass (weld /write-file pax) %arvo %c %info (foal pax cay)]
:: ::
@ -730,15 +730,15 @@
++ affection-primary ++ affection-primary
|= del=delta |= del=delta
^- (list card) ^- (list card)
[%give %fact `/primary %publish-rumor !>(del)]~ [%give %fact ~[/primary] %publish-rumor !>(del)]~
:: +affection: rumors to interested :: +affection: rumors to interested
:: ::
++ affection ++ affection
|= del=delta |= del=delta
^- (list card) ^- (list card)
=/ wir=wire /collection/[col.del] =/ wir=wire /collection/[col.del]
:~ [%give %fact `/primary %publish-rumor !>(del)] :~ [%give %fact ~[/primary] %publish-rumor !>(del)]
[%give %fact `wir %publish-rumor !>(del)] [%give %fact ~[wir] %publish-rumor !>(del)]
== ==
:: ::
++ get-post-by-index ++ get-post-by-index
@ -1263,7 +1263,7 @@
=/ upd=update [%invite %.y src.bol coll.act title.act] =/ upd=update [%invite %.y src.bol coll.act title.act]
:_ state :_ state
%+ welp make-tile-moves %+ 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 :: %reject-invite: remove invite from list, acceptance is handled by
:: %subscribe action :: %subscribe action
@ -1276,7 +1276,7 @@
=/ upd=update [%invite %.n who.act coll.act u.title] =/ upd=update [%invite %.n who.act coll.act u.title]
:_ state :_ state
%+ welp make-tile-moves %+ welp make-tile-moves
[%give %fact `/primary %publish-update !>(upd)]~ [%give %fact ~[/primary] %publish-update !>(upd)]~
:: ::
:: %serve: :: %serve:
:: ::
@ -1406,7 +1406,7 @@
[%pass wir %agent [who.act %publish] %watch wir]~ [%pass wir %agent [who.act %publish] %watch wir]~
?~ title ~ ?~ title ~
=/ upd=update [%invite %.n who.act coll.act u.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 :: %unsubscribe: unsub from a foreign blog, delete all state related to it
@ -1435,7 +1435,7 @@
:- [%pass wir %agent [who.act %publish] %leave ~] :- [%pass wir %agent [who.act %publish] %leave ~]
%+ welp make-tile-moves %+ welp make-tile-moves
=/ rum=rumor [%remove who.act coll.act ~] =/ 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 :: %read: notify that we've seen a post
:: ::
@ -1445,7 +1445,7 @@
%+ welp make-tile-moves %+ welp make-tile-moves
:: ::
=/ upd=update [%unread %.n (sy [who.act coll.act post.act] ~)] =/ 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 ++ make-tile-moves
^- (list card) ^- (list card)
[%give %fact `/publishtile %json !>(make-tile-json)]~ [%give %fact ~[/publishtile] %json !>(make-tile-json)]~
:: ::
++ make-tile-json ++ make-tile-json
^- 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 /- spider
/+ libstrand=strand, default-agent, verb /+ libstrand=strand, default-agent, verb
=, strand=strand:libstrand =, strand=strand:libstrand
@ -127,9 +125,6 @@
|- ^- (quip card _this) |- ^- (quip card _this)
?~ yarns ?~ yarns
`this `this
?. ?=([@ ~] i.yarns)
$(yarns t.yarns)
~| killing=i.yarns
=^ cards-1 state =^ cards-1 state
(handle-stop-thread:sc (yarn-to-tid i.yarns) |) (handle-stop-thread:sc (yarn-to-tid i.yarns) |)
=^ cards-2 this =^ cards-2 this
@ -139,8 +134,6 @@
++ on-poke ++ on-poke
|= [=mark =vase] |= [=mark =vase]
^- (quip card _this) ^- (quip card _this)
?: ?=(%spider-kill mark)
(on-load on-save)
=^ cards state =^ cards state
?+ mark (on-poke:def mark vase) ?+ mark (on-poke:def mark vase)
%spider-input (on-poke-input:sc !<(input vase)) %spider-input (on-poke-input:sc !<(input vase))
@ -357,15 +350,12 @@
^- ^card ^- ^card
?+ card card ?+ card card
[%pass * *] [%pass [%thread tid p.card] q.card] [%pass * *] [%pass [%thread tid p.card] q.card]
[%give %fact *] [%give ?(%fact %kick) *]
?~ path.p.card =- card(paths.p -)
card %+ turn paths.p.card
card(path.p `[%thread tid u.path.p.card]) |= =path
:: ^- ^path
[%give %kick *] [%thread tid path]
?~ path.p.card
card
card(path.p `[%thread tid u.path.p.card])
== ==
=. cards (weld cards cards.r) =. cards (weld cards cards.r)
=^ final-cards=(list card) state =^ final-cards=(list card) state
@ -391,13 +381,14 @@
++ thread-say-fail ++ thread-say-fail
|= [=tid =term =tang] |= [=tid =term =tang]
^- (list card) ^- (list card)
:~ [%give %fact `/thread-result/[tid] %thread-fail !>([term tang])] :~ [%give %fact ~[/thread-result/[tid]] %thread-fail !>([term tang])]
[%give %kick `/thread-result/[tid] ~] [%give %kick ~[/thread-result/[tid]] ~]
== ==
:: ::
++ thread-fail ++ thread-fail
|= [=yarn =term =tang] |= [=yarn =term =tang]
^- (quip card ^state) ^- (quip card ^state)
%- (slog leaf+"strand {<yarn>} failed" leaf+<term> tang)
=/ =tid (yarn-to-tid yarn) =/ =tid (yarn-to-tid yarn)
=/ fail-cards (thread-say-fail tid term tang) =/ fail-cards (thread-say-fail tid term tang)
=^ cards state (thread-clean yarn) =^ cards state (thread-clean yarn)
@ -409,8 +400,8 @@
:: %- (slog leaf+"strand {<yarn>} finished" (sell vase) ~) :: %- (slog leaf+"strand {<yarn>} finished" (sell vase) ~)
=/ =tid (yarn-to-tid yarn) =/ =tid (yarn-to-tid yarn)
=/ done-cards=(list card) =/ done-cards=(list card)
:~ [%give %fact `/thread-result/[tid] %thread-done vase] :~ [%give %fact ~[/thread-result/[tid]] %thread-done vase]
[%give %kick `/thread-result/[tid] ~] [%give %kick ~[/thread-result/[tid]] ~]
== ==
=^ cards state (thread-clean yarn) =^ cards state (thread-clean yarn)
[(weld done-cards cards) state] [(weld done-cards cards) state]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,55 +1,89 @@
:: Ames extends Arvo's %pass/%give move semantics across the network. :: Ames extends Arvo's %pass/%give move semantics across the network.
:: ::
:: A "forward flow" message, which is like a request, is passed to :: Ames receives packets as Arvo events and emits packets as Arvo
:: Ames from a local vane. Ames transmits the message to the peer's :: effects. The runtime is responsible for transferring the bytes in
:: Ames, which passes the message to the destination vane. :: an Ames packet across a physical network to another ship.
:: ::
:: Once the peer has processed the "forward flow" message, it sends a :: The runtime tells Ames which physical address a packet came from,
:: message acknowledgment over the wire back to the local Ames. This :: represented as an opaque atom. Ames can emit a packet effect to
:: ack can either be positive or negative, in which case we call it a :: one of those opaque atoms or to the Urbit address of a galaxy
:: "nack". (Don't confuse Ames nacks with TCP nacks, which are a :: (root node), which the runtime is responsible for translating to a
:: different concept). :: 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 :: A local vane can pass Ames a %plea request message. Ames
:: combination of a nack and nack-trace (explained in more detail :: 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 :: 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 :: A local vane can give Ames zero or more %boon response messages in
:: subscription update, is given to Ames from a local vane. Ames :: response to a %plea, on the same duct that Ames used to pass the
:: transmits the message to the peer's Ames, which gives the message :: %plea to the vane. Ames transmits a %boon over the wire to the
:: to the destination vane. :: 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 :: %boon messages are acked automatically by the receiver Ames. They
:: remote. This message is a "backward flow" message, forming one of :: cannot be nacked, and Ames only uses the ack internally, without
:: potentially many responses to a "forward flow" message that a :: notifying the client vane that gave Ames the %boon.
:: 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.
:: ::
:: Backward flow messages are acked automatically by the receiver. :: If the Arvo event that completed receipt of a %boon message
:: They cannot be nacked, and Ames only uses the ack internally, :: crashes, Ames instead sends the client vane a %lost message
:: without notifying the client vane. :: indicating the %boon was missed.
:: ::
:: Forward flow messages can be nacked, in which case the peer will :: %plea messages can be nacked, in which case the peer will send
:: send both a message-nack packet and a nack-trace message, which is :: both a message-nack packet and a naxplanation message, which is
:: sent on a special diagnostic flow so as not to interfere with :: sent in a way that does not interfere with normal operation. The
:: normal operation. The nack-trace is sent as a full Ames message, :: naxplanation is sent as a full Ames message, instead of just a
:: instead of just a packet, because the contained error information :: packet, because the contained error information can be arbitrarily
:: can be arbitrarily large. :: 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 :: Ames guarantees a total ordering of messages within a "flow",
:: has received the full message and failed to process it. This :: identified in other vanes by a duct and over the wire by a "bone":
:: means if we later hear an ack packet on the failed message, we can :: an opaque number. Each flow has a FIFO queue of %plea requests
:: ignore it. :: 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 :: Message order across flows is not specified and may vary based on
:: when we receive a nack-trace for message n, we know the peer has :: network conditions.
:: 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 :: Ames guarantees that a message will only be delivered once to the
:: on all those messages, we apply positive acks when we hear the :: destination vane.
:: nack-trace. ::
:: 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 :: 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 :: The first bone is 0. They increment by 4, since each flow includes
:: a bit for each message determining forward vs. backward and a :: a bit for each message determining forward vs. backward and a
:: second bit for whether the message is on the normal flow or the :: 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 +$ ossuary
$: =next=bone $: =next=bone
@ -542,43 +584,40 @@
:: Messages queue up in |message-pump's .unsent-messages until they :: Messages queue up in |message-pump's .unsent-messages until they
:: can be packetized and fed into |packet-pump for sending. When we :: can be packetized and fed into |packet-pump for sending. When we
:: pop a message off .unsent-messages, we push as many fragments as :: pop a message off .unsent-messages, we push as many fragments as
:: we can into |packet-pump, then place the remaining in :: we can into |packet-pump, which sends every packet it eats.
:: .unsent-fragments. :: Packets rejected by |packet-pump are placed in .unsent-fragments.
:: ::
:: When we hear a packet ack, we send it to |packet-pump. If we :: When we hear a packet ack, we send it to |packet-pump to be
:: haven't seen it before, |packet-pump reports the fresh ack. :: removed from its queue of unacked packets.
:: ::
:: When we hear a message ack (positive or negative), we treat that :: When we hear a message ack (positive or negative), we treat that
:: as though all fragments have been acked. If this message is not :: 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 :: .current, then this ack is for a future message and .current has
:: acked, so we place the ack in .queued-message-acks. :: 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 :: If we hear a message ack before we've sent all the fragments for
:: fragments for that message, clear .unsent-fragments. If the :: that message, clear .unsent-fragments and have |packet-pump delete
:: message ack was positive, print it out because it indicates the :: all sent fragments from the message. If this early message ack was
:: peer is not behaving properly. :: 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, :: If the ack is for the current message, have |packet-pump delete
:: increment .current, and check if this next message is in :: all packets from the message, give the message ack back
:: .queued-message-acks. If it is, emit the message (n)ack, :: to the client vane, increment .current, and check if this next
:: increment .current, and check the next message. Repeat until :: message is in .queued-message-acks. If it is, emit the message
:: .current is not fully acked. :: (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.
:: ::
:: The following equation is always true: :: The following equation is always true:
:: .next - .current == number of messages in flight :: .next - .current == number of messages in flight
:: ::
:: At the end of a task, |message-pump sends a %halt task to :: 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 :: |packet-pump, which can trigger a timer to be set or cleared based
:: on congestion control calculations. When it fires, the timer will :: on congestion control calculations. When the timer fires, it will
:: generally cause one or more packets to be resent. :: generally cause a packet to be re-sent.
:: ::
:: Message sequence numbers start at 1 so the first message will be :: Message sequence numbers start at 1 so that the first message will
:: greater than .last-acked.message-sink-state on the receiver. :: be greater than .last-acked.message-sink-state on the receiver.
:: ::
:: current: sequence number of earliest message sent or being sent :: current: sequence number of earliest message sent or being sent
:: next: sequence number of next message to send :: next: sequence number of next message to send
@ -618,7 +657,14 @@
:: algorithm. The information signals and their responses are :: algorithm. The information signals and their responses are
:: identical to those of the "NewReno" variant of Reno; the :: identical to those of the "NewReno" variant of Reno; the
:: implementation differs because Ames acknowledgments differ from :: 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 :: If .skips reaches 3, we perform a fast retransmit and fast
:: recovery. This corresponds to Reno's handling of "three duplicate :: recovery. This corresponds to Reno's handling of "three duplicate
@ -697,8 +743,6 @@
== ==
:: $note: request to other vane :: $note: request to other vane
:: ::
:: TODO: specialize gall interface for subscription management
::
:: Ames passes a %plea note to another vane when it receives a :: Ames passes a %plea note to another vane when it receives a
:: message on a "forward flow" from a peer, originally passed from :: message on a "forward flow" from a peer, originally passed from
:: one of the peer's vanes to the peer's Ames. :: one of the peer's vanes to the peer's Ames.
@ -729,13 +773,6 @@
== == == == == ==
:: $sign: response from other vane :: $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 +$ sign
$~ [%b %wake ~] $~ [%b %wake ~]
$% $: %b $% $: %b
@ -1126,11 +1163,70 @@
-- --
:: +scry: dereference namespace :: +scry: dereference namespace
:: ::
:: The ones producing vases are expected to be used like this:
::
:: &tang [(sell .^(vase %a /=peer=/~zod)) ~]
::
++ scry ++ scry
|= [fur=(unit (set monk)) ren=@tas why=shop syd=desk lot=coin tyl=path] |= [fur=(unit (set monk)) ren=@tas why=shop syd=desk lot=coin tyl=path]
^- (unit (unit cage)) ^- (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 :: helpers
:: ::
@ -1381,10 +1477,15 @@
?> =(rcvr-life.shut-packet our-life.channel) ?> =(rcvr-life.shut-packet our-life.channel)
:: non-galaxy: update route with heard lane or forwarded lane :: non-galaxy: update route with heard lane or forwarded lane
:: ::
=? route.peer-state =? route.peer-state
?& !=(%czar (clan:title her.channel)) ?: =(%czar (clan:title her.channel))
!=([~ %& *] route.peer-state) %.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 ?~ origin.packet
`[direct=%.y lane] `[direct=%.y lane]
`[direct=%.n u.origin.packet] `[direct=%.n u.origin.packet]
@ -1512,6 +1613,7 @@
:: ::
:: Abandon all pretense of continuity and delete all messaging state :: Abandon all pretense of continuity and delete all messaging state
:: associated with .ship, including sent and unsent messages. :: associated with .ship, including sent and unsent messages.
:: Also cancel all timers related to .ship.
:: ::
++ on-publ-breach ++ on-publ-breach
|= =ship |= =ship
@ -2053,7 +2155,11 @@
++ send-shut-packet ++ send-shut-packet
|= =shut-packet |= =shut-packet
^+ peer-core ^+ 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) =. bone.shut-packet (mix 1 bone.shut-packet)
:: ::
@ -2201,7 +2307,7 @@
:: +on-sink-boon: handle response message received by |message-sink :: +on-sink-boon: handle response message received by |message-sink
:: ::
:: .bone must be mapped in .ossuary.peer-state, or we crash. :: .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 :: could change this to a no-op if we had some sort of security
:: reporting. :: reporting.
:: ::
@ -2491,7 +2597,7 @@
^+ message-pump ^+ message-pump
=/ top-live =/ top-live
(peek:packet-queue:*make-packet-pump live.packet-pump-state.state) (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] ~| [%strange-current current=current.state key.u.top-live]
!! !!
message-pump message-pump
@ -2654,7 +2760,7 @@
:: +on-hear: handle ack on a live packet :: +on-hear: handle ack on a live packet
:: ::
:: If the packet was in our queue, delete it and update our :: 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 ++ on-hear
|= [=message-num =fragment-num] |= [=message-num =fragment-num]

View File

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

View File

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

View File

@ -54,7 +54,7 @@
++ state ++ state
$: :: state version $: :: state version
:: ::
%2 %3
:: agents by ship :: agents by ship
:: ::
=agents =agents
@ -904,7 +904,7 @@
%give %give
=/ =gift:agent p.card =/ =gift:agent p.card
?: ?=(%kick -.gift) ?: ?=(%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 %+ turn ducts
|= =duct |= =duct
~? &(=(duct system-duct.agents.state) !=(agent-name %hood)) ~? &(=(duct system-duct.agents.state) !=(agent-name %hood))
@ -914,7 +914,7 @@
?. ?=(%fact -.gift) ?. ?=(%fact -.gift)
[agent-duct %give %unto 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 =/ =cage cage.gift
%+ turn ducts %+ turn ducts
|= =duct |= =duct
@ -1010,6 +1010,17 @@
:: ::
++ ap-agent-core ++ ap-agent-core
~(. agent.current-agent ap-construct-bowl) ~(. 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: get ducts subscribed to path
:: ::
++ ap-ducts-from-path ++ ap-ducts-from-path
@ -1567,16 +1578,177 @@
=? all-state ?=(%1 -.all-state) =? all-state ?=(%1 -.all-state)
(state-1-to-2 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) gall-payload(state all-state)
:: ::
:: +all-state: upgrade path :: +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-to-2
|= =state-1 |= =state-1
^- ^state ^- state-2
%= state-1 %= state-1
- %2 - %2
+.agents-1 [~ +.agents-1.state-1] +.agents-1 [~ +.agents-1.state-1]
@ -1590,7 +1762,7 @@
++ agents-1 ++ agents-1
$: system-duct=duct $: system-duct=duct
contacts=(set ship) contacts=(set ship)
running=(map term running-agent) running=(map term running-agent-2)
blocked=(map term blocked) blocked=(map term blocked)
== ==
:: ::
@ -1602,7 +1774,7 @@
running.agents-0 running.agents-0
%- ~(run by running.agents-0.state-0) %- ~(run by running.agents-0.state-0)
|= =running-agent-0 |= =running-agent-0
^- running-agent ^- running-agent-2
%= running-agent-0 %= running-agent-0
agent-0 (agent-0-to-1 agent-0.running-agent-0) agent-0 (agent-0-to-1 agent-0.running-agent-0)
== ==
@ -1610,7 +1782,7 @@
:: ::
++ agent-0-to-1 ++ agent-0-to-1
|= =agent-0 |= =agent-0
^- agent ^- agent-2
|_ =bowl:gall |_ =bowl:gall
+* this . +* this .
pass ~(. agent-0 bowl) pass ~(. agent-0 bowl)
@ -1692,7 +1864,7 @@
+$ card (wind note gift) +$ card (wind note gift)
+$ note note:agent +$ note note:agent
+$ task task:agent +$ task task:agent
+$ gift gift:agent +$ gift gift:agent-2
+$ sign sign:agent +$ sign sign:agent
++ form ++ form
$_ ^| $_ ^|

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -308,7 +308,7 @@
:~ :* duct=~[/http-blah] %give %response :~ :* duct=~[/http-blah] %give %response
[%start [200 ['content-type' 'text/html']~] ~ %.n] [%start [200 ['content-type' 'text/html']~] ~ %.n]
== == == == == ==
;: weld ;: weld
results1 results1
results2 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('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('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('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.series('tile-jsx-transform', 'tile-js-imports', 'tile-js-minify'));
gulp.task('bundle-dev', gulp.task('bundle-dev',

View File

@ -99,6 +99,21 @@ h2 {
word-break: break-all; 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 */ /* responsive */
@media all and (max-width: 34.375em) { @media all and (max-width: 34.375em) {
@ -114,6 +129,9 @@ h2 {
.h-100-minus-96-s { .h-100-minus-96-s {
height: calc(100% - 96px); height: calc(100% - 96px);
} }
.embed-container {
padding-bottom: 56.25%;
}
} }
@media all and (min-width: 34.375em) and (max-width: 46.875em) { @media all and (min-width: 34.375em) and (max-width: 46.875em) {
@ -123,6 +141,9 @@ h2 {
.h-100-minus-48-m { .h-100-minus-48-m {
height: calc(100% - 48px); height: calc(100% - 48px);
} }
.embed-container {
padding-bottom: 56.25%;
}
} }
@media all and (min-width: 46.875em) and (max-width: 60em) { @media all and (min-width: 46.875em) and (max-width: 60em) {
@ -132,6 +153,9 @@ h2 {
.h-100-minus-48-l { .h-100-minus-48-l {
height: calc(100% - 48px); height: calc(100% - 48px);
} }
.embed-container {
padding-bottom: 37.5%;
}
} }
@media all and (min-width: 60em) { @media all and (min-width: 60em) {
@ -141,4 +165,52 @@ h2 {
.h-100-minus-48-xl { .h-100-minus-48-xl {
height: calc(100% - 48px); 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), add: this.groupAdd.bind(this),
remove: this.groupRemove.bind(this) remove: this.groupRemove.bind(this)
}; };
this.chat = { this.chat = {
message: this.chatMessage.bind(this), message: this.chatMessage.bind(this),
read: this.chatRead.bind(this) read: this.chatRead.bind(this)
@ -25,7 +25,7 @@ class UrbitApi {
delete: this.chatViewDelete.bind(this), delete: this.chatViewDelete.bind(this),
join: this.chatViewJoin.bind(this), join: this.chatViewJoin.bind(this),
}; };
this.invite = { this.invite = {
accept: this.inviteAccept.bind(this), accept: this.inviteAccept.bind(this),
decline: this.inviteDecline.bind(this), decline: this.inviteDecline.bind(this),
@ -36,7 +36,7 @@ class UrbitApi {
bind(path, method, ship = this.authTokens.ship, app, success, fail, quit) { bind(path, method, ship = this.authTokens.ship, app, success, fail, quit) {
this.bindPaths = _.uniq([...this.bindPaths, path]); this.bindPaths = _.uniq([...this.bindPaths, path]);
window.subscriptionId = window.urb.subscribe(ship, app, path, window.subscriptionId = window.urb.subscribe(ship, app, path,
(err) => { (err) => {
fail(err); fail(err);
}, },
@ -59,7 +59,7 @@ class UrbitApi {
window.urb.poke(ship, appl, mark, data, window.urb.poke(ship, appl, mark, data,
(json) => { (json) => {
resolve(json); resolve(json);
}, },
(err) => { (err) => {
reject(err); reject(err);
}); });
@ -142,7 +142,7 @@ class UrbitApi {
} }
chatViewJoin(ship, path, askHistory) { chatViewJoin(ship, path, askHistory) {
this.chatViewAction({ this.chatViewAction({
join: { join: {
ship, path, ship, path,
'ask-history': askHistory 'ask-history': askHistory
@ -153,9 +153,9 @@ class UrbitApi {
inviteAction(data) { inviteAction(data) {
this.action("invite-store", "json", data); this.action("invite-store", "json", data);
} }
inviteInvite(path, ship) { inviteInvite(path, ship) {
this.action("invite-hook", "json", this.action("invite-hook", "json",
{ {
invite: { invite: {
path: '/chat', path: '/chat',
@ -180,7 +180,7 @@ class UrbitApi {
} }
}); });
} }
inviteDecline(uid) { inviteDecline(uid) {
this.inviteAction({ this.inviteAction({
decline: { decline: {

View File

@ -230,14 +230,15 @@ export class ChatScreen extends Component {
<Link to="/~chat/">{"⟵ All Chats"}</Link> <Link to="/~chat/">{"⟵ All Chats"}</Link>
</div> </div>
<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 }}> style={{ height: 48 }}>
<SidebarSwitcher <SidebarSwitcher
sidebarShown={this.props.sidebarShown} sidebarShown={this.props.sidebarShown}
popout={this.props.popout} popout={this.props.popout}
/> />
<Link to={`/~chat/` + isinPopout + `room` + state.station} <Link to={`/~chat/` + isinPopout + `room` + state.station}
className="pt2"> className="pt2 white-d">
<h2 <h2
className="mono dib f8 fw4 v-top" className="mono dib f8 fw4 v-top"
style={{ width: "max-content" }}> style={{ width: "max-content" }}>
@ -253,7 +254,7 @@ export class ChatScreen extends Component {
/> />
</div> </div>
<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" }} style={{ height: "100%", resize: "vertical" }}
onScroll={this.onScroll}> onScroll={this.onScroll}>
<div <div

View File

@ -80,9 +80,9 @@ export class JoinScreen extends Component {
render() { render() {
const { props } = this; 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 === "/")) { 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 />); let errElem = (<span />);
@ -95,7 +95,8 @@ export class JoinScreen extends Component {
} }
return ( 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 <div
className="w-100 dn-m dn-l dn-xl inter pt1 pb6 f8"> className="w-100 dn-m dn-l dn-xl inter pt1 pb6 f8">
<Link to="/~chat/">{"⟵ All Chats"}</Link> <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> <p className="f9 gray2 mb4">Chat names use lowercase, hyphens, and slashes.</p>
<textarea <textarea
ref={ e => { this.textarea = e; } } 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" placeholder="~zod/chatroom"
spellCheck="false" spellCheck="false"
rows={1} rows={1}

View File

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

View File

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

View File

@ -17,7 +17,7 @@ export class HeaderBar extends Component {
: "dn db-m db-l db-xl"; : "dn db-m db-l db-xl";
return ( 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}}> style={{ height: 48, padding: 8}}>
<a className="db" <a className="db"
style={{ background: '#1A1A1A', style={{ background: '#1A1A1A',

View File

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

View File

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

View File

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

View File

@ -80,7 +80,7 @@ export class InviteElement extends Component {
<div></div> <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) { if (state.error) {
modifyButtonClasses = modifyButtonClasses + ' gray3'; modifyButtonClasses = modifyButtonClasses + ' gray3';
} }
@ -96,7 +96,7 @@ export class InviteElement extends Component {
<div> <div>
<textarea <textarea
ref={ e => { this.textarea = e; } } 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={{ style={{
resize: 'none', resize: 'none',
height: 50 height: 50

View File

@ -16,14 +16,14 @@ export class MemberElement extends Component {
let actionElem; let actionElem;
if (props.ship === props.owner) { if (props.ship === props.owner) {
actionElem = ( 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 Host
</p> </p>
); );
} else if (window.ship !== props.ship && window.ship === props.owner) { } else if (window.ship !== props.ship && window.ship === props.owner) {
actionElem = ( actionElem = (
<a onClick={this.onRemove.bind(this)} <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 Ban
</a> </a>
); );
@ -38,7 +38,7 @@ export class MemberElement extends Component {
<Sigil ship={props.ship} size={32} /> <Sigil ship={props.ship} size={32} />
<p <p
className={ 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} ~{props.ship}
</p> </p>

View File

@ -8,14 +8,29 @@ import _ from 'lodash';
export class Message extends Component { 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() { renderContent() {
const { props } = this; const { props } = this;
let letter = props.msg.letter; let letter = props.msg.letter;
if ('code' in letter) { if ('code' in letter) {
let outputElement = let outputElement =
(!!letter.code.output && (!!letter.code.output &&
letter.code.output.length && letter.code.output.length > 0) ? letter.code.output.length && letter.code.output.length > 0) ?
( (
<pre className="clamp-attachment pa1 mt0 mb0"> <pre className="clamp-attachment pa1 mt0 mb0">
@ -34,10 +49,20 @@ export class Message extends Component {
let imgMatch = let imgMatch =
/(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF|GIF|webp|WEBP|webm|WEBM)$/ /(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF|GIF|webp|WEBP|webm|WEBM)$/
.exec(letter.url); .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; let contents = letter.url;
if (imgMatch) { if (imgMatch) {
contents = ( contents = (
<img <img
className="o-60-d"
src={letter.url} src={letter.url}
style={{ style={{
width: "50%", width: "50%",
@ -45,18 +70,58 @@ export class Message extends Component {
}} }}
></img> ></img>
); );
} return (
return ( <a className="f7 lh-copy v-top bb word-break-all"
<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 (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} href={letter.url}
target="_blank" target="_blank"
rel="noopener noreferrer"> rel="noopener noreferrer">
{contents} {letter.url}
</a> </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) { } else if ('me' in letter) {
return ( return (
<p className='f7 lh-copy v-top'> <p className='f7 i lh-copy v-top'>
{letter.me} {letter.me}
</p> </p>
); );
@ -70,7 +135,7 @@ export class Message extends Component {
&& (chatroom[0] === letter.text))) { // entire message is room name? && (chatroom[0] === letter.text))) { // entire message is room name?
return ( return (
<Link <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}> to={"/~chat/join/" + chatroom.input}>
{letter.text} {letter.text}
</Link> </Link>
@ -89,7 +154,7 @@ export class Message extends Component {
render() { render() {
const { props } = this; const { props } = this;
let pending = !!props.msg.pending ? ' o-40' : ''; 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'} : ''; let paddingTop = props.paddingTop ? {'paddingTop': '6px'} : '';
@ -108,22 +173,22 @@ export class Message extends Component {
<Sigil <Sigil
ship={props.msg.author} ship={props.msg.author}
size={24} size={24}
color={((props.msg.author === window.ship) color={((props.msg.author === window.ship)
|| (props.msg.author.substr(1) === window.ship)) || (props.msg.author.substr(1) === window.ship))
? "#4330FC" ? "#4330FC"
: "#000000"} : "#000000"}
/> />
</div> </div>
<div <div
className="fr clamp-message" className="fr clamp-message white-d"
style={{ flexGrow: 1, marginTop: -8 }}> style={{ flexGrow: 1, marginTop: -8 }}>
<div className="hide-child" style={paddingTop}> <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.slice(0, 1) === "~" ? "" : "~"}
{props.msg.author} {props.msg.author}
</p> </p>
<p className="v-mid mono f9 gray dib">{timestamp}</p> <p className="v-mid mono f9 gray2 dib">{timestamp}</p>
<p className="v-mid mono f9 ml2 gray dib child dn-s">{datestamp}</p> <p className="v-mid mono f9 ml2 gray2 dib child dn-s">{datestamp}</p>
</div> </div>
{this.renderContent()} {this.renderContent()}
</div> </div>
@ -138,9 +203,9 @@ export class Message extends Component {
style={{ style={{
minHeight: "min-content" minHeight: "min-content"
}}> }}>
<p className="child pt2 pl2 pr1 mono f9 gray dib">{timestamp}</p> <p className="child pt2 pl2 pr1 mono f9 gray2 dib">{timestamp}</p>
<div className="fr f7 clamp-message" style={{ flexGrow: 1 }}> <div className="fr f7 clamp-message white-d pr3" style={{ flexGrow: 1 }}>
{this.renderContent()} {this.renderContent()}
</div> </div>
</div> </div>
); );

View File

@ -18,7 +18,7 @@ export class SidebarInvite extends Component {
return ( return (
<div className='pa3'> <div className='pa3'>
<div className='w-100 v-mid'> <div className='w-100 v-mid'>
<p className="dib f8 mono"> <p className="dib f8 mono gray4-d">
{props.invite.text} {props.invite.text}
</p> </p>
</div> </div>
@ -28,7 +28,7 @@ export class SidebarInvite extends Component {
Accept Invite Accept Invite
</a> </a>
<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)}> onClick={this.onDecline.bind(this)}>
Decline Decline
</a> </a>

View File

@ -37,7 +37,7 @@ export class SidebarItem extends Component {
getLetter(lett) { getLetter(lett) {
if ('text' in lett) { if ('text' in lett) {
return lett.text; return lett.text;
} else if ('url' in lett) { } else if ('url' in lett) {
return lett.url; return lett.url;
} else if ('code' in lett) { } else if ('code' in lett) {
@ -50,23 +50,23 @@ export class SidebarItem extends Component {
render() { render() {
const { props, state } = this; const { props, state } = this;
let unreadElem = !!props.unread let unreadElem = !!props.unread
? "fw7 green2" ? "fw7 green2"
: ""; : "";
let title = props.title.substr(1); let title = props.title.substr(1);
let description = this.getLetter(props.description); 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 ( return (
<div <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)}> onClick={this.onClick.bind(this)}>
<div className="w-100 v-mid"> <div className="w-100 v-mid">
<p className={"dib mono f8 " + unreadElem }> <p className={"dib mono f8 " + unreadElem }>
<span className={(unreadElem === "") ? "gray3" : ""}> <span className={(unreadElem === "") ? "gray3 gray2-d" : ""}>
{title.substr(0, title.indexOf("/"))}/ {title.substr(0, title.indexOf("/"))}/
</span> </span>
{title.substr(title.indexOf("/") + 1)} {title.substr(title.indexOf("/") + 1)}

View File

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

View File

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

View File

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

View File

@ -49,7 +49,7 @@ export class SettingsScreen extends Component {
let chatOwner = (deSig(props.match.params.ship) === window.ship); 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"; let leaveButtonClasses = (!chatOwner) ? "pointer" : "c-default";
return ( return (
@ -58,7 +58,7 @@ export class SettingsScreen extends Component {
<p className="f8 mt3 lh-copy db">Leave Chat</p> <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> <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} <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>
<div className={"w-100 fl mt3 " + ((!chatOwner) ? 'o-30' : '')}> <div className={"w-100 fl mt3 " + ((!chatOwner) ? 'o-30' : '')}>
<p className="f8 mt3 lh-copy db">Delete Chat</p> <p className="f8 mt3 lh-copy db">Delete Chat</p>
@ -83,21 +83,21 @@ export class SettingsScreen extends Component {
} }
return ( 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 <div
className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8" className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8"
style={{ height: "1rem" }}> style={{ height: "1rem" }}>
<Link to="/~chat/">{"⟵ All Chats"}</Link> <Link to="/~chat/">{"⟵ All Chats"}</Link>
</div> </div>
<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 }}> style={{ height: 48 }}>
<SidebarSwitcher <SidebarSwitcher
sidebarShown={this.props.sidebarShown} sidebarShown={this.props.sidebarShown}
popout={this.props.popout} popout={this.props.popout}
/> />
<Link to={`/~chat/` + isinPopout + `room` + state.station} <Link to={`/~chat/` + isinPopout + `room` + state.station}
className="pt2"> className="pt2 white-d">
<h2 <h2
className="mono dib f8 fw4 v-top" className="mono dib f8 fw4 v-top"
style={{ width: "max-content" }}> style={{ width: "max-content" }}>
@ -118,7 +118,7 @@ export class SettingsScreen extends Component {
} }
return ( 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 <div
className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8" className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8"
style={{ height: "1rem" }}> style={{ height: "1rem" }}>

View File

@ -71,18 +71,19 @@ export class Sidebar extends Component {
}); });
return ( 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"> <div className="overflow-y-auto h-100">
{sidebarInvites} {sidebarInvites}
{sidebarItems} {sidebarItems}
</div> </div>
<div className="absolute z2 tc w-100 bg-transparent" <div className="absolute z2 tc w-100 bg-transparent"
style={{ bottom: 10 }}> 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)}> onClick={this.onClickNew.bind(this)}>
Create New Chat Create New Chat
</a> </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)}> onClick={this.onClickJoin.bind(this)}>
Join Existing Chat Join Existing Chat
</a> </a>

View File

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

View File

@ -26,9 +26,9 @@ export class ChatUpdateReducer {
messages(json, state) { messages(json, state) {
let data = _.get(json, 'messages', false); let data = _.get(json, 'messages', false);
if (data) { if (data) {
state.inbox[data.path].envelopes = state.inbox[data.path].envelopes =
data.envelopes.concat(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; state.inbox[data.path].config.length + data.envelopes.length;
} }
} }
@ -60,7 +60,7 @@ export class ChatUpdateReducer {
delete state.inbox[data.path]; delete state.inbox[data.path];
} }
} }
pending(json, state) { pending(json, state) {
let msg = _.get(json, 'message', false); let msg = _.get(json, 'message', false);
if (!msg || !state.pendingMessages.has(msg.path)) { 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 ( return (
<BrowserRouter> <BrowserRouter>
<div> <div>
<Route exact path="/" <Route exact path="/"
render={ (props) => { render={ (props) => {
return ( return (
<Home <Home
{...props} {...props}
data={this.state} data={this.state}
keys={new Set(Object.keys(this.state))} keys={new Set(Object.keys(this.state))}
/> />
); );

View File

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

View File

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

View File

@ -1,7 +1,7 @@
class Api { class Api {
bind(app, path, success, fail, ship) { bind(app, path, success, fail, ship) {
window.urb.subscribe(ship, app, path, window.urb.subscribe(ship, app, path,
(err) => { (err) => {
fail(err, app, path, ship); fail(err, app, path, ship);
}, },
@ -25,7 +25,7 @@ class Api {
window.urb.poke(ship, appl, mark, data, window.urb.poke(ship, appl, mark, data,
(json) => { (json) => {
resolve(json); resolve(json);
}, },
(err) => { (err) => {
reject(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('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('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('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.series('tile-jsx-transform', 'tile-js-imports', 'tile-js-minify'));
gulp.task('bundle-dev', gulp.task('bundle-dev',

View File

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

View File

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

View File

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

View File

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

View File

@ -51,7 +51,7 @@ export class BlogSubs extends Component {
.split(/[\s,]+/) .split(/[\s,]+/)
.map(t => t.trim()); .map(t => t.trim());
let valid = tokens.reduce((valid, s) => let valid = tokens.reduce((valid, s) =>
valid && ((s !== '~') && urbitOb.isValidPatp(s) && s.includes('~')), true); valid && ((s !== '~') && urbitOb.isValidPatp(s) && s.includes('~')), true);
if (valid) { if (valid) {
@ -86,7 +86,7 @@ export class BlogSubs extends Component {
render() { render() {
let back = '<- Back to notes' let back = '<- Back to notes'
let subscribers = this.props.subs.map((sub, i) => { let subscribers = this.props.subs.map((sub, i) => {
return ( return (
<div className="flex w-100" key={i+1}> <div className="flex w-100" key={i+1}>
@ -113,7 +113,7 @@ export class BlogSubs extends Component {
</p> </p>
<div className="flex"> <div className="flex">
<div className="flex-col w-100"> <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" <p className="gray-50 label-small-2"
style={{marginTop:12, marginBottom: 23}}> style={{marginTop:12, marginBottom: 23}}>
Everyone subscribed to this notebook Everyone subscribed to this notebook
@ -121,7 +121,7 @@ export class BlogSubs extends Component {
{subscribers} {subscribers}
</div> </div>
<div className="flex-col w-100"> <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" <p className="gray-50 label-small-2"
style={{marginTop:12, marginBottom: 23}}> style={{marginTop:12, marginBottom: 23}}>
Invite people to subscribe to this notebook 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"
: "body-regular-400 w-100 gray-30"; : "body-regular-400 w-100 gray-30";
return ( return (
<div className="cb w-100 flex" <div className="cb w-100 flex"
style={{paddingBottom: 8, marginTop: 32}}> style={{paddingBottom: 8, marginTop: 32}}>
<div className="fl" style={{marginRight: 10}}> <div className="fl" style={{marginRight: 10}}>
<Sigil ship={this.props.our} size={36}/> <Sigil ship={this.props.our} size={36}/>
@ -67,10 +67,10 @@ export class CommentBox extends Component {
onChange={this.commentChange} onChange={this.commentChange}
disabled={(!this.props.enabled)}> disabled={(!this.props.enabled)}>
</textarea> </textarea>
<PostButton <PostButton
post={this.props.post} post={this.props.post}
enabled={(Boolean(this.props.content) && this.props.enabled)} enabled={(Boolean(this.props.content) && this.props.enabled)}
/> />
</div> </div>
</div> </div>
); );

View File

@ -12,7 +12,7 @@ export class Comments extends Component {
commentBody: '', commentBody: '',
awaiting: false, awaiting: false,
} }
this.toggleDisplay = this.toggleDisplay.bind(this); this.toggleDisplay = this.toggleDisplay.bind(this);
this.commentChange = this.commentChange.bind(this); this.commentChange = this.commentChange.bind(this);
this.postComment = this.postComment.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 className="fl bb b-gray-30 w-16" >
</div> </div>
<NavLink exact <NavLink exact
className="header-menu-item" className="header-menu-item"
to="/~publish/recent" to="/~publish/recent"
activeStyle={{ activeStyle={{
@ -44,7 +44,7 @@ export class HeaderMenu extends Component {
<div className="fl bb b-gray-30 w-16" > <div className="fl bb b-gray-30 w-16" >
</div> </div>
<NavLink exact <NavLink exact
className="header-menu-item" className="header-menu-item"
to="/~publish/subs" to="/~publish/subs"
activeStyle={{ activeStyle={{
@ -58,7 +58,7 @@ export class HeaderMenu extends Component {
<div className="fl bb b-gray-30 w-16" > <div className="fl bb b-gray-30 w-16" >
</div> </div>
<NavLink exact <NavLink exact
className="header-menu-item" className="header-menu-item"
to="/~publish/pubs" to="/~publish/pubs"
activeStyle={{ activeStyle={{

View File

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

View File

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

View File

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

View File

@ -32,7 +32,7 @@ export class PathControl extends Component {
(last.lastMatch === '/~publish/:ship/:blog')){ (last.lastMatch === '/~publish/:ship/:blog')){
blog = (last.lastParams.ship.slice(1) == window.ship) blog = (last.lastParams.ship.slice(1) == window.ship)
? _.get(this.props, `pubs["${last.lastParams.blog}"]`, false) ? _.get(this.props, `pubs["${last.lastParams.blog}"]`, false)
: _.get(this.props, : _.get(this.props,
`subs["${last.lastParams.ship.slice(1)}"]["${last.lastParams.blog}"]`, false); `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, let page = this.parseContent(this.props.body.c,
this.props.body.gn, this.props.body.gn,
this.props.body.ga, this.props.body.ga,
null); null);
return page; return page;
} }
} }

View File

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

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