diff --git a/bin/solid.pill b/bin/solid.pill index 766a71c0a..cdd7cd826 100644 --- a/bin/solid.pill +++ b/bin/solid.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58deed8e9b8cd2c84d092cb8f638b9881cb0d12b97f7c719339e3604c9e9d1d2 -size 13826033 +oid sha256:575484aaf6c8bc03ab3b962ca52d48a90113bcb38a29a1ac84f2d49d1363b4ba +size 7319532 diff --git a/pkg/arvo/app/invite-view.hoon b/pkg/arvo/app/invite-view.hoon deleted file mode 100644 index 82cdf18df..000000000 --- a/pkg/arvo/app/invite-view.hoon +++ /dev/null @@ -1,74 +0,0 @@ -:: invite-view: provide a json interface to invite-store -:: -:: accepts subscriptions at the /primary path. -:: passes through all invites and their updates. -:: only accepts subcriptions from the host's team. -:: -::TODO could maybe use /lib/proxy-hook, be renamed invite-proxy-hook -:: -/+ *invite-json, default-agent, dbug -:: -|% -+$ card card:agent:gall --- -:: -=> - |% - ++ watch-updates - |= our=ship - ^- card - [%pass /store %agent [our %invite-store] %watch /updates] - -- -:: -%- agent:dbug -^- agent:gall -|_ =bowl:gall -+* this . - def ~(. (default-agent this %|) bowl) -:: -++ on-init - ^- (quip card _this) - [[(watch-updates our.bowl)]~ this] -:: -++ on-save on-save:def -++ on-load - |= old=vase - ^- (quip card _this) - [~ this] -:: -++ on-watch - |= =path - ^- (quip card _this) - ?> (team:title our.bowl src.bowl) - ?. =(/primary path) - (on-watch:def path) - :_ this - =/ =invites - .^(invites %gx /=invite-store/(scot %da now.bowl)/all/noun) - [%give %fact ~ %json !>((invites-to-json invites))]~ -:: -++ on-agent - |= [=wire =sign:agent:gall] - ^- (quip card _this) - :_ this - ?- -.sign - %poke-ack ~|([dap.bowl %unexpected-poke-ack] !!) - %watch-ack ~ - %kick [(watch-updates our.bowl)]~ - :: - %fact - ~| [dap.bowl %unexpected-fact-mark p.cage.sign] - ?> ?=(%invite-update p.cage.sign) - :~ :* - %give %fact - ~[/primary] %json - !>((update-to-json !<(invite-update q.cage.sign))) - == == - == -:: -++ on-poke on-poke:def -++ on-peek on-peek:def -++ on-leave on-leave:def -++ on-arvo on-arvo:def -++ on-fail on-fail:def --- diff --git a/pkg/arvo/app/landscape/img/Link.png b/pkg/arvo/app/landscape/img/Link.png new file mode 100644 index 000000000..d83bb877c Binary files /dev/null and b/pkg/arvo/app/landscape/img/Link.png differ diff --git a/pkg/arvo/app/publish.hoon b/pkg/arvo/app/publish.hoon index c04180d0d..5e0125a75 100644 --- a/pkg/arvo/app/publish.hoon +++ b/pkg/arvo/app/publish.hoon @@ -2161,7 +2161,6 @@ [[[~ %json] [%'publish-view' %notebooks ~]] ~] %- json-response:gen %- json-to-octs - %+ frond:enjs:format %publish-response (notebooks-map:enjs our.bol books) :: :: notes pagination @@ -2181,7 +2180,6 @@ not-found:gen %- json-response:gen %- json-to-octs - %+ frond:enjs:format %publish-response :- %o (notes-page:enjs notes.u.book u.start u.length) :: @@ -2206,7 +2204,6 @@ not-found:gen %- json-response:gen %- json-to-octs - %+ frond:enjs:format %publish-response (comments-page:enjs comments.u.note u.start u.length) :: :: single notebook with initial 50 notes in short form, as json @@ -2225,9 +2222,7 @@ (~(put by p.notebook-json) %subscribers (get-subscribers-json book-name)) =. p.notebook-json (~(put by p.notebook-json) %writers (get-writers-json u.host book-name)) - =/ jon=json - (frond:enjs:format %publish-response (pairs notebook+notebook-json ~)) - (json-response:gen (json-to-octs jon)) + (json-response:gen (json-to-octs (pairs notebook+notebook-json ~))) :: :: single note, with initial 50 comments, as json [[[~ %json] [%'publish-view' @ @ @ ~]] ~] @@ -2241,7 +2236,6 @@ =/ note=(unit note) (~(get by notes.u.book) note-name) ?~ note not-found:gen =/ jon=json - %+ frond %publish-response o+(note-presentation:enjs u.book note-name u.note) (json-response:gen (json-to-octs jon)) == diff --git a/pkg/arvo/lib/chat-store.hoon b/pkg/arvo/lib/chat-store.hoon index d589168d6..1ef713879 100644 --- a/pkg/arvo/lib/chat-store.hoon +++ b/pkg/arvo/lib/chat-store.hoon @@ -56,26 +56,23 @@ [%read (numb read.config)] == :: - ++ inbox - |= box=^inbox - ^- json - %+ frond %chat-initial - %- pairs - %+ turn ~(tap by box) - |= [pax=^path =mailbox] - ^- [cord json] - :- (spat pax) - %- pairs - :~ [%envelopes [%a (turn envelopes.mailbox envelope)]] - [%config (config config.mailbox)] - == - :: ++ update |= upd=^update ^- json %+ frond %chat-update %- pairs :~ + ?: ?=(%initial -.upd) + :- %initial + %- pairs + %+ turn ~(tap by inbox.upd) + |= [pax=^path =mailbox] + ^- [cord json] + :- (spat pax) + %- pairs + :~ [%envelopes [%a (turn envelopes.mailbox envelope)]] + [%config (config config.mailbox)] + == ?: ?=(%message -.upd) :- %message %- pairs diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 36bc3cfbf..dec82994f 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -104,7 +104,6 @@ %permission-group-hook %invite-store %invite-hook - %invite-view %chat-store %chat-hook %chat-view diff --git a/pkg/arvo/sys/vane/eyre.hoon b/pkg/arvo/sys/vane/eyre.hoon index 58ac07e72..01218dc38 100644 --- a/pkg/arvo/sys/vane/eyre.hoon +++ b/pkg/arvo/sys/vane/eyre.hoon @@ -979,7 +979,7 @@ =/ actual-redirect ?:(=(u.redirect '') '/' u.redirect) %- handle-response :* %start - :- status-code=307 + :- status-code=303 ^= headers :~ ['location' actual-redirect] ['set-cookie' cookie-line] diff --git a/pkg/arvo/tests/sys/vane/eyre.hoon b/pkg/arvo/tests/sys/vane/eyre.hoon index 9d6d67a38..8ce38a774 100644 --- a/pkg/arvo/tests/sys/vane/eyre.hoon +++ b/pkg/arvo/tests/sys/vane/eyre.hoon @@ -613,12 +613,12 @@ ^- (hypo sign:http-server-gate) :- *type :* %g %unto %fact %http-response-header - !>([307 ['location' '/~/login?redirect=/~landscape/inner-path']~]) + !>([303 ['location' '/~/login?redirect=/~landscape/inner-path']~]) == == ^= expected-move :~ :* duct=~[/http-blah] %give %response - [%start [307 ['location' '/~/login?redirect=/~landscape/inner-path']~] ~ %.n] + [%start [303 ['location' '/~/login?redirect=/~landscape/inner-path']~] ~ %.n] == == == :: the browser then fetches the login page :: @@ -2152,7 +2152,7 @@ %give %response %start - :- 307 + :- 303 :~ ['location' '/~landscape'] :- 'set-cookie' 'urbauth-~nul=0v3.q0p7t.mlkkq.cqtto.p0nvi.2ieea; Path=/; Max-Age=604800' diff --git a/pkg/interface/config/urbitrc-sample b/pkg/interface/config/urbitrc-sample index 88053638e..1315a1d06 100644 --- a/pkg/interface/config/urbitrc-sample +++ b/pkg/interface/config/urbitrc-sample @@ -1,5 +1,6 @@ module.exports = { URBIT_PIERS: [ "/Users/user/ships/zod/home", - ] + ], + herb: false }; diff --git a/pkg/interface/config/webpack.dev.js b/pkg/interface/config/webpack.dev.js index 7d972ee62..caea66830 100644 --- a/pkg/interface/config/webpack.dev.js +++ b/pkg/interface/config/webpack.dev.js @@ -2,6 +2,41 @@ const path = require('path'); // const HtmlWebpackPlugin = require('html-webpack-plugin'); // const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const urbitrc = require('./urbitrc'); +const fs = require('fs'); +const util = require('util'); +const exec = util.promisify(require('child_process').exec); + +function copyFile(src,dest) { + return new Promise((res,rej) => + fs.copyFile(src,dest, err => err ? rej(err) : res())); +} + +class UrbitShipPlugin { + constructor(urbitrc) { + this.piers = urbitrc.URBIT_PIERS; + this.herb = urbitrc.herb || false; + } + + apply(compiler) { + compiler.hooks.afterCompile.tapPromise( + 'UrbitShipPlugin', + async (compilation) => { + const src = path.resolve(compiler.options.output.path, 'index.js'); + return Promise.all(this.piers.map(pier => { + const dst = path.resolve(pier, 'app/landscape/js/index.js'); + copyFile(src, dst).then(() => { + if(!this.herb) { + return; + } + pier = pier.split('/'); + const desk = pier.pop(); + return exec(`herb -p hood -d '+hood/commit %${desk}' ${pier.join('/')}`); + }); + })); + } + ) + } +} module.exports = { mode: 'development', @@ -49,16 +84,18 @@ module.exports = { // historyApiFallback: true // }, plugins: [ + new UrbitShipPlugin(urbitrc) // new CleanWebpackPlugin(), // new HtmlWebpackPlugin({ // title: 'Hot Module Replacement', // template: './public/index.html', // }), ], + watch: true, output: { filename: 'index.js', chunkFilename: 'index.js', - path: path.resolve(urbitrc.URBIT_PIERS[0] + '/app/landscape/', 'js'), + path: path.resolve(__dirname, '../dist'), publicPath: '/' }, optimization: { diff --git a/pkg/interface/src/App.js b/pkg/interface/src/App.js index f0c08ebb3..34c8d2919 100644 --- a/pkg/interface/src/App.js +++ b/pkg/interface/src/App.js @@ -1,5 +1,5 @@ import * as React from 'react'; -import { BrowserRouter as Router, Route, Link, withRouter } from 'react-router-dom'; +import { BrowserRouter as Router, Route, withRouter, Switch } from 'react-router-dom'; import styled, { ThemeProvider, createGlobalStyle } from 'styled-components'; import './css/indigo-static.css'; import './css/fonts.css'; @@ -8,11 +8,13 @@ import { light } from '@tlon/indigo-react'; import LaunchApp from './apps/launch/app'; import ChatApp from './apps/chat/app'; import DojoApp from './apps/dojo/app'; -import StatusBar from './components/StatusBar'; import GroupsApp from './apps/groups/app'; import LinksApp from './apps/links/app'; import PublishApp from './apps/publish/app'; +import StatusBar from './components/StatusBar'; +import NotFound from './components/404'; + import GlobalStore from './store/global'; import GlobalSubscription from './subscription/global'; import GlobalApi from './api/global'; @@ -71,48 +73,64 @@ export default class App extends React.Component { api={this.api} />
Sigil Color
+Ship Name
diff --git a/pkg/interface/src/apps/groups/components/lib/contact-sidebar.js b/pkg/interface/src/apps/groups/components/lib/contact-sidebar.js index b2552ddeb..80838ac35 100644 --- a/pkg/interface/src/apps/groups/components/lib/contact-sidebar.js +++ b/pkg/interface/src/apps/groups/components/lib/contact-sidebar.js @@ -99,7 +99,7 @@ export class ContactSidebar extends Component { style={{ paddingTop: 6 }} onClick={() => { this.setState({ awaiting: true }, (() => { - props.api.groupRemove(props.path, [`~${member}`]) + props.api.group.remove(props.path, [`~${member}`]) .then(() => { this.setState({ awaiting: false }); }); diff --git a/pkg/interface/src/apps/groups/components/lib/group-detail.js b/pkg/interface/src/apps/groups/components/lib/group-detail.js index 7fdfb6a1c..9d71acb0e 100644 --- a/pkg/interface/src/apps/groups/components/lib/group-detail.js +++ b/pkg/interface/src/apps/groups/components/lib/group-detail.js @@ -18,11 +18,10 @@ export class GroupDetail extends Component { componentDidMount() { const { props } = this; - const channelPath = `${props.path}/contacts${props.path}`; - if ((props.association) && (props.association[channelPath])) { + if (props.association.metadata) { this.setState({ - title: props.association[channelPath].metadata.title, - description: props.association[channelPath].metadata.description + title: props.association.metadata.title, + description: props.association.metadata.description }); } } @@ -30,11 +29,10 @@ export class GroupDetail extends Component { componentDidUpdate(prevProps) { const { props } = this; if (prevProps !== this.props) { - const channelPath = `${props.path}/contacts${props.path}`; - if ((props.association) && (props.association[channelPath])) { + if (props.association.metadata) { this.setState({ - title: props.association[channelPath].metadata.title, - description: props.association[channelPath].metadata.description + title: props.association.metadata.title, + description: props.association.metadata.description }); } } @@ -54,78 +52,74 @@ export class GroupDetail extends Component { const responsiveClass = props.activeDrawer === 'detail' ? 'db ' : 'dn db-ns '; - const isEmpty = (Object.keys(props.association).length === 0) || - ((Object.keys(props.association).length === 1) && - (Object.keys(props.association)[0].includes('contacts'))); + let channelList = []; - let channelList = (); + Object.keys(props.associations).filter((app) => { + return app !== 'contacts'; + }).map((app) => { + Object.keys(props.associations[app]).filter((channel) => { + return props.associations[app][channel]['group-path'] === props.association['group-path']; + }) + .map((channel) => { + const channelObj = props.associations[app][channel]; + const title = + channelObj.metadata?.title || channelObj['app-path'] || ''; - channelList = Object.keys(props.association).sort((a, b) => { - const aChannel = props.association[a]; - const bChannel = props.association[b]; - - const aTitle = aChannel.metadata.title || a; - const bTitle = bChannel.metadata.title || b; - - return aTitle.toLowerCase().localeCompare(bTitle.toLowerCase()); - }).map((key) => { - const channel = props.association[key]; - if (!('metadata' in channel)) { - return ; - } - - if (channel['app-name'] === 'contacts') { - return ; - } - - const title = channel.metadata.title || channel['app-path'] || ''; - const color = uxToHex(channel.metadata.color) || '000000'; - let app = channel['app-name'] || 'Unknown'; - const channelPath = channel['app-path']; - const link = `/~${app}/join${channelPath}`; - app = app.charAt(0).toUpperCase() + app.slice(1); - - const overlay = { - r: parseInt(color.slice(0, 2), 16), - g: parseInt(color.slice(2, 4), 16), - b: parseInt(color.slice(4, 6), 16) - }; - - const tile = (app === 'Unknown') - ? - :{title}
-- {app} - - Open - -
-{each.title}
++ {each.app} + + Open + +
+Please try again. -
+ className="f9 red2 pt1" + >Please try again. + ; } - if (location.protocol === "https:") { + if (location.protocol === 'https:') { secureCheck = this.locationSubmit()}>Detect -> + style={{ right: 8, top: 8 }} + onClick={() => this.locationSubmit()} + >Detect ->; } return this.renderWrapper( -- Please enter your{" "} +
+ Please enter your{' '} + target="_blank" + > latitude and longitude .
{error} -+ style={{ left: 8, top: 8 }} + > Weather
+ style={{ bottom: 8, left: 8, cursor: 'pointer' }} + > -> Set location
Weather
@@ -230,7 +244,8 @@ export default class WeatherTile extends React.Component { style={{ right: 8, top: 8 }} onClick={() => this.setState({ manualEntry: !this.state.manualEntry }) - }> + } + > ->{notebook?.about}
; break; case 'subscribers': inner =Convert Notebook
-- Convert this notebook into a group with associated chat, or select a - group to add this notebook to. -
+ {this.renderHeader( + 'Convert Notebook', + 'Convert this notebook into a group with associated chat, or select a group to add this notebook to.')}{title}
+{subtitle}
+ > + ); + } + render() { const commentsSwitchClasses = (this.state.comments) ? 'relative checked bg-green2 br3 h1 toggle v-mid z-0' : 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0'; const copyShortcode =Share
-Share a shortcode to join this notebook
+ {this.renderHeader('Share', 'Share a shortcode to join this notebook')}Delete Notebook
-- Permanently delete this notebook. (All current members will no - longer see this notebook) -
+ {this.renderHeader( + 'Delete Notebook', + 'Permanently delete this notebook. (All current members will no longer see this notebook)')} -Rename
-Change the name of this notebook
+ {this.renderHeader('Rename', 'Change the name of this notebook')}Change description
-Change the description of this notebook
+ {this.renderHeader("Change description", "Change the description of this notebook")}Not found.
+ If this is unexpected, email support@tlon.io
or submit an issue.