From b6e4566e61b49ae6a60e24aa911dcf1dd074edb1 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Mon, 13 Apr 2020 17:37:51 -0400 Subject: [PATCH 1/8] contacts: fix group deletion and do some quality of life fixes --- pkg/arvo/app/contact-hook.hoon | 10 ++- pkg/arvo/sur/contact-hook.hoon | 3 + .../src/js/components/lib/contact-card.js | 1 + pkg/interface/groups/src/js/subscription.js | 63 ++++++++++--------- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/pkg/arvo/app/contact-hook.hoon b/pkg/arvo/app/contact-hook.hoon index bf66c27cd..956f894b7 100644 --- a/pkg/arvo/app/contact-hook.hoon +++ b/pkg/arvo/app/contact-hook.hoon @@ -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 @@ -202,6 +203,12 @@ !>([%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)] ^- (quip card _state) @@ -353,7 +360,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/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/groups/src/js/components/lib/contact-card.js b/pkg/interface/groups/src/js/components/lib/contact-card.js index d02e5ddb4..dff7b4aa4 100644 --- a/pkg/interface/groups/src/js/components/lib/contact-card.js +++ b/pkg/interface/groups/src/js/components/lib/contact-card.js @@ -323,6 +323,7 @@ export class ContactCard extends Component { this.setState({awaiting: false}); props.history.push(`/~groups${destination}`); }); + api.contactView.delete(props.path); })) } diff --git a/pkg/interface/groups/src/js/subscription.js b/pkg/interface/groups/src/js/subscription.js index 081c6c386..aa0d23730 100644 --- a/pkg/interface/groups/src/js/subscription.js +++ b/pkg/interface/groups/src/js/subscription.js @@ -5,48 +5,53 @@ import urbitOb from 'urbit-ob'; export class Subscription { + + constructor() { + this.firstRoundSubscriptionComplete = false; + } + start() { if (api.authTokens) { - this.initializeContacts(); + this.firstRoundSubscription(); } else { console.error("~~~ ERROR: Must set api.authTokens before operation ~~~"); } } - initializeContacts() { - api.bind('/primary', 'PUT', api.authTokens.ship, 'contact-view', + 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); } handleEvent(diff) { store.handleEvent(diff); } - - handleError(err) { - console.error(err); - } - - handleQuitSilently(quit) { - // no-op - } - - handleQuitAndResubscribe(quit) { - // TODO: resubscribe - } } export let subscription = new Subscription(); From bfcaf6468ea34d11822d07186ce31a0912f3c90c Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 14 Apr 2020 21:57:21 +0000 Subject: [PATCH 2/8] contact-hook: tested it, got /synced path working, and subscriptions loading --- pkg/arvo/app/contact-hook.hoon | 17 +++++++++++++---- pkg/arvo/lib/contact-json.hoon | 13 ++++++++++++- pkg/arvo/mar/contact/hook-update.hoon | 13 +++++++++++++ pkg/interface/groups/src/js/subscription.js | 3 --- 4 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 pkg/arvo/mar/contact/hook-update.hoon diff --git a/pkg/arvo/app/contact-hook.hoon b/pkg/arvo/app/contact-hook.hoon index 956f894b7..ad7b53c8c 100644 --- a/pkg/arvo/app/contact-hook.hoon +++ b/pkg/arvo/app/contact-hook.hoon @@ -138,6 +138,7 @@ ^- (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)]~ @@ -161,7 +162,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 ~ %contact-hook-update !>([%initial synced])] + == :: %add-synced ?> (team:title our.bol src.bol) @@ -169,7 +172,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 ~ %contact-hook-update !>([%initial synced])] + == :: %remove =/ ship (~(get by synced) path.act) @@ -180,13 +185,17 @@ %- zing :~ (pull-wire [%contacts path.act]) [%give %kick ~[[%contacts path.act]] ~]~ + [%give %fact ~ %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)) + :_ state(synced (~(del by synced) path.act)) + %- zing + :~ (pull-wire [%contacts path.act]) + [%give %fact ~ %contact-hook-update !>([%initial synced])]~ + == == :: ++ watch-contacts 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/interface/groups/src/js/subscription.js b/pkg/interface/groups/src/js/subscription.js index aa0d23730..c7dc1b748 100644 --- a/pkg/interface/groups/src/js/subscription.js +++ b/pkg/interface/groups/src/js/subscription.js @@ -49,9 +49,6 @@ export class Subscription { store.handleEvent(diff); } - handleEvent(diff) { - store.handleEvent(diff); - } } export let subscription = new Subscription(); From 0145981542e93927fa880e0e087b49ca26df2318 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 14 Apr 2020 18:16:44 -0400 Subject: [PATCH 3/8] contact-js: made channel handle onChannelError --- pkg/interface/groups/src/js/store.js | 25 ++++++++++++++------- pkg/interface/groups/src/js/subscription.js | 13 +++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) 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 c7dc1b748..269fc2fe0 100644 --- a/pkg/interface/groups/src/js/subscription.js +++ b/pkg/interface/groups/src/js/subscription.js @@ -13,11 +13,24 @@ export class Subscription { start() { if (api.authTokens) { this.firstRoundSubscription(); + window.urb.setOnChannelError(this.onChannelError.bind(this)); } else { console.error("~~~ ERROR: Must set api.authTokens before operation ~~~"); } } + 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), From de077ffb4759d31a9eab33d50bba97b046a6ad78 Mon Sep 17 00:00:00 2001 From: Matilde Park Date: Tue, 21 Apr 2020 14:30:28 -0400 Subject: [PATCH 4/8] chat: set code toggle only at start of input --- pkg/interface/chat/src/js/components/lib/chat-input.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 55214b1e2..3a10e4f17 100644 --- a/pkg/interface/chat/src/js/components/lib/chat-input.js +++ b/pkg/interface/chat/src/js/components/lib/chat-input.js @@ -380,7 +380,7 @@ export class ChatInput extends Component { message = []; } - // perf: + // perf: //setTimeout(this.closure, 2000); this.editor.setValue(''); @@ -454,7 +454,9 @@ export class ChatInput extends Component { ? this.completePatp(state.selectedSuggestion) : this.messageSubmit(), 'Shift-3': (cm) => - this.toggleCode() + cm.getValue().length === 0 + ? this.toggleCode() + : CodeMirror.Pass } }; From 0e357373c0ebb5410111faaf5ff95b7b3d278822 Mon Sep 17 00:00:00 2001 From: Matilde Park Date: Tue, 21 Apr 2020 14:31:32 -0400 Subject: [PATCH 5/8] chat: lint chat-input.js --- .../chat/src/js/components/lib/chat-input.js | 190 ++++++++---------- 1 file changed, 81 insertions(+), 109 deletions(-) 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 3a10e4f17..ce04de716 100644 --- a/pkg/interface/chat/src/js/components/lib/chat-input.js +++ b/pkg/interface/chat/src/js/components/lib/chat-input.js @@ -1,9 +1,8 @@ import React, { Component } from 'react'; import _ from 'lodash'; import moment from 'moment'; -import Mousetrap from 'mousetrap'; import cn from 'classnames'; -import { UnControlled as CodeEditor } from 'react-codemirror2' +import { UnControlled as CodeEditor } from 'react-codemirror2'; import CodeMirror from 'codemirror'; import 'codemirror/mode/markdown/markdown'; @@ -11,54 +10,34 @@ import 'codemirror/addon/display/placeholder'; import { Sigil } from '/components/lib/icons/sigil'; -import { uuid, uxToHex, hexToRgba } from '/lib/util'; +import { uxToHex, hexToRgba } from '/lib/util'; const MARKDOWN_CONFIG = { - name: "markdown", + name: 'markdown', tokenTypeOverrides: { - header: "presentation", - quote: "presentation", - list1: "presentation", - list2: "presentation", - list3: "presentation", - hr: "presentation", - image: "presentation", - imageAltText: "presentation", - imageMarker: "presentation", - formatting: "presentation", - linkInline: "presentation", - linkEmail: "presentation", - linkText: "presentation", - linkHref: "presentation", + header: 'presentation', + quote: 'presentation', + list1: 'presentation', + list2: 'presentation', + list3: 'presentation', + hr: 'presentation', + image: 'presentation', + imageAltText: 'presentation', + imageMarker: 'presentation', + formatting: 'presentation', + linkInline: 'presentation', + linkEmail: 'presentation', + linkText: 'presentation', + linkHref: 'presentation' } -} - -// line height -const INPUT_LINE_HEIGHT = 28; - -const INPUT_TOP_PADDING = 3; - - -function getAdvance(a, b) { - let res = ''; - if(!a) { - return b; - } - for (let i = 0; i < Math.min(a.length, b.length); i++) { - if (a[i] !== b[i]) { - return res; - } - res = res.concat(a[i]); - } - return res; -} +}; function ChatInputSuggestion({ ship, contacts, selected, onSelect }) { - let contact = contacts[ship]; - let color = "#000000"; - let sigilClass = "v-mid mix-blend-diff" + const contact = contacts[ship]; + let color = '#000000'; + let sigilClass = 'v-mid mix-blend-diff'; let nickname; - let nameStyle = {}; + const nameStyle = {}; const isSelected = ship === selected; if (contact) { const hex = uxToHex(contact.color); @@ -66,7 +45,7 @@ function ChatInputSuggestion({ ship, contacts, selected, onSelect }) { nameStyle.color = hexToRgba(hex, .7); nameStyle.textShadow = '0px 0px 0px #000'; nameStyle.filter = 'contrast(1.3) saturate(1.5)'; - sigilClass = "v-mid"; + sigilClass = 'v-mid'; nickname = contact.nickname; } @@ -77,7 +56,7 @@ function ChatInputSuggestion({ ship, contacts, selected, onSelect }) { 'f8 pv1 ph3 pointer hover-bg-gray1-d hover-bg-gray4 relative flex items-center', { 'white-d bg-gray0-d bg-white': !isSelected, - 'black-d bg-gray1-d bg-gray4': isSelected, + 'black-d bg-gray1-d bg-gray4': isSelected } )} key={ship} @@ -99,7 +78,6 @@ function ChatInputSuggestion({ ship, contacts, selected, onSelect }) {

); - } function ChatInputSuggestions({ suggestions, onSelect, selected, contacts }) { @@ -112,14 +90,16 @@ function ChatInputSuggestions({ suggestions, onSelect, selected, contacts }) { className={ 'absolute black white-d bg-white bg-gray0-d ' + 'w7 pv3 z-1 mt1 ba b--gray1-d b--gray4' - }> + } + > {suggestions.map(ship => () + ship={ship} + />) )} ); @@ -150,9 +130,8 @@ export class ChatInput extends Component { this.editor = null; - // perf testing: - /*let closure = () => { + /* let closure = () => { let x = 0; for (var i = 0; i < 30; i++) { x++; @@ -174,21 +153,21 @@ export class ChatInput extends Component { past: function(input) { return input === 'just now' ? input - : input + ' ago' + : input + ' ago'; }, s : 'just now', - future: "in %s", + future: 'in %s', ss : '%d sec', - m: "a minute", - mm: "%d min", - h: "an hr", - hh: "%d hrs", - d: "a day", - dd: "%d days", - M: "a month", - MM: "%d months", - y: "a year", - yy: "%d years" + m: 'a minute', + mm: '%d min', + h: 'an hr', + hh: '%d hrs', + d: 'a day', + dd: '%d days', + M: 'a month', + MM: '%d months', + y: 'a year', + yy: '%d years' } }); } @@ -206,36 +185,33 @@ export class ChatInput extends Component { this.setState({ selectedSuggestion: patpSuggestions[idx] }); } - patpAutocomplete(message, fresh = false) { const match = /~([a-zA-Z\-]*)$/.exec(message); if (!match ) { - this.setState({ patpSuggestions: [] }) + this.setState({ patpSuggestions: [] }); return; } - const needle = match[1].toLowerCase(); - const matchString = hay => { + const matchString = (hay) => { hay = hay.toLowerCase(); return hay.startsWith(needle) || _.some(_.words(hay), s => s.startsWith(needle)); }; - const contacts = _.chain(this.props.contacts) .defaultTo({}) - .map((details, ship) => ({...details, ship })) + .map((details, ship) => ({ ...details, ship })) .filter(({ nickname, ship }) => matchString(nickname) || matchString(ship)) .map('ship') - .value() + .value(); const suggestions = _.chain(this.props.envelopes) .defaultTo([]) - .map("author") + .map('author') .uniq() .reverse() .filter(matchString) @@ -244,7 +220,7 @@ export class ChatInput extends Component { .take(5) .value(); - let newState = { + const newState = { patpSuggestions: suggestions, selectedSuggestion: suggestions[0] }; @@ -255,7 +231,7 @@ export class ChatInput extends Component { clearSuggestions() { this.setState({ patpSuggestions: [] - }) + }); } completePatp(suggestion) { @@ -276,15 +252,12 @@ export class ChatInput extends Component { } messageChange(editor, data, value) { - const { patpSuggestions } = this.state; if(patpSuggestions.length !== 0) { this.patpAutocomplete(value, false); } - } - getLetterType(letter) { if (letter.startsWith('/me')) { letter = letter.slice(3); @@ -296,22 +269,21 @@ export class ChatInput extends Component { return { me: letter - } + }; } else if (this.isUrl(letter)) { return { url: letter - } + }; } else { return { text: letter - } + }; } } isUrl(string) { try { - let websiteTest = new RegExp('' - + /((\w+:\/\/)[-a-zA-Z0-9:@;?&=\/%\+\.\*!'\(\),\$_\{\}\^~\[\]`#|]+)/.source + const websiteTest = new RegExp(String(/((\w+:\/\/)[-a-zA-Z0-9:@;?&=\/%\+\.\*!'\(\),\$_\{\}\^~\[\]`#|]+)/.source) ); return websiteTest.test(string); } catch (e) { @@ -341,10 +313,10 @@ export class ChatInput extends Component { return; } let message = []; - editorMessage.split(" ").map((each) => { + editorMessage.split(' ').map((each) => { if (this.isUrl(each)) { if (message.length > 0) { - message = message.join(" "); + message = message.join(' '); message = this.getLetterType(message); props.api.chat.message( props.station, @@ -354,22 +326,20 @@ export class ChatInput extends Component { ); message = []; } - let URL = this.getLetterType(each); + const URL = this.getLetterType(each); props.api.chat.message( props.station, `~${window.ship}`, Date.now(), URL ); - } - else { + } else { return message.push(each); } - }) - + }); if (message.length > 0) { - message = message.join(" "); + message = message.join(' '); message = this.getLetterType(message); props.api.chat.message( props.station, @@ -381,10 +351,9 @@ export class ChatInput extends Component { } // perf: - //setTimeout(this.closure, 2000); + // setTimeout(this.closure, 2000); this.editor.setValue(''); - } toggleCode() { @@ -395,7 +364,7 @@ export class ChatInput extends Component { } else { this.setState({ code: true }); this.editor.setOption('mode', null); - this.editor.setOption('placeholder', "Code..."); + this.editor.setOption('placeholder', 'Code...'); } const value = this.editor.getValue(); @@ -404,17 +373,16 @@ export class ChatInput extends Component { this.editor.setValue(' '); this.editor.setValue(''); } - } render() { const { props, state } = this; - let color = !!props.ownerContact + const color = props.ownerContact ? uxToHex(props.ownerContact.color) : '000000'; - let sigilClass = !!props.ownerContact - ? "" : "mix-blend-diff"; + const sigilClass = props.ownerContact + ? '' : 'mix-blend-diff'; const completeActive = this.state.patpSuggestions.length !== 0; @@ -427,43 +395,43 @@ export class ChatInput extends Component { lineWrapping: true, scrollbarStyle: 'native', cursorHeight: 0.85, - placeholder: state.code ? "Code..." : props.placeholder, + placeholder: state.code ? 'Code...' : props.placeholder, extraKeys: { - Tab: (cm) => + Tab: cm => completeActive ? this.nextAutocompleteSuggestion() : this.patpAutocomplete(cm.getValue(), true), - 'Shift-Tab': (cm) => + 'Shift-Tab': cm => completeActive ? this.nextAutocompleteSuggestion(true) : CodeMirror.Pass, - 'Up': (cm) => + 'Up': cm => completeActive ? this.nextAutocompleteSuggestion(true) : CodeMirror.Pass, - 'Escape': (cm) => + 'Escape': cm => completeActive ? this.clearSuggestions(true) : CodeMirror.Pass, - 'Down': (cm) => + 'Down': cm => completeActive ? this.nextAutocompleteSuggestion() : CodeMirror.Pass, - 'Enter': (cm) => + 'Enter': cm => completeActive ? this.completePatp(state.selectedSuggestion) : this.messageSubmit(), - 'Shift-3': (cm) => + 'Shift-3': cm => cm.getValue().length === 0 ? this.toggleCode() : CodeMirror.Pass } }; - return (
+ style={{ flexGrow: 1 }} + > {state.patpSuggestions.length !== 0 && ( + }} + > + />
+ style={{ flexGrow: 1, maxHeight: '224px', width: 'calc(100% - 48px)' }} + > { this.editor = editor; }} + editorDidMount={(editor) => { + this.editor = editor; +}} onChange={(e, d, v) => this.messageChange(e, d, v)} />
From 6d4a694aeb4d89c9d6d07196a8d2415f1b571a5d Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 21 Apr 2020 14:58:37 -0400 Subject: [PATCH 6/8] t groups + contacts: make removes completely clean up state --- pkg/arvo/app/contact-hook.hoon | 64 +++++++++---------- pkg/arvo/app/contact-store.hoon | 2 +- pkg/arvo/app/contact-view.hoon | 4 +- pkg/arvo/app/group-hook.hoon | 50 ++++++--------- pkg/interface/groups/src/js/api.js | 11 +--- .../src/js/components/lib/contact-card.js | 3 +- 6 files changed, 58 insertions(+), 76 deletions(-) diff --git a/pkg/arvo/app/contact-hook.hoon b/pkg/arvo/app/contact-hook.hoon index ad7b53c8c..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=_| == -- @@ -125,31 +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) - ?. (~(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)]~ - -- +:: +++ 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 @@ -163,7 +161,7 @@ =. synced (~(put by synced) path.act our.bol) :_ state :~ [%pass contact-path %agent [our.bol %contact-store] %watch contact-path] - [%give %fact ~ %contact-hook-update !>([%initial synced])] + [%give %fact [/synced]~ %contact-hook-update !>([%initial synced])] == :: %add-synced @@ -173,7 +171,7 @@ =/ contact-path [%contacts path.act] :_ state :~ [%pass contact-path %agent [ship.act %contact-hook] %watch contact-path] - [%give %fact ~ %contact-hook-update !>([%initial synced])] + [%give %fact [/synced]~ %contact-hook-update !>([%initial synced])] == :: %remove @@ -185,16 +183,19 @@ %- zing :~ (pull-wire [%contacts path.act]) [%give %kick ~[[%contacts path.act]] ~]~ - [%give %fact ~ %contact-hook-update !>([%initial synced])]~ + [%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 + =/ 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 ~ %contact-hook-update !>([%initial synced])]~ + [%give %fact [/synced]~ %contact-hook-update !>([%initial synced])]~ + cards == == :: @@ -207,10 +208,7 @@ =/ =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 @@ -324,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]) 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/interface/groups/src/js/api.js b/pkg/interface/groups/src/js/api.js index 6e56ca9ac..70a6a69b9 100644 --- a/pkg/interface/groups/src/js/api.js +++ b/pkg/interface/groups/src/js/api.js @@ -11,8 +11,7 @@ class UrbitApi { this.bindPaths = []; this.contactHook = { - edit: this.contactEdit.bind(this), - remove: this.contactRemove.bind(this) + edit: this.contactEdit.bind(this) }; this.contactView = { @@ -108,14 +107,6 @@ class UrbitApi { return this.action("contact-hook", "contact-action", data); } - contactRemove(path, ship) { - return this.contactHookAction({ - remove: { - path, ship - } - }); - } - contactEdit(path, ship, editField) { /* editField can be... {nickname: ''} diff --git a/pkg/interface/groups/src/js/components/lib/contact-card.js b/pkg/interface/groups/src/js/components/lib/contact-card.js index dff7b4aa4..de3189918 100644 --- a/pkg/interface/groups/src/js/components/lib/contact-card.js +++ b/pkg/interface/groups/src/js/components/lib/contact-card.js @@ -317,13 +317,12 @@ export class ContactCard extends Component { ); this.setState({awaiting: true, type: "Removing from group"}, (() => { - 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}); props.history.push(`/~groups${destination}`); }); - api.contactView.delete(props.path); })) } From bcde27a7ff40531285fa699e7f00091bde565e7c Mon Sep 17 00:00:00 2001 From: Matilde Park Date: Tue, 21 Apr 2020 15:05:48 -0400 Subject: [PATCH 7/8] publish: change line-height on numbered lists --- pkg/interface/publish/src/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/interface/publish/src/css/custom.css b/pkg/interface/publish/src/css/custom.css index 5b068397e..ec574dd6f 100644 --- a/pkg/interface/publish/src/css/custom.css +++ b/pkg/interface/publish/src/css/custom.css @@ -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 { From 707bedc2b4138bf03ef822fe5a481acfc218fc2a Mon Sep 17 00:00:00 2001 From: Matilde Park Date: Tue, 21 Apr 2020 19:36:30 -0400 Subject: [PATCH 8/8] publish: set font size for ordered lists --- pkg/interface/publish/src/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/interface/publish/src/css/custom.css b/pkg/interface/publish/src/css/custom.css index ec574dd6f..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; }