diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dc7dacb20..b7b954227 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: - uses: cachix/cachix-action@v8 with: - name: ${{ secrets.CACHIX_NAME }} + name: ares authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - run: nix-build -A urbit --arg enableStatic true @@ -88,7 +88,7 @@ jobs: - uses: cachix/install-nix-action@v12 - uses: cachix/cachix-action@v8 with: - name: ${{ secrets.CACHIX_NAME }} + name: ares authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - run: nix-build -A hs.urbit-king.components.exes.urbit-king --arg enableStatic true diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml index b80d0ca09..bae515601 100644 --- a/.github/workflows/release-docker.yml +++ b/.github/workflows/release-docker.yml @@ -22,7 +22,7 @@ jobs: system-features = nixos-test benchmark big-parallel kvm - uses: cachix/cachix-action@v8 with: - name: ${{ secrets.CACHIX_NAME }} + name: ares authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - uses: docker/docker-login-action@v1.8.0 with: diff --git a/bin/solid.pill b/bin/solid.pill index e44e08925..7e7658c6d 100644 --- a/bin/solid.pill +++ b/bin/solid.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:288b3ab68e2e3946dbf0e0de05c2907c351ec97fcc08134e558569eab4121c94 -size 8809816 +oid sha256:271d575a87373f4ed73b195780973ed41cb72be21b428a645c42a49ab5f786ee +size 8873583 diff --git a/pkg/arvo/app/glob.hoon b/pkg/arvo/app/glob.hoon index 7b39eb6ff..293574f2a 100644 --- a/pkg/arvo/app/glob.hoon +++ b/pkg/arvo/app/glob.hoon @@ -5,7 +5,7 @@ /- glob /+ default-agent, verb, dbug |% -++ hash 0v1.4u9gp.rs1fi.ki7ok.ib4cp.mgdvs +++ hash 0v7.ttn7o.50403.rf6oh.63hnc.hgpc9 +$ 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 a5e501ce8..a50a2c7fa 100644 --- a/pkg/arvo/app/landscape/index.html +++ b/pkg/arvo/app/landscape/index.html @@ -24,6 +24,6 @@
- + diff --git a/pkg/arvo/sys/vane/ames.hoon b/pkg/arvo/sys/vane/ames.hoon index 64d410698..ad799da54 100644 --- a/pkg/arvo/sys/vane/ames.hoon +++ b/pkg/arvo/sys/vane/ames.hoon @@ -180,6 +180,9 @@ $(index +(index), sorted [(~(got by fragments) index) sorted]) :: (cue (rep 13 (flop sorted))) +:: +jim: caching +jam +:: +++ jim |=(n=* ~+((jam n))) :: +bind-duct: find or make new $bone for .duct in .ossuary :: ++ bind-duct @@ -1931,7 +1934,7 @@ == now :: - =/ =message-blob (dedup-message (jam payload)) + =/ =message-blob (dedup-message (jim payload)) =. peer-core (run-message-pump bone %memo message-blob) :: ?: &(=(%boon valence) ?=(?(%dead %unborn) -.qos.peer-state)) diff --git a/pkg/arvo/ted/graph/join.hoon b/pkg/arvo/ted/graph/join.hoon index 5837409ae..25a18e3b7 100644 --- a/pkg/arvo/ted/graph/join.hoon +++ b/pkg/arvo/ted/graph/join.hoon @@ -29,13 +29,16 @@ ^- form:m =/ pax (en-path:resource rid) + =/ hold=@dr ~s0..8000 |- ^- form:m + ?> (lte hold ~m5) =* loop $ ;< u-group=(unit group) bind:m (scry:strandio ,(unit group) (weld /gx/group-store/groups (snoc pax %noun))) ?^ u-group (pure:m ~) - ;< ~ bind:m (sleep:strandio `@dr`(div ~s1 2)) + ;< ~ bind:m (sleep:strandio hold) + =. hold (mul hold 2) loop :: ++ wait-for-md @@ -44,13 +47,16 @@ ^- form:m =/ pax (en-path:resource rid) + =/ hold=@dr ~s0..8000 |- ^- form:m + ?> (lte hold ~m5) =* loop $ - ;< groups=(set path) bind:m - (scry:strandio ,(set path) /gy/metadata-store/group-indices) - ?: (~(has in groups) pax) + ;< groups=(jug path md-resource) bind:m + (scry:strandio ,(jug path md-resource) /gy/metadata-store/group-indices) + ?: (~(has by groups) pax) (pure:m ~) - ;< ~ bind:m (sleep:strandio `@dr`(div ~s1 2)) + ;< ~ bind:m (sleep:strandio hold) + =. hold (mul hold 2) loop -- :: diff --git a/pkg/interface/package-lock.json b/pkg/interface/package-lock.json index 6f1071d53..cdadefa5f 100644 Binary files a/pkg/interface/package-lock.json and b/pkg/interface/package-lock.json differ diff --git a/pkg/interface/package.json b/pkg/interface/package.json index 3a8e65cca..b8c18d79d 100644 --- a/pkg/interface/package.json +++ b/pkg/interface/package.json @@ -4,85 +4,85 @@ "description": "", "main": "index.js", "dependencies": { - "@babel/runtime": "^7.10.5", + "@babel/runtime": "^7.12.5", "@reach/disclosure": "^0.10.5", "@reach/menu-button": "^0.10.5", "@reach/tabs": "^0.10.5", "@tlon/indigo-dark": "^1.0.6", "@tlon/indigo-light": "^1.0.6", - "@tlon/indigo-react": "1.2.16", + "@tlon/indigo-react": "1.2.17", "@tlon/sigil-js": "^1.4.3", - "aws-sdk": "^2.726.0", + "aws-sdk": "^2.830.0", "big-integer": "^1.6.48", "classnames": "^2.2.6", - "codemirror": "^5.55.0", - "css-loader": "^3.5.3", - "file-saver": "^2.0.2", - "formik": "^2.1.4", - "immer": "^8.0.0", - "lodash": "^4.17.15", + "codemirror": "^5.59.2", + "css-loader": "^3.6.0", + "file-saver": "^2.0.5", + "formik": "^2.2.6", + "immer": "^8.0.1", + "lodash": "^4.17.20", "markdown-to-jsx": "^6.11.4", - "moment": "^2.20.1", + "moment": "^2.29.1", "mousetrap": "^1.6.5", "mousetrap-global-bind": "^1.1.0", "normalize-wheel": "1.0.1", - "oembed-parser": "^1.4.1", + "oembed-parser": "^1.4.5", "prop-types": "^15.7.2", - "react": "^16.5.2", + "react": "^16.14.0", "react-codemirror2": "^6.0.1", - "react-dom": "^16.8.6", + "react-dom": "^16.14.0", "react-helmet": "^6.1.0", "react-markdown": "^4.3.1", "react-oembed-container": "^1.0.0", - "react-router-dom": "^5.0.0", - "react-virtuoso": "^0.20.0", + "react-router-dom": "^5.2.0", + "react-virtuoso": "^0.20.3", "react-visibility-sensor": "^5.1.1", "remark-breaks": "^2.0.1", "remark-disable-tokenizers": "^1.0.24", - "style-loader": "^1.2.1", - "styled-components": "^5.1.0", + "style-loader": "^1.3.0", + "styled-components": "^5.1.1", "styled-system": "^5.1.5", "suncalc": "^1.8.0", - "urbit-ob": "^5.0.0", + "urbit-ob": "^5.0.1", "yup": "^0.29.3", - "zustand": "^3.2.0" + "zustand": "^3.3.1" }, "devDependencies": { - "@babel/core": "^7.9.0", - "@babel/plugin-proposal-class-properties": "^7.8.3", - "@babel/plugin-proposal-object-rest-spread": "^7.9.5", - "@babel/plugin-proposal-optional-chaining": "^7.9.0", - "@babel/plugin-transform-runtime": "^7.10.5", - "@babel/preset-env": "^7.9.5", - "@babel/preset-react": "^7.9.4", - "@babel/preset-typescript": "^7.10.1", - "@types/lodash": "^4.14.155", - "@types/react": "^16.9.38", - "@types/react-dom": "^16.9.8", - "@types/react-router-dom": "^5.1.5", - "@types/styled-components": "^5.1.2", + "@babel/core": "^7.12.10", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-transform-runtime": "^7.12.10", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "@types/lodash": "^4.14.168", + "@types/react": "^16.14.2", + "@types/react-dom": "^16.9.10", + "@types/react-router-dom": "^5.1.7", + "@types/styled-components": "^5.1.7", "@types/styled-system": "^5.1.10", - "@types/yup": "^0.29.7", - "@typescript-eslint/eslint-plugin": "^3.8.0", - "@typescript-eslint/parser": "^3.8.0", + "@types/yup": "^0.29.11", + "@typescript-eslint/eslint-plugin": "^3.10.1", + "@typescript-eslint/parser": "^3.10.1", "babel-eslint": "^10.1.0", - "babel-loader": "^8.1.0", + "babel-loader": "^8.2.2", "babel-plugin-lodash": "^3.3.4", - "babel-plugin-root-import": "^6.5.0", + "babel-plugin-root-import": "^6.6.0", "clean-webpack-plugin": "^3.0.0", - "cross-env": "^7.0.2", + "cross-env": "^7.0.3", "eslint": "^6.8.0", - "eslint-plugin-react": "^7.19.0", - "file-loader": "^6.0.0", - "html-webpack-plugin": "^4.2.0", + "eslint-plugin-react": "^7.22.0", + "file-loader": "^6.2.0", + "html-webpack-plugin": "^4.5.1", "moment-locales-webpack-plugin": "^1.2.0", - "react-hot-loader": "^4.12.21", - "sass": "^1.26.5", + "react-hot-loader": "^4.13.0", + "sass": "^1.32.5", "sass-loader": "^8.0.2", "typescript": "^3.9.7", - "webpack": "^4.43.0", - "webpack-cli": "^3.3.11", - "webpack-dev-server": "^3.10.3" + "webpack": "^4.46.0", + "webpack-cli": "^3.3.12", + "webpack-dev-server": "^3.11.2" }, "scripts": { "lint": "eslint ./src/**/*.{js,ts,tsx}", diff --git a/pkg/interface/src/logic/api/graph.ts b/pkg/interface/src/logic/api/graph.ts index 40b9c1aad..0606a2c1e 100644 --- a/pkg/interface/src/logic/api/graph.ts +++ b/pkg/interface/src/logic/api/graph.ts @@ -3,8 +3,8 @@ import { StoreState } from '../store/type'; import { Patp, Path, PatpNoSig } from '~/types/noun'; import _ from 'lodash'; import {makeResource, resourceFromPath} from '../lib/group'; -import {GroupPolicy, Enc, Post, NodeMap, Content} from '~/types'; -import { numToUd, unixToDa, decToUd, deSig } from '~/logic/lib/util'; +import {GroupPolicy, Enc, Post, NodeMap, Content, Resource} from '~/types'; +import { numToUd, unixToDa, decToUd, deSig, resourceAsPath } from '~/logic/lib/util'; export const createBlankNodeWithChildPost = ( parentIndex: string = '', @@ -81,6 +81,8 @@ function moduleToMark(mod: string): string | undefined { export default class GraphApi extends BaseApi { + joiningGraphs = new Set(); + private storeAction(action: any): Promise { return this.action('graph-store', 'graph-update', action) } @@ -138,11 +140,19 @@ export default class GraphApi extends BaseApi { joinGraph(ship: Patp, name: string) { const resource = makeResource(ship, name); + const rid = resourceAsPath(resource); + if(this.joiningGraphs.has(rid)) { + return Promise.resolve(); + } + this.joiningGraphs.add(rid); return this.viewAction('graph-join', { join: { resource, ship, } + }).then(res => { + this.joiningGraphs.delete(rid); + return res; }); } diff --git a/pkg/interface/src/views/apps/chat/components/ChatMessage.tsx b/pkg/interface/src/views/apps/chat/components/ChatMessage.tsx index c57d21143..c1ff5f630 100644 --- a/pkg/interface/src/views/apps/chat/components/ChatMessage.tsx +++ b/pkg/interface/src/views/apps/chat/components/ChatMessage.tsx @@ -282,7 +282,7 @@ export const MessageContent = ({ content, contacts, measure, fontSize, group }) url={content.url} onLoad={measure} imageProps={{style: { - maxWidth: '18rem', + maxWidth: 'min(100%,18rem)', display: 'block' }}} videoProps={{style: { diff --git a/pkg/interface/src/views/apps/links/LinkResource.tsx b/pkg/interface/src/views/apps/links/LinkResource.tsx index 962871f03..0bf62c845 100644 --- a/pkg/interface/src/views/apps/links/LinkResource.tsx +++ b/pkg/interface/src/views/apps/links/LinkResource.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useCallback } from "react"; import { Box, Row, Col, Center, LoadingSpinner, Text } from "@tlon/indigo-react"; import { Switch, Route, Link } from "react-router-dom"; import bigInt from 'big-integer'; @@ -10,10 +10,14 @@ import { RouteComponentProps } from "react-router-dom"; import { LinkItem } from "./components/LinkItem"; import LinkSubmit from "./components/LinkSubmit"; +import { LinkPreview } from "./components/link-preview"; +import { LinkWindow } from "./LinkWindow"; import { Comments } from "~/views/components/Comments"; import "./css/custom.css"; +const emptyMeasure = () => {}; + type LinkResourceProps = StoreState & { association: Association; api: GlobalApi; @@ -57,39 +61,28 @@ export function LinkResource(props: LinkResourceProps) { return
; } + return ( - + { return ( - - - - - {Array.from(graph).map(([date, node]) => { - const contact = contactDetails[node.post.author]; - return ( - - ); - })} - + ); }} /> @@ -112,6 +105,7 @@ export function LinkResource(props: LinkResourceProps) { const contact = contactDetails[node.post.author]; return ( + {"<- Back"} + ); }} /> diff --git a/pkg/interface/src/views/apps/links/LinkWindow.tsx b/pkg/interface/src/views/apps/links/LinkWindow.tsx new file mode 100644 index 000000000..abc85d672 --- /dev/null +++ b/pkg/interface/src/views/apps/links/LinkWindow.tsx @@ -0,0 +1,97 @@ +import React, { useRef, useCallback, useEffect, useMemo } from "react"; +import { Col } from "@tlon/indigo-react"; +import bigInt from 'big-integer'; +import { + Association, + Graph, + Contacts, + Unreads, + LocalUpdateRemoteContentPolicy, + Group, + Rolodex, + S3State, +} from "~/types"; +import GlobalApi from "~/logic/api/global"; +import VirtualScroller from "~/views/components/VirtualScroller"; +import { LinkItem } from "./components/LinkItem"; +import LinkSubmit from "./components/LinkSubmit"; + +interface LinkWindowProps { + association: Association; + contacts: Rolodex; + resource: string; + graph: Graph; + unreads: Unreads; + hideNicknames: boolean; + hideAvatars: boolean; + baseUrl: string; + group: Group; + path: string; + api: GlobalApi; + s3: S3State; +} +export function LinkWindow(props: LinkWindowProps) { + const { graph, api, association } = props; + const loadedNewest = useRef(true); + const loadedOldest = useRef(false); + const virtualList = useRef(); + const fetchLinks = useCallback( + async (newer: boolean) => { + /* stubbed, should we generalize the display of graphs in virtualscroller? */ + }, [] + ); + + useEffect(() => { + const list = virtualList?.current; + if(!list) return; + list.calculateVisibleItems(); + }, [graph.size]); + + const first = graph.peekLargest()?.[0]; + + const [,,ship, name] = association['app-path'].split('/'); + + const style = useMemo(() => + ({ + height: "100%", + width: "100%", + display: 'flex', + flexDirection: 'column', + alignItems: 'center' + }), []); + + return ( + (virtualList.current = l ?? undefined)} + origin="top" + style={style} + onStartReached={() => {}} + onScroll={() => {}} + data={graph} + size={graph.size} + renderer={({ index, measure, scrollWindow }) => { + const node = graph.get(index); + const post = node?.post; + if (!node || !post) return null; + const linkProps = { + ...props, + node, + measure, + key: index.toString() + }; + if(index.eq(first ?? bigInt.zero)) { + return ( + <> + + + + + + ) + } + return ; + }} + loadRows={fetchLinks} + /> + ); +} diff --git a/pkg/interface/src/views/apps/links/components/LinkItem.tsx b/pkg/interface/src/views/apps/links/components/LinkItem.tsx index d47e5ee57..83bfc2dc8 100644 --- a/pkg/interface/src/views/apps/links/components/LinkItem.tsx +++ b/pkg/interface/src/views/apps/links/components/LinkItem.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect, useRef, useCallback } from 'react'; import { Link } from 'react-router-dom'; import { Row, Col, Anchor, Box, Text, Icon, Action } from '@tlon/indigo-react'; @@ -17,8 +17,9 @@ interface LinkItemProps { api: GlobalApi; group: Group; path: string; - contacts: Rolodex[]; + contacts: Rolodex; unreads: Unreads; + measure: (el: any) => void; } export const LinkItem = (props: LinkItemProps) => { @@ -29,9 +30,12 @@ export const LinkItem = (props: LinkItemProps) => { group, path, contacts, + measure, ...rest } = props; + const ref = useRef(null); + const URLparser = new RegExp( /((?:([\w\d\.-]+)\:\/\/?){1}(?:(www)\.?){0,1}(((?:[\w\d-]+\.)*)([\w\d-]+\.[\w\d]+))){1}(?:\:(\d+)){0,1}((\/(?:(?:[^\/\s\?]+\/)*))(?:([^\?\/\s#]+?(?:.[^\?\s]+){0,1}){0,1}(?:\?([^\s#]+)){0,1})){0,1}(?:#([^#\s]+)){0,1}/ ); @@ -70,9 +74,18 @@ export const LinkItem = (props: LinkItemProps) => { const markRead = () => { api.hark.markEachAsRead(props.association, '/', `/${index}`, 'link', 'link'); } - return ( - + + const onMeasure = useCallback(() => { + ref.current && measure(ref.current); + }, [ref.current, measure]) + + useEffect(() => { + onMeasure(); + }, [onMeasure]); + + return ( + { url={contents[1].url} text={contents[0].text} unfold={true} + onLoad={onMeasure} style={{ alignSelf: 'center' }} oembedProps={{ p: 2, diff --git a/pkg/interface/src/views/apps/notifications/inbox.tsx b/pkg/interface/src/views/apps/notifications/inbox.tsx index ad7c3573f..bdf366e1b 100644 --- a/pkg/interface/src/views/apps/notifications/inbox.tsx +++ b/pkg/interface/src/views/apps/notifications/inbox.tsx @@ -146,7 +146,7 @@ export default function Inbox(props: { return ( - + {inviteItems(invites, api)} {[...notificationsByDay.keys()].map((day, index) => { diff --git a/pkg/interface/src/views/apps/publish/css/custom.css b/pkg/interface/src/views/apps/publish/css/custom.css index 4bead77ae..32ef87e4f 100644 --- a/pkg/interface/src/views/apps/publish/css/custom.css +++ b/pkg/interface/src/views/apps/publish/css/custom.css @@ -264,7 +264,7 @@ background-color: #333; } .publish .cm-s-tlon.CodeMirror { - background: #333; + background: unset; color: #fff; } diff --git a/pkg/interface/src/views/components/AsyncButton.tsx b/pkg/interface/src/views/components/AsyncButton.tsx index b7f99588c..f62288ee5 100644 --- a/pkg/interface/src/views/components/AsyncButton.tsx +++ b/pkg/interface/src/views/components/AsyncButton.tsx @@ -29,10 +29,15 @@ export function AsyncButton({ }, [status]); return ( -