diff --git a/pkg/arvo/app/contact-hook.hoon b/pkg/arvo/app/contact-hook.hoon index bf66c27cd..e34b2ad8b 100644 --- a/pkg/arvo/app/contact-hook.hoon +++ b/pkg/arvo/app/contact-hook.hoon @@ -19,7 +19,7 @@ +$ state-zero [%0 state-base] +$ state-one [%1 state-base] +$ state-base - $: synced=(map path ship) + $: =synced invite-created=_| == -- @@ -77,6 +77,7 @@ ^- (quip card _this) ?+ path (on-watch:def path) [%contacts *] [(watch-contacts:cc t.path) this] + [%synced *] [(watch-synced:cc t.path) this] == :: ++ on-agent @@ -124,30 +125,29 @@ ++ poke-contact-action |= act=contact-action ^- (quip card _state) - |^ :_ state ?+ -.act !! %edit (handle-contact-action path.act ship.act act) %add (handle-contact-action path.act ship.act act) %remove (handle-contact-action path.act ship.act act) == - :: - ++ handle-contact-action - |= [=path =ship act=contact-action] - ^- (list card) - :: local - ?: (team:title our.bol src.bol) - =/ shp ?:(=(path /~/default) our.bol (~(got by synced) path)) - =/ appl ?:(=(shp our.bol) %contact-store %contact-hook) - [%pass / %agent [shp appl] %poke %contact-action !>(act)]~ - :: foreign - =/ shp (~(got by synced) path) - ?. |(=(shp our.bol) =(src.bol ship)) ~ - :: scry group to check if ship is a member - =/ =group (need (group-scry path)) - ?. (~(has in group) shp) ~ - [%pass / %agent [our.bol %contact-store] %poke %contact-action !>(act)]~ - -- +:: +++ handle-contact-action + |= [=path =ship act=contact-action] + ^- (list card) + :: local + ?: (team:title our.bol src.bol) + ?. (~(has by synced) path) ~ + =/ shp ?:(=(path /~/default) our.bol (~(got by synced) path)) + =/ appl ?:(=(shp our.bol) %contact-store %contact-hook) + [%pass / %agent [shp appl] %poke %contact-action !>(act)]~ + :: foreign + =/ shp (~(got by synced) path) + ?. |(=(shp our.bol) =(src.bol ship)) ~ + :: scry group to check if ship is a member + =/ =group (need (group-scry path)) + ?. (~(has in group) shp) ~ + [%pass / %agent [our.bol %contact-store] %poke %contact-action !>(act)]~ :: ++ poke-hook-action |= act=contact-hook-action @@ -160,7 +160,9 @@ [~ state] =. synced (~(put by synced) path.act our.bol) :_ state - [%pass contact-path %agent [our.bol %contact-store] %watch contact-path]~ + :~ [%pass contact-path %agent [our.bol %contact-store] %watch contact-path] + [%give %fact [/synced]~ %contact-hook-update !>([%initial synced])] + == :: %add-synced ?> (team:title our.bol src.bol) @@ -168,7 +170,9 @@ =. synced (~(put by synced) path.act ship.act) =/ contact-path [%contacts path.act] :_ state - [%pass contact-path %agent [ship.act %contact-hook] %watch contact-path]~ + :~ [%pass contact-path %agent [ship.act %contact-hook] %watch contact-path] + [%give %fact [/synced]~ %contact-hook-update !>([%initial synced])] + == :: %remove =/ ship (~(get by synced) path.act) @@ -179,13 +183,20 @@ %- zing :~ (pull-wire [%contacts path.act]) [%give %kick ~[[%contacts path.act]] ~]~ + [%give %fact [/synced]~ %contact-hook-update !>([%initial synced])]~ == ?. |(=(u.ship src.bol) (team:title our.bol src.bol)) :: if neither ship = source or source = us, do nothing [~ state] :: delete a foreign ship's path - :- (pull-wire [%contacts path.act]) - state(synced (~(del by synced) path.act)) + =/ cards + (handle-contact-action path.act our.bol [%remove path.act our.bol]) + :_ state(synced (~(del by synced) path.act)) + %- zing + :~ (pull-wire [%contacts path.act]) + [%give %fact [/synced]~ %contact-hook-update !>([%initial synced])]~ + cards + == == :: ++ watch-contacts @@ -197,10 +208,13 @@ =/ =group (need (group-scry pax)) ?> (~(has in group) src.bol) =/ contacts (need (contacts-scry pax)) - :~ :* - %give %fact ~ %contact-update - !>([%contacts pax contacts]) - == == + [%give %fact ~ %contact-update !>([%contacts pax contacts])]~ +:: +++ watch-synced + |= pax=path + ^- (list card) + ?> (team:title our.bol src.bol) + [%give %fact ~ %contact-hook-update !>([%initial synced])]~ :: ++ watch-ack |= [wir=wire saw=(unit tang)] @@ -308,13 +322,15 @@ == :: %add - =/ owner (~(got by synced) path.fact) - ?> |(=(owner src.bol) =(src.bol ship.fact)) + =/ owner (~(get by synced) path.fact) + ?~ owner ~ + ?> |(=(u.owner src.bol) =(src.bol ship.fact)) ~[(contact-poke [%add path.fact ship.fact contact.fact])] :: %remove - =/ owner (~(got by synced) path.fact) - ?> |(=(owner src.bol) =(src.bol ship.fact)) + =/ owner (~(get by synced) path.fact) + ?~ owner ~ + ?> |(=(u.owner src.bol) =(src.bol ship.fact)) %+ welp :~ (group-poke [%remove [ship.fact ~ ~] path.fact]) (contact-poke [%remove path.fact ship.fact]) @@ -353,7 +369,8 @@ |= =path ^- (quip card _state) ?. (~(has by synced) path) - [~ state] + :_ state + [(contact-poke [%delete path])]~ :_ state(synced (~(del by synced) path)) :~ [%pass [%contacts path] %agent [our.bol %contact-store] %leave ~] [(contact-poke [%delete path])] diff --git a/pkg/arvo/app/contact-store.hoon b/pkg/arvo/app/contact-store.hoon index 7792e7918..398ef15b0 100644 --- a/pkg/arvo/app/contact-store.hoon +++ b/pkg/arvo/app/contact-store.hoon @@ -142,7 +142,7 @@ |= [=path =ship] ^- (quip card _state) =/ contacts (~(got by rolodex) path) - ?> (~(has by contacts) ship) + ?. (~(has by contacts) ship) [~ state] =. contacts (~(del by contacts) ship) :- (send-diff path [%remove path ship]) state(rolodex (~(put by rolodex) path contacts)) diff --git a/pkg/arvo/app/contact-view.hoon b/pkg/arvo/app/contact-view.hoon index 9c85c135d..1bfd5a69a 100644 --- a/pkg/arvo/app/contact-view.hoon +++ b/pkg/arvo/app/contact-view.hoon @@ -147,9 +147,9 @@ :: %delete %+ weld - :~ (group-poke [%unbundle path.act]) + :~ (contact-hook-poke [%remove path.act]) + (group-poke [%unbundle path.act]) (contact-poke [%delete path.act]) - (contact-hook-poke [%remove path.act]) == (delete-metadata path.act) :: diff --git a/pkg/arvo/app/group-hook.hoon b/pkg/arvo/app/group-hook.hoon index 47ccc1d42..7cfc83188 100644 --- a/pkg/arvo/app/group-hook.hoon +++ b/pkg/arvo/app/group-hook.hoon @@ -38,18 +38,12 @@ ^- (quip card _this) =/ old !<(state-zero vase) :_ this(state old) - %+ murn - ~(tap by synced.old) + %+ murn ~(tap by synced.old) |= [=path =ship] ^- (unit card) - =/ =wire - [(scot %p ship) %group path] - =/ =term - ?: =(our.bowl ship) - %group-store - %group-hook - ?: (~(has by wex.bowl) [wire ship term]) - ~ + =/ =wire [(scot %p ship) %group path] + =/ =term ?:(=(our.bowl ship) %group-store %group-hook) + ?: (~(has by wex.bowl) [wire ship term]) ~ `[%pass wire %agent [ship term] %watch [%group path]] :: ++ on-leave on-leave:def @@ -173,10 +167,9 @@ %remove [(update-subscribers [%group pax.diff] diff) state] :: %unbundle - :_ state(synced (~(del by synced.state) pax.diff)) - %+ snoc - (update-subscribers [%group pax.diff] diff) - [%give %kick [%group pax.diff]~ ~] + =/ ship (~(get by synced.state) pax.diff) + ?~ ship [~ state] + (poke-group-hook-action [%remove pax.diff]) == :: ++ handle-foreign @@ -185,7 +178,6 @@ ?- -.diff %keys [~ state] %bundle [~ state] - :: %path :_ state ?~ pax.diff ~ @@ -219,23 +211,24 @@ [(group-poke pax.diff diff)]~ :: %remove - :_ state - ?~ pax.diff ~ + ?~ pax.diff [~ state] =/ ship (~(get by synced.state) pax.diff) - ?~ ship ~ - ?. =(src.bol u.ship) ~ - [(group-poke pax.diff diff)]~ + ?~ ship [~ state] + ?. =(src.bol u.ship) [~ state] + ?. (~(has in members.diff) our.bol) [~ state] + =/ changes (poke-group-hook-action [%remove pax.diff]) + :_ +.changes + %+ welp -.changes + :~ (group-poke pax.diff diff) + (group-poke pax.diff [%unbundle pax.diff]) + == :: %unbundle - ?~ pax.diff - [~ state] + ?~ pax.diff [~ state] =/ ship (~(get by synced.state) pax.diff) - ?~ ship - [~ state] - ?. =(src.bol u.ship) - [~ state] - :_ state(synced (~(del by synced.state) pax.diff)) - [(group-poke pax.diff diff)]~ + ?~ ship [~ state] + ?. =(src.bol u.ship) [~ state] + (poke-group-hook-action [%remove pax.diff]) == :: ++ group-poke @@ -262,5 +255,4 @@ ?: =(u.shp our.bol) [%pass wir %agent [our.bol %group-store] %leave ~]~ [%pass wir %agent [u.shp %group-hook] %leave ~]~ -:: -- diff --git a/pkg/arvo/lib/contact-json.hoon b/pkg/arvo/lib/contact-json.hoon index c212e2708..cca3aa70e 100644 --- a/pkg/arvo/lib/contact-json.hoon +++ b/pkg/arvo/lib/contact-json.hoon @@ -1,10 +1,21 @@ -/- *contact-view +/- *contact-view, *contact-hook |% ++ nu :: parse number as hex |= jon/json ?> ?=({$s *} jon) (rash p.jon hex) :: +++ hook-update-to-json + |= upd=contact-hook-update + =, enjs:format + ^- json + %+ frond %contact-hook-update + %- pairs + %+ turn ~(tap by synced.upd) + |= [pax=^path shp=^ship] + ^- [cord json] + [(spat pax) s+(scot %p shp)] +:: ++ rolodex-to-json |= rolo=rolodex =, enjs:format diff --git a/pkg/arvo/mar/contact/hook-update.hoon b/pkg/arvo/mar/contact/hook-update.hoon new file mode 100644 index 000000000..a1bdebd7b --- /dev/null +++ b/pkg/arvo/mar/contact/hook-update.hoon @@ -0,0 +1,13 @@ +/+ *contact-json +|_ upd=contact-hook-update +++ grow + |% + ++ json (hook-update-to-json upd) + -- +:: +++ grab + |% + ++ noun contact-hook-update + -- +:: +-- diff --git a/pkg/arvo/sur/contact-hook.hoon b/pkg/arvo/sur/contact-hook.hoon index 0b196e5dd..5926ec5a5 100644 --- a/pkg/arvo/sur/contact-hook.hoon +++ b/pkg/arvo/sur/contact-hook.hoon @@ -12,4 +12,7 @@ :: [%remove =path] == +:: ++$ synced (map path ship) ++$ contact-hook-update [%initial =synced] -- diff --git a/pkg/interface/chat/src/js/components/lib/chat-input.js b/pkg/interface/chat/src/js/components/lib/chat-input.js index a9606367c..503e93b62 100644 --- a/pkg/interface/chat/src/js/components/lib/chat-input.js +++ b/pkg/interface/chat/src/js/components/lib/chat-input.js @@ -31,6 +31,7 @@ const MARKDOWN_CONFIG = { } }; + export class ChatInput extends Component { constructor(props) { super(props); @@ -116,6 +117,7 @@ export class ChatInput extends Component { return; } this.setState({ patpSearch: match[1].toLowerCase() }); + } clearSearch() { @@ -314,7 +316,6 @@ export class ChatInput extends Component { searchTerm={this.state.patpSearch} cm={this.editor} /> -
{ - api.contactHook.remove(props.path, `~${props.ship}`).then(() => { + api.contactView.delete(props.path).then(() => { let destination = (props.ship === window.ship) ? "" : props.path; this.setState({awaiting: false}); diff --git a/pkg/interface/groups/src/js/store.js b/pkg/interface/groups/src/js/store.js index f1ebad44c..47ac07316 100644 --- a/pkg/interface/groups/src/js/store.js +++ b/pkg/interface/groups/src/js/store.js @@ -9,14 +9,7 @@ import { LocalReducer } from '/reducers/local.js'; class Store { constructor() { - this.state = { - contacts: {}, - groups: {}, - associations: {}, - permissions: {}, - invites: {}, - selectedGroups: [] - }; + this.state = this.initialState(); this.initialReducer = new InitialReducer(); this.groupUpdateReducer = new GroupUpdateReducer(); @@ -28,6 +21,17 @@ class Store { this.setState = () => {}; } + initialState() { + return { + contacts: {}, + groups: {}, + associations: {}, + permissions: {}, + invites: {}, + selectedGroups: [] + }; + } + setStateHandler(setState) { this.setState = setState; } @@ -35,6 +39,11 @@ class Store { handleEvent(data) { let json = data.data; + if ('clear' in json && json.clear) { + this.setState(this.initialState()); + return; + } + console.log(json); this.initialReducer.reduce(json, this.state); this.groupUpdateReducer.reduce(json, this.state); diff --git a/pkg/interface/groups/src/js/subscription.js b/pkg/interface/groups/src/js/subscription.js index 081c6c386..269fc2fe0 100644 --- a/pkg/interface/groups/src/js/subscription.js +++ b/pkg/interface/groups/src/js/subscription.js @@ -5,48 +5,63 @@ import urbitOb from 'urbit-ob'; export class Subscription { + + constructor() { + this.firstRoundSubscriptionComplete = false; + } + start() { if (api.authTokens) { - this.initializeContacts(); + this.firstRoundSubscription(); + window.urb.setOnChannelError(this.onChannelError.bind(this)); } else { console.error("~~~ ERROR: Must set api.authTokens before operation ~~~"); } } - initializeContacts() { - api.bind('/primary', 'PUT', api.authTokens.ship, 'contact-view', + onChannelError(err) { + console.error('event source error: ', err); + console.log('initiating new channel'); + this.firstRoundSubscriptionComplete = false; + setTimeout(2000, () => { + store.handleEvent({ + data: { clear : true} + }); + this.start(); + }); + } + + subscribe(path, app) { + api.bind(path, 'PUT', api.authTokens.ship, app, this.handleEvent.bind(this), - this.handleError.bind(this), - this.handleQuitAndResubscribe.bind(this)); - api.bind('/primary', 'PUT', api.authTokens.ship, 'invite-view', - this.handleEvent.bind(this), - this.handleError.bind(this), - this.handleQuitAndResubscribe.bind(this)); - api.bind('/all', 'PUT', api.authTokens.ship, 'group-store', - this.handleEvent.bind(this), - this.handleError.bind(this), - this.handleQuitAndResubscribe.bind(this)); - api.bind('/all', 'PUT', api.authTokens.ship, 'metadata-store', - this.handleEvent.bind(this), - this.handleError.bind(this), - this.handleQuitAndResubscribe.bind(this)); + (err) => { + console.log(err); + this.subscribe(path, app); + }, + () => { + this.subscribe(path, app); + }); + } + + firstRoundSubscription() { + this.subscribe('/primary', 'contact-view'); + } + + secondRoundSubscriptions() { + this.subscribe('/synced', 'contact-hook'); + this.subscribe('/primary', 'invite-view'); + this.subscribe('/all', 'group-store'); + this.subscribe('/all', 'metadata-store'); } handleEvent(diff) { + if (!this.firstRoundSubscriptionComplete) { + this.firstRoundSubscriptionComplete = true; + this.secondRoundSubscriptions(); + } store.handleEvent(diff); } - handleError(err) { - console.error(err); - } - - handleQuitSilently(quit) { - // no-op - } - - handleQuitAndResubscribe(quit) { - // TODO: resubscribe - } } export let subscription = new Subscription(); diff --git a/pkg/interface/publish/src/css/custom.css b/pkg/interface/publish/src/css/custom.css index 5b068397e..5f225ebef 100644 --- a/pkg/interface/publish/src/css/custom.css +++ b/pkg/interface/publish/src/css/custom.css @@ -242,7 +242,7 @@ a { display: none; } -.md h1, .md h2, .md h3, .md h4, .md h5, .md p, .md a, .md ul, .md blockquote,.md code,.md pre { +.md h1, .md h2, .md h3, .md h4, .md h5, .md p, .md a, .md ul, .md ol, .md blockquote,.md code,.md pre { font-size: 14px; margin-bottom: 16px; } @@ -265,7 +265,7 @@ a { .md code, .md pre { font-family: "Source Code Pro", mono; } -.md ul>li { +.md ul>li, .md ol>li { line-height: 1.5; } .md a {