From f0c3f37b0e8ccc98ab9e96204b01215e2bfcf7c1 Mon Sep 17 00:00:00 2001 From: James Acklin Date: Sat, 3 Apr 2021 12:04:01 -0400 Subject: [PATCH 01/17] groups: resize group summary fixes urbit/landscape#728 --- .../landscape/components/Home/EmptyGroupHome.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/interface/src/views/landscape/components/Home/EmptyGroupHome.js b/pkg/interface/src/views/landscape/components/Home/EmptyGroupHome.js index f61075b8d..22d28ef9b 100644 --- a/pkg/interface/src/views/landscape/components/Home/EmptyGroupHome.js +++ b/pkg/interface/src/views/landscape/components/Home/EmptyGroupHome.js @@ -22,12 +22,14 @@ export function EmptyGroupHome(props) { alignItems="center" display="flex"> { groupAssociation?.group ? ( - + + + ) : ( From c398b2c0e451d7a1b51994b6409ecc0dcecb23a5 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 6 Apr 2021 08:28:53 +1000 Subject: [PATCH 02/17] interface: mark BigIntOrderedMap compat with immer Fixes urbit/landscape#707 Fixes urbit/landscape#740 --- pkg/interface/src/logic/lib/BigIntOrderedMap.ts | 2 ++ pkg/npm/api/lib/BigIntOrderedMap.ts | 2 ++ pkg/npm/api/package.json | 1 + 3 files changed, 5 insertions(+) diff --git a/pkg/interface/src/logic/lib/BigIntOrderedMap.ts b/pkg/interface/src/logic/lib/BigIntOrderedMap.ts index 21fc1c8ca..1e6a41e40 100644 --- a/pkg/interface/src/logic/lib/BigIntOrderedMap.ts +++ b/pkg/interface/src/logic/lib/BigIntOrderedMap.ts @@ -1,4 +1,5 @@ import bigInt, { BigInteger } from 'big-integer'; +import { immerable } from 'immer'; interface NonemptyNode { n: [BigInteger, V]; @@ -14,6 +15,7 @@ type MapNode = NonemptyNode | null; */ export class BigIntOrderedMap implements Iterable<[BigInteger, V]> { private root: MapNode = null; + [immerable] = true; size = 0; constructor(initial: [BigInteger, V][] = []) { diff --git a/pkg/npm/api/lib/BigIntOrderedMap.ts b/pkg/npm/api/lib/BigIntOrderedMap.ts index 6f42da526..d7cd00bdf 100644 --- a/pkg/npm/api/lib/BigIntOrderedMap.ts +++ b/pkg/npm/api/lib/BigIntOrderedMap.ts @@ -1,4 +1,5 @@ import { BigInteger } from "big-integer"; +import { immerable } from 'immer'; interface NonemptyNode { n: [BigInteger, V]; @@ -14,6 +15,7 @@ type MapNode = NonemptyNode | null; */ export default class BigIntOrderedMap implements Iterable<[BigInteger, V]> { private root: MapNode = null; + [immerable] = true; size: number = 0; constructor(initial: [BigInteger, V][] = []) { diff --git a/pkg/npm/api/package.json b/pkg/npm/api/package.json index 256e74751..b4589d387 100644 --- a/pkg/npm/api/package.json +++ b/pkg/npm/api/package.json @@ -21,6 +21,7 @@ "@types/lodash": "^4.14.168", "@urbit/eslint-config": "^1.0.0", "big-integer": "^1.6.48", + "immer": "^9.0.1", "lodash": "^4.17.20" } } From 067991533a9ffc06a490790b7627077a80009eab Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 6 Apr 2021 11:43:58 +1000 Subject: [PATCH 03/17] EditProfile: do not mutate contact Fixes urbit/landscape#698 --- .../src/views/apps/profile/components/EditProfile.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkg/interface/src/views/apps/profile/components/EditProfile.tsx b/pkg/interface/src/views/apps/profile/components/EditProfile.tsx index d59bd98a8..0648d7326 100644 --- a/pkg/interface/src/views/apps/profile/components/EditProfile.tsx +++ b/pkg/interface/src/views/apps/profile/components/EditProfile.tsx @@ -93,9 +93,6 @@ export function EditProfile(props: any): ReactElement { }; const history = useHistory(); - if (contact) { - contact.isPublic = isPublic; - } const onSubmit = async (values: any, actions: any) => { try { @@ -143,7 +140,7 @@ export function EditProfile(props: any): ReactElement { <> {({ setFieldValue }) => ( From c60a41b26dad1ec259a35b4fab0cb26562235e70 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 6 Apr 2021 11:54:28 +1000 Subject: [PATCH 04/17] publish: fix color in darkmode Fixes urbit/landscape#736 --- pkg/interface/src/views/apps/permalinks/TranscludedNode.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/interface/src/views/apps/permalinks/TranscludedNode.tsx b/pkg/interface/src/views/apps/permalinks/TranscludedNode.tsx index 67b1e4374..c84630ff7 100644 --- a/pkg/interface/src/views/apps/permalinks/TranscludedNode.tsx +++ b/pkg/interface/src/views/apps/permalinks/TranscludedNode.tsx @@ -100,7 +100,7 @@ function TranscludedPublishNode(props: { ?.get(bigInt.one) ?.children?.peekLargest()?.[1]!; return ( - + Date: Tue, 6 Apr 2021 14:13:40 +1000 Subject: [PATCH 05/17] Invite: fix stale props in inviteAccept callback Now that the store is immutable, callbacks that close over props will see stale props because the reference is captured at instantiation. This was not an issue previously, because the references would be directly mutated. To remedy this, useRunIO has been added, which takes an async function to run for the actual network processing, and a second callback, which is able to see fresh props because it is not instantiated until the async callback has resolved successfully. Importantly, useRunIO does not resolve until the second callback has finished, preserving the semantics of the callback for Formik handlers and the like. Fixes urbit/landscape#691 --- pkg/interface/src/logic/lib/useRunIO.ts | 52 ++++++ .../src/views/components/Invite/index.tsx | 176 ++++++++++-------- 2 files changed, 151 insertions(+), 77 deletions(-) create mode 100644 pkg/interface/src/logic/lib/useRunIO.ts diff --git a/pkg/interface/src/logic/lib/useRunIO.ts b/pkg/interface/src/logic/lib/useRunIO.ts new file mode 100644 index 000000000..12d8628cd --- /dev/null +++ b/pkg/interface/src/logic/lib/useRunIO.ts @@ -0,0 +1,52 @@ +import { useState, useEffect } from "react"; +import { useWaitForProps } from "./useWaitForProps"; +import {unstable_batchedUpdates} from "react-dom"; + +export type IOInstance = ( + input: I +) => (props: P) => Promise<[(p: P) => boolean, O]>; + +export function useRunIO( + io: (i: I) => Promise, + after: (o: O) => void, + key: string +) { + const [resolve, setResolve] = useState<() => void>(() => () => {}); + const [reject, setReject] = useState<(e: any) => void>(() => () => {}); + const [output, setOutput] = useState(null); + const [done, setDone] = useState(false); + const run = (i: I) => + new Promise((res, rej) => { + setResolve(() => res); + setReject(() => rej); + io(i) + .then((o) => { + unstable_batchedUpdates(() => { + setOutput(o); + setDone(true); + }); + }) + .catch(rej); + }); + + useEffect(() => { + reject(new Error("useRunIO: key changed")); + setDone(false); + setOutput(null); + }, [key]); + + useEffect(() => { + if (!done) { + return; + } + try { + after(output!); + resolve(); + } catch (e) { + reject(e); + } + }, [done]); + + return run; +} + diff --git a/pkg/interface/src/views/components/Invite/index.tsx b/pkg/interface/src/views/components/Invite/index.tsx index a8d90f781..144daf714 100644 --- a/pkg/interface/src/views/components/Invite/index.tsx +++ b/pkg/interface/src/views/components/Invite/index.tsx @@ -1,27 +1,28 @@ -import React, { useState, useEffect, useCallback } from 'react'; -import { useHistory } from 'react-router-dom'; +import React, { useState, useEffect, useCallback } from "react"; +import { useHistory } from "react-router-dom"; import { MetadataUpdatePreview, Contacts, JoinRequests, Groups, - Associations -} from '@urbit/api'; -import { Invite } from '@urbit/api/invite'; -import { Text, Icon, Row } from '@tlon/indigo-react'; + Associations, +} from "@urbit/api"; +import { Invite } from "@urbit/api/invite"; +import { Text, Icon, Row } from "@tlon/indigo-react"; -import { cite, useShowNickname } from '~/logic/lib/util'; -import GlobalApi from '~/logic/api/global'; -import { resourceFromPath } from '~/logic/lib/group'; -import { GroupInvite } from './Group'; -import { InviteSkeleton } from './InviteSkeleton'; -import { JoinSkeleton } from './JoinSkeleton'; -import { useWaitForProps } from '~/logic/lib/useWaitForProps'; -import useGroupState from '~/logic/state/group'; -import useContactState from '~/logic/state/contact'; -import useMetadataState from '~/logic/state/metadata'; -import useGraphState from '~/logic/state/graph'; +import { cite, useShowNickname } from "~/logic/lib/util"; +import GlobalApi from "~/logic/api/global"; +import { resourceFromPath } from "~/logic/lib/group"; +import { GroupInvite } from "./Group"; +import { InviteSkeleton } from "./InviteSkeleton"; +import { JoinSkeleton } from "./JoinSkeleton"; +import { useWaitForProps } from "~/logic/lib/useWaitForProps"; +import useGroupState from "~/logic/state/group"; +import useContactState from "~/logic/state/contact"; +import useMetadataState from "~/logic/state/metadata"; +import useGraphState from "~/logic/state/graph"; +import { useRunIO } from "~/logic/lib/useRunIO"; interface InviteItemProps { invite?: Invite; @@ -32,62 +33,81 @@ interface InviteItemProps { api: GlobalApi; } +export function useInviteAccept( + resource: string, + api: GlobalApi, + app?: string, + uid?: string, + invite?: Invite, +) { + const { ship, name } = resourceFromPath(resource); + const history = useHistory(); + const associations = useMetadataState((s) => s.associations); + const groups = useGroupState((s) => s.groups); + const graphKeys = useGraphState((s) => s.graphKeys); + + const waiter = useWaitForProps({ associations, graphKeys, groups }); + return useRunIO( + async () => { + if (!(app && invite && uid)) { + return false; + } + if (resource in groups) { + await api.invite.decline(app, uid); + return false; + } + + await api.groups.join(ship, name); + await api.invite.accept(app, uid); + await waiter((p) => { + return ( + (resource in p.groups && + resource in (p.associations?.graph ?? {}) && + p.graphKeys.has(resource.slice(7))) || + resource in (p.associations?.groups ?? {}) + ); + }); + return true; + }, + (success: boolean) => { + if (!success) { + return; + } + if (groups?.[resource]?.hidden) { + const { metadata } = associations.graph[resource]; + if (metadata && "graph" in metadata.config) { + if (metadata.config.graph === "chat") { + history.push( + `/~landscape/messages/resource/${metadata.config.graph}${resource}` + ); + } else { + history.push( + `/~landscape/home/resource/${metadata.config.graph}${resource}` + ); + } + } else { + console.error("unknown metadata: ", metadata); + } + } else { + history.push(`/~landscape${resource}`); + } + }, + resource + ); +} + export function InviteItem(props: InviteItemProps) { const [preview, setPreview] = useState(null); const { pendingJoin, invite, resource, uid, app, api } = props; - const { ship, name } = resourceFromPath(resource); - const groups = useGroupState(state => state.groups); - const graphKeys = useGraphState(s => s.graphKeys); - const associations = useMetadataState(state => state.associations); - const contacts = useContactState(state => state.contacts); + const { name } = resourceFromPath(resource); + const contacts = useContactState((state) => state.contacts); const contact = contacts?.[`~${invite?.ship}`] ?? {}; const showNickname = useShowNickname(contact); - const waiter = useWaitForProps( - { associations, groups, pendingJoin, graphKeys: Array.from(graphKeys) }, - 50000 - ); - const history = useHistory(); - const inviteAccept = useCallback(async () => { - if (!(app && invite && uid)) { - return; - } - if(resource in groups) { - await api.invite.decline(app, uid); - return; - } - - api.groups.join(ship, name); - await waiter(p => !!p.pendingJoin); - - api.invite.accept(app, uid); - await waiter((p) => { - return ( - resource in p.groups && - (resource in (p.associations?.graph ?? {}) || - resource in (p.associations?.groups ?? {})) - ); - }); - - if (groups?.[resource]?.hidden) { - await waiter(p => p.graphKeys.includes(resource.slice(7))); - const { metadata } = associations.graph[resource]; - if (metadata && 'graph' in metadata.config) { - if (metadata.config.graph === 'chat') { - history.push(`/~landscape/messages/resource/${metadata.config.graph}${resource}`); - } else { - history.push(`/~landscape/home/resource/${metadata.config.graph}${resource}`); - } - } else { - console.error('unknown metadata: ', metadata); - } - } else { - history.push(`/~landscape${resource}`); - } - }, [app, history, waiter, invite, uid, resource, groups, associations]); + const inviteAccept = useInviteAccept(resource, api, app, uid, invite); const inviteDecline = useCallback(async () => { - if(!(app && uid)) { + if (!(app && uid)) { return; } await api.invite.decline(app, uid); @@ -96,7 +116,7 @@ export function InviteItem(props: InviteItemProps) { const handlers = { onAccept: inviteAccept, onDecline: inviteDecline }; useEffect(() => { - if (!app || app === 'groups') { + if (!app || app === "groups") { (async () => { setPreview(await api.metadata.preview(resource)); })(); @@ -108,7 +128,7 @@ export function InviteItem(props: InviteItemProps) { } }, [invite]); - if(pendingJoin?.hidden) { + if (pendingJoin?.hidden) { return null; } @@ -123,7 +143,7 @@ export function InviteItem(props: InviteItemProps) { {...handlers} /> ); - } else if (invite && name.startsWith('dm--')) { + } else if (invite && name.startsWith("dm--")) { return ( - + fontWeight={showNickname ? "500" : "400"} + > {showNickname ? contact?.nickname : cite(`~${invite!.ship}`)} invited you to a DM ); - } else if (status && name.startsWith('dm--')) { + } else if (status && name.startsWith("dm--")) { return ( @@ -162,9 +184,11 @@ export function InviteItem(props: InviteItemProps) { > - + fontWeight={showNickname ? "500" : "400"} + > {showNickname ? contact?.nickname : cite(`~${invite!.ship}`)} @@ -174,14 +198,12 @@ export function InviteItem(props: InviteItemProps) { ); } else if (pendingJoin) { - const [, , ship, name] = resource.split('/'); + const [, , ship, name] = resource.split("/"); return ( - - You are joining - + You are joining {cite(ship)}/{name} From 4aa9bba5b3b902acc8e60982ca874e3c14da7dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Tue, 6 Apr 2021 18:59:23 +0000 Subject: [PATCH 06/17] gcp: isConfigured doesn't touch store Makes the thread return a simple boolean; almost as simple as just returning %.y or %.n. gcpManager now stores whether GCP is configured as a private variable. Also fixes some type errors in gcp. --- pkg/arvo/ted/gcp/is-configured.hoon | 3 +-- pkg/interface/src/logic/api/gcp.ts | 17 +++++------- pkg/interface/src/logic/lib/GcpClient.ts | 2 +- pkg/interface/src/logic/lib/gcpManager.ts | 27 +++++++++---------- .../src/logic/reducers/gcp-reducer.ts | 9 ------- pkg/interface/src/types/gcp-state.ts | 1 - 6 files changed, 21 insertions(+), 38 deletions(-) diff --git a/pkg/arvo/ted/gcp/is-configured.hoon b/pkg/arvo/ted/gcp/is-configured.hoon index 02b67e60b..8c32e7d41 100644 --- a/pkg/arvo/ted/gcp/is-configured.hoon +++ b/pkg/arvo/ted/gcp/is-configured.hoon @@ -6,7 +6,6 @@ /- gcp, spider, settings /+ strandio =, strand=strand:spider -=, enjs:format ^- thread:spider |^ |= * @@ -22,7 +21,7 @@ == %- pure:m !> -%+ frond %gcp-configured +^- json b+has :: ++ has-settings diff --git a/pkg/interface/src/logic/api/gcp.ts b/pkg/interface/src/logic/api/gcp.ts index c6b955b22..8e8cb0bf9 100644 --- a/pkg/interface/src/logic/api/gcp.ts +++ b/pkg/interface/src/logic/api/gcp.ts @@ -1,19 +1,16 @@ import BaseApi from './base'; -import {StoreState} from '../store/type'; -import {GcpToken} from '../types/gcp-state'; +import type {StoreState} from '../store/type'; +import type {GcpToken} from '../../types/gcp-state'; export default class GcpApi extends BaseApi { - isConfigured() { - return this.spider('noun', 'json', 'gcp-is-configured', {}) - .then((data) => { - this.store.handleEvent({ - data - }); - }); + // Does not touch the store; use the value manually. + async isConfigured(): Promise { + return this.spider('noun', 'json', 'gcp-is-configured', {}); } - getToken() { + // Does not return the token; read it out of the store. + async getToken(): Promise { return this.spider('noun', 'gcp-token', 'gcp-get-token', {}) .then((token) => { this.store.handleEvent({ diff --git a/pkg/interface/src/logic/lib/GcpClient.ts b/pkg/interface/src/logic/lib/GcpClient.ts index b03c7fd0a..ba85503e3 100644 --- a/pkg/interface/src/logic/lib/GcpClient.ts +++ b/pkg/interface/src/logic/lib/GcpClient.ts @@ -26,7 +26,7 @@ class GcpUpload implements StorageUpload { this.#accessKey = accessKey; } - async promise(): UploadResult { + async promise(): Promise { const {Bucket, Key, ContentType, Body} = this.#params; const urlParams = { uploadType: 'media', diff --git a/pkg/interface/src/logic/lib/gcpManager.ts b/pkg/interface/src/logic/lib/gcpManager.ts index 4831ffc5c..9ce4abf90 100644 --- a/pkg/interface/src/logic/lib/gcpManager.ts +++ b/pkg/interface/src/logic/lib/gcpManager.ts @@ -5,10 +5,9 @@ // 1. call configure with a GlobalApi and GlobalStore. // 2. call start() to start the token refresh loop. // -// If the ship does not have GCP storage configured, we don't try to get -// a token, but we keep checking at regular intervals to see if it gets -// configured. If GCP storage is configured, we try to invoke the GCP -// get-token thread on the ship until it gives us an access token. Once +// If the ship does not have GCP storage configured, we don't try to +// get a token. If GCP storage is configured, we try to invoke the GCP +// get-token thread on the ship until it gives us an access token. Once // we have a token, we refresh it every hour or so according to its // intrinsic expiry. // @@ -25,7 +24,7 @@ class GcpManager { } #running = false; - #timeoutId: number | null = null; + #timeoutId: ReturnType | null = null; start() { if (this.#running) { @@ -61,19 +60,17 @@ class GcpManager { } #consecutiveFailures: number = 0; - - private isConfigured() { - return useStorageState.getState().gcp.configured; - } + #configured: boolean = false; private refreshLoop() { - if (!this.isConfigured()) { - this.#api.gcp.isConfigured() - .then(() => { - if (this.isConfigured() === undefined) { + if (!this.#configured) { + this.#api!.gcp.isConfigured() + .then((configured) => { + if (configured === undefined) { throw new Error("can't check whether GCP is configured?"); } - if (this.isConfigured()) { + this.#configured = configured; + if (this.#configured) { this.refreshLoop(); } else { console.log('GcpManager: GCP storage not configured; stopping.'); @@ -86,7 +83,7 @@ class GcpManager { }); return; } - this.#api.gcp.getToken() + this.#api!.gcp.getToken() .then(() => { const token = useStorageState.getState().gcp.token; if (token) { diff --git a/pkg/interface/src/logic/reducers/gcp-reducer.ts b/pkg/interface/src/logic/reducers/gcp-reducer.ts index c7280d6cf..ef143f23c 100644 --- a/pkg/interface/src/logic/reducers/gcp-reducer.ts +++ b/pkg/interface/src/logic/reducers/gcp-reducer.ts @@ -8,20 +8,11 @@ import { reduceState } from '../state/base'; export default class GcpReducer { reduce(json: Cage) { reduceState(useStorageState, json, [ - reduceConfigured, reduceToken ]); } } -const reduceConfigured = (json, state: StorageState): StorageState => { - let data = json['gcp-configured']; - if (data !== undefined) { - state.gcp.configured = data; - } - return state; -} - const reduceToken = (json: Cage, state: StorageState): StorageState => { let data = json['gcp-token']; if (data) { diff --git a/pkg/interface/src/types/gcp-state.ts b/pkg/interface/src/types/gcp-state.ts index cdbcbc1c9..e45a37011 100644 --- a/pkg/interface/src/types/gcp-state.ts +++ b/pkg/interface/src/types/gcp-state.ts @@ -4,6 +4,5 @@ export interface GcpToken { }; export interface GcpState { - configured?: boolean; token?: GcpToken }; From 01890fa040886f890916c09650eb929ad5e861cd Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 6 Apr 2021 15:47:57 -0500 Subject: [PATCH 07/17] observe-hook: upgrade to keep marks warm --- pkg/arvo/app/observe-hook.hoon | 81 +++++++++++++++++++++++++++++++--- pkg/arvo/sur/observe-hook.hoon | 9 +++- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/pkg/arvo/app/observe-hook.hoon b/pkg/arvo/app/observe-hook.hoon index 57eab9195..8d76b9cfe 100644 --- a/pkg/arvo/app/observe-hook.hoon +++ b/pkg/arvo/app/observe-hook.hoon @@ -14,6 +14,7 @@ [%2 observers=(map serial observer:sur)] [%3 observers=(map serial observer:sur)] [%4 observers=(map serial observer:sur)] + [%5 observers=(map serial observer:sur) warm-cache=_|] == :: +$ serial @uv @@ -27,7 +28,7 @@ -- :: %- agent:dbug -=| [%4 observers=(map serial observer:sur)] +=| [%5 observers=(map serial observer:sur) warm-cache=_|] =* state - :: ^- agent:gall @@ -66,8 +67,13 @@ =| cards=(list card) |- ?- -.old-state - %4 + %5 [cards this(state old-state)] + %4 + =. cards + :_ cards + (act [%warm-cache-all ~]) + $(old-state [%5 observers.old-state %.n]) :: %3 =. cards @@ -110,11 +116,19 @@ ?> (team:title our.bowl src.bowl) ?. ?=(%observe-action mark) (on-poke:def mark vase) + |^ =/ =action:sur !<(action:sur vase) =* observer observer.action =/ vals (silt ~(val by observers)) ?- -.action - %watch + %watch (watch observer vals) + %ignore (ignore observer vals) + %warm-cache-all warm-cache-all + %cool-cache-all cool-cache-all + == + :: + ++ watch + |= [=observer:sur vals=(set observer:sur)] ?: ?|(=(app.observer %spider) =(app.observer %observe-hook)) ~|('we avoid infinite loops' !!) ?: (~(has in vals) observer) @@ -129,7 +143,8 @@ path.observer == :: - %ignore + ++ ignore + |= [=observer:sur vals=(set observer:sur)] ?. (~(has in vals) observer) ~|('cannot remove nonexistent observer' !!) =/ key (got-by-val observers observer) @@ -142,7 +157,20 @@ %leave ~ == - == + :: + ++ warm-cache-all + ?: warm-cache + ~|('cannot warm up cache that is already warm' !!) + :::_ this(warm-cache %.y) + :_ this + =/ =mood:clay [%t da+now.bowl /mar] + [%pass /warm-cache %arvo %c %warp our.bowl %home `[%sing mood]]~ + :: + ++ cool-cache-all + ?. warm-cache + ~|('cannot cool down cache that is already cool' !!) + [~ this(warm-cache %.n)] + -- :: ++ on-agent |= [=wire =sign:agent:gall] @@ -260,9 +288,50 @@ == == -- :: +++ on-arvo + |= [=wire =sign-arvo] + ^- (quip card _this) + ?+ wire (on-arvo:def wire sign-arvo) + [%warm-cache ~] + ?> ?=([%clay %writ *] sign-arvo) + =* riot p.sign-arvo + ?~ riot + ~|('should always have data in %/mar directory' !!) + :_ this + %+ turn !<((list path) q.r.u.riot) + |= pax=path + ^- card + =. pax `path`(snip (slag 1 `(list @)`pax)) + =/ mark=@ta + %+ roll pax + |= [=term mark=term] + ?: =(0 (lent (trip mark))) + term + %- crip + %- zing + :~ (trip mark) + "-" + (trip term) + == + =/ =rave:clay [%sing %b [%da now.bowl] [mark ~]] + [%pass [%mar mark ~] %arvo %c %warp our.bowl [%home `rave]] + :: + [%mar ^] + ?. warm-cache + [~ this] + ?> ?=([%clay %writ *] sign-arvo) + =* riot p.sign-arvo + =* mark t.wire + ?~ riot + ~|('mark build failed for {}' !!) + ~& mark + :_ this + =/ =rave:clay [%next %b [%da now.bowl] mark] + [%pass wire %arvo %c %warp our.bowl [%home `rave]]~ + == +:: ++ on-watch on-watch:def ++ on-leave on-leave:def ++ on-peek on-peek:def -++ on-arvo on-arvo:def ++ on-fail on-fail:def -- diff --git a/pkg/arvo/sur/observe-hook.hoon b/pkg/arvo/sur/observe-hook.hoon index a424c9622..60030ad5d 100644 --- a/pkg/arvo/sur/observe-hook.hoon +++ b/pkg/arvo/sur/observe-hook.hoon @@ -1,7 +1,14 @@ |% +$ observer [app=term =path thread=term] +$ action - $% [%watch =observer] + $% :: %gall actions + :: + [%watch =observer] [%ignore =observer] + :: + :: %clay actions + :: + [%warm-cache-all ~] + [%cool-cache-all ~] == -- From 5f14b21636833d5ff48bf36d591a1c8b31df451f Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 6 Apr 2021 16:02:18 -0500 Subject: [PATCH 08/17] observe-hook: warm up caches in +on-init also, not just +on-load --- pkg/arvo/app/observe-hook.hoon | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/arvo/app/observe-hook.hoon b/pkg/arvo/app/observe-hook.hoon index 8d76b9cfe..3e701c322 100644 --- a/pkg/arvo/app/observe-hook.hoon +++ b/pkg/arvo/app/observe-hook.hoon @@ -43,6 +43,7 @@ (act [%watch %group-store /groups %group-on-leave]) (act [%watch %group-store /groups %group-on-remove-member]) (act [%watch %metadata-store /updates %md-on-add-group-feed]) + (act [%warm-cache-all ~]) == :: ++ act From 744b9f23345a38c0613d0f942a03c53a67d0e320 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 6 Apr 2021 16:19:22 -0500 Subject: [PATCH 09/17] observe-hook: remove debugging code --- pkg/arvo/app/observe-hook.hoon | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/arvo/app/observe-hook.hoon b/pkg/arvo/app/observe-hook.hoon index 3e701c322..a6ce2852f 100644 --- a/pkg/arvo/app/observe-hook.hoon +++ b/pkg/arvo/app/observe-hook.hoon @@ -162,8 +162,7 @@ ++ warm-cache-all ?: warm-cache ~|('cannot warm up cache that is already warm' !!) - :::_ this(warm-cache %.y) - :_ this + :_ this(warm-cache %.y) =/ =mood:clay [%t da+now.bowl /mar] [%pass /warm-cache %arvo %c %warp our.bowl %home `[%sing mood]]~ :: @@ -325,7 +324,6 @@ =* mark t.wire ?~ riot ~|('mark build failed for {}' !!) - ~& mark :_ this =/ =rave:clay [%next %b [%da now.bowl] mark] [%pass wire %arvo %c %warp our.bowl [%home `rave]]~ From c6616a7e9d43b1353cae8b0e7f39bf7e051615d8 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 6 Apr 2021 16:47:17 -0500 Subject: [PATCH 10/17] observe-hook: listen for mark additions --- pkg/arvo/app/observe-hook.hoon | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/arvo/app/observe-hook.hoon b/pkg/arvo/app/observe-hook.hoon index a6ce2852f..d9f78a4f4 100644 --- a/pkg/arvo/app/observe-hook.hoon +++ b/pkg/arvo/app/observe-hook.hoon @@ -293,11 +293,15 @@ ^- (quip card _this) ?+ wire (on-arvo:def wire sign-arvo) [%warm-cache ~] + ?. warm-cache + [~ this] ?> ?=([%clay %writ *] sign-arvo) + :_ this + :- =/ =rave:clay [%next [%t da+now.bowl /mar]] + [%pass /warm-cache %arvo %c %warp our.bowl %home `rave] =* riot p.sign-arvo ?~ riot - ~|('should always have data in %/mar directory' !!) - :_ this + ~ %+ turn !<((list path) q.r.u.riot) |= pax=path ^- card @@ -314,7 +318,7 @@ (trip term) == =/ =rave:clay [%sing %b [%da now.bowl] [mark ~]] - [%pass [%mar mark ~] %arvo %c %warp our.bowl [%home `rave]] + [%pass [%mar mark ~] %arvo %c %warp our.bowl %home `rave] :: [%mar ^] ?. warm-cache From faf1f83e8f3be2515a51820ec56f5b376f13f2bf Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 6 Apr 2021 17:21:09 -0500 Subject: [PATCH 11/17] graph-store: remove obsoleted code necessary to keep graph marks warm --- pkg/arvo/app/graph-store.hoon | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/pkg/arvo/app/graph-store.hoon b/pkg/arvo/app/graph-store.hoon index 55a40a104..684cfdf09 100644 --- a/pkg/arvo/app/graph-store.hoon +++ b/pkg/arvo/app/graph-store.hoon @@ -46,19 +46,8 @@ %0 %_ $ -.old %1 - :: - validators.old - (~(put in validators.old) %graph-validator-link) - :: - cards - %+ weld cards - %+ turn - ~(tap in (~(put in validators.old) %graph-validator-link)) - |= validator=@t - ^- card - =/ =wire /validator/[validator] - =/ =rave:clay [%sing %b [%da now.bowl] /[validator]] - [%pass wire %arvo %c %warp our.bowl [%home `rave]] + cards cards + validators.old validators.old :: graphs.old %- ~(run by graphs.old) @@ -285,19 +274,10 @@ graphs (~(put by graphs) resource [graph mark]) update-logs (~(put by update-logs) resource update-log) archive (~(del by archive) resource) - :: - validators - ?~ mark validators - (~(put in validators) u.mark) == %- zing :~ (give [/keys ~] %keys (~(put in ~(key by graphs)) resource)) (give [/updates ~] %add-graph resource *graph:store mark overwrite) - ?~ mark ~ - ?: (~(has in validators) u.mark) ~ - =/ wire /validator/[u.mark] - =/ =rave:clay [%sing %b [%da now.bowl] /[u.mark]] - [%pass wire %arvo %c %warp our.bowl [%home `rave]]~ == :: ++ remove-graph @@ -1119,13 +1099,8 @@ ?+ wire (on-arvo:def wire sign-arvo) :: :: old wire, do nothing - [%graph *] [~ this] - :: - [%validator @ ~] - :_ this - =* validator i.t.wire - =/ =rave:clay [%next %b [%da now.bowl] /[validator]] - [%pass wire %arvo %c %warp our.bowl [%home `rave]]~ + [%graph *] [~ this] + [%validator @ ~] [~ this] :: [%try-rejoin @ *] =/ rid=resource:store (de-path:res t.t.wire) From c7e4291d6d91cf3ee855fb7765514a1c6263b0a8 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 6 Apr 2021 18:51:32 -0500 Subject: [PATCH 12/17] observe-hook: ask for next case as opposed to now.bowl when using %next, unless riot is null. small cleanup --- pkg/arvo/app/observe-hook.hoon | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/pkg/arvo/app/observe-hook.hoon b/pkg/arvo/app/observe-hook.hoon index d9f78a4f4..8a90cb024 100644 --- a/pkg/arvo/app/observe-hook.hoon +++ b/pkg/arvo/app/observe-hook.hoon @@ -163,8 +163,8 @@ ?: warm-cache ~|('cannot warm up cache that is already warm' !!) :_ this(warm-cache %.y) - =/ =mood:clay [%t da+now.bowl /mar] - [%pass /warm-cache %arvo %c %warp our.bowl %home `[%sing mood]]~ + =/ =rave:clay [%sing [%t da+now.bowl /mar]] + [%pass /warm-cache %arvo %c %warp our.bowl %home `rave]~ :: ++ cool-cache-all ?. warm-cache @@ -291,17 +291,18 @@ ++ on-arvo |= [=wire =sign-arvo] ^- (quip card _this) + :_ this ?+ wire (on-arvo:def wire sign-arvo) [%warm-cache ~] ?. warm-cache - [~ this] + ~ ?> ?=([%clay %writ *] sign-arvo) - :_ this - :- =/ =rave:clay [%next [%t da+now.bowl /mar]] - [%pass /warm-cache %arvo %c %warp our.bowl %home `rave] =* riot p.sign-arvo ?~ riot - ~ + =/ =rave:clay [%next [%t da+now.bowl /mar]] + [%pass /warm-cache %arvo %c %warp our.bowl %home `rave]~ + :- =/ =rave:clay [%next [%t q.p.u.riot /mar]] + [%pass /warm-cache %arvo %c %warp our.bowl %home `rave] %+ turn !<((list path) q.r.u.riot) |= pax=path ^- card @@ -311,26 +312,20 @@ |= [=term mark=term] ?: =(0 (lent (trip mark))) term - %- crip - %- zing - :~ (trip mark) - "-" - (trip term) - == - =/ =rave:clay [%sing %b [%da now.bowl] [mark ~]] + :((cury cat 3) mark '-' term) + =/ =rave:clay [%sing %b da+now.bowl /[mark]] [%pass [%mar mark ~] %arvo %c %warp our.bowl %home `rave] :: [%mar ^] ?. warm-cache - [~ this] + ~ ?> ?=([%clay %writ *] sign-arvo) =* riot p.sign-arvo =* mark t.wire ?~ riot - ~|('mark build failed for {}' !!) - :_ this - =/ =rave:clay [%next %b [%da now.bowl] mark] - [%pass wire %arvo %c %warp our.bowl [%home `rave]]~ + ~ + =/ =rave:clay [%next %b q.p.u.riot mark] + [%pass wire %arvo %c %warp our.bowl %home `rave]~ == :: ++ on-watch on-watch:def From 2e41b7657e46be9a44450aadbbc2d21780e77679 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 7 Apr 2021 17:07:57 +1000 Subject: [PATCH 13/17] ChatMessage: prevent link overflow Fixes urbit/landscape#732 --- pkg/interface/src/views/apps/chat/components/ChatMessage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/interface/src/views/apps/chat/components/ChatMessage.tsx b/pkg/interface/src/views/apps/chat/components/ChatMessage.tsx index 3bdc3d2a8..b2eee5b91 100644 --- a/pkg/interface/src/views/apps/chat/components/ChatMessage.tsx +++ b/pkg/interface/src/views/apps/chat/components/ChatMessage.tsx @@ -591,7 +591,7 @@ export const Message = ({ lineHeight='20px' color='black' width="fit-content" - maxWidth="500px" + maxWidth="min(500px, 100%)" > Date: Wed, 7 Apr 2021 12:19:26 -0500 Subject: [PATCH 14/17] observe-hook: style fixes as per joe's review --- pkg/arvo/app/observe-hook.hoon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/arvo/app/observe-hook.hoon b/pkg/arvo/app/observe-hook.hoon index 8a90cb024..07fadb5c2 100644 --- a/pkg/arvo/app/observe-hook.hoon +++ b/pkg/arvo/app/observe-hook.hoon @@ -306,11 +306,11 @@ %+ turn !<((list path) q.r.u.riot) |= pax=path ^- card - =. pax `path`(snip (slag 1 `(list @)`pax)) + =. pax (snip (slag 1 pax)) =/ mark=@ta %+ roll pax |= [=term mark=term] - ?: =(0 (lent (trip mark))) + ?: ?=(%$ mark) term :((cury cat 3) mark '-' term) =/ =rave:clay [%sing %b da+now.bowl /[mark]] From a22db08ff6469b0876e6958b648fd4d34910b2ef Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Thu, 8 Apr 2021 10:02:40 +1000 Subject: [PATCH 15/17] interface: update package-lock.json --- pkg/interface/package-lock.json | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/pkg/interface/package-lock.json b/pkg/interface/package-lock.json index bf6648ae4..eb9e97a95 100644 --- a/pkg/interface/package-lock.json +++ b/pkg/interface/package-lock.json @@ -1783,36 +1783,30 @@ "dependencies": { "@babel/runtime": { "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", - "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "bundled": true, "requires": { "regenerator-runtime": "^0.13.4" } }, "@types/lodash": { "version": "4.14.168", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", - "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==" + "bundled": true }, "@urbit/eslint-config": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@urbit/eslint-config/-/eslint-config-1.0.0.tgz", - "integrity": "sha512-Xmzb6MvM7KorlPJEq/hURZZ4BHSVy/7CoQXWogsBSTv5MOZnMqwNKw6yt24k2AO/2UpHwjGptimaNLqFfesJbw==" + "bundled": true }, "big-integer": { "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" + "bundled": true }, "lodash": { "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "bundled": true }, "regenerator-runtime": { "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + "bundled": true } } }, From baf365b63b79b34efed86445a2163db08e836f48 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Thu, 8 Apr 2021 15:20:20 +1000 Subject: [PATCH 16/17] glob: update to 0v4.7tk5q.9ha4l.tbmji.fvkno.s9pfq --- bin/solid.pill | 4 ++-- pkg/arvo/app/glob.hoon | 2 +- pkg/arvo/app/landscape/index.html | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/solid.pill b/bin/solid.pill index a9530ca77..01a73d75d 100644 --- a/bin/solid.pill +++ b/bin/solid.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abc163491b53cc9d48a70ea378dde8bb455648e3f6e7f57a0c7a8e164d4ca105 -size 10226599 +oid sha256:accbadc701471f6b071ed286164a0bf4d3f8a2e64cfaea9019e123bd9edca569 +size 10292454 diff --git a/pkg/arvo/app/glob.hoon b/pkg/arvo/app/glob.hoon index 9b0c3f1eb..bf6a49acf 100644 --- a/pkg/arvo/app/glob.hoon +++ b/pkg/arvo/app/glob.hoon @@ -5,7 +5,7 @@ /- glob /+ default-agent, verb, dbug |% -++ hash 0v2i7ds.j99ka.5dpja.pef1e.b04e0 +++ hash 0v4.7tk5q.9ha4l.tbmji.fvkno.s9pfq +$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))] +$ all-states $% state-0 diff --git a/pkg/arvo/app/landscape/index.html b/pkg/arvo/app/landscape/index.html index 3ce429b2a..b5baae89e 100644 --- a/pkg/arvo/app/landscape/index.html +++ b/pkg/arvo/app/landscape/index.html @@ -24,6 +24,6 @@
- + From b19233633bdce5ea6e86b6fecbae704312845a6f Mon Sep 17 00:00:00 2001 From: James Acklin Date: Thu, 8 Apr 2021 16:36:08 -0400 Subject: [PATCH 17/17] groups: set universal maxWidth of GroupDescription fixes urbit/landscape#728 --- .../landscape/components/GroupSummary.tsx | 2 +- .../components/Home/EmptyGroupHome.js | 14 ++-- .../views/landscape/components/JoinGroup.tsx | 71 ++++++++++--------- 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/pkg/interface/src/views/landscape/components/GroupSummary.tsx b/pkg/interface/src/views/landscape/components/GroupSummary.tsx index 8e3d42299..e4eb205bd 100644 --- a/pkg/interface/src/views/landscape/components/GroupSummary.tsx +++ b/pkg/interface/src/views/landscape/components/GroupSummary.tsx @@ -23,7 +23,7 @@ export function GroupSummary(props: GroupSummaryProps & PropFunc): R anchorRef ); return ( - + { groupAssociation?.group ? ( - - - + ) : ( diff --git a/pkg/interface/src/views/landscape/components/JoinGroup.tsx b/pkg/interface/src/views/landscape/components/JoinGroup.tsx index b0a6d0c47..13a214b60 100644 --- a/pkg/interface/src/views/landscape/components/JoinGroup.tsx +++ b/pkg/interface/src/views/landscape/components/JoinGroup.tsx @@ -151,47 +151,50 @@ export function JoinGroup(props: JoinGroupProps): ReactElement { ) : preview ? ( - - { Object.keys(preview.channels).length > 0 && ( - - - Channels - - - {Object.values(preview.channels).map(({ metadata }: any) => ( - - - {metadata.title} - - ))} - - - )} + <> + + { Object.keys(preview.channels).length > 0 && ( + + + Channels + + + {Object.values(preview.channels).map(({ metadata }: any) => ( + + + {metadata.title} + + ))} + + + )} + onConfirm(preview.group)} > Join {preview.metadata.title} - + ) : (