mirror of
https://github.com/urbit/shrub.git
synced 2024-12-02 08:55:07 +03:00
Merge pull request #3312 from tylershuster/reactive-head
interface: made head reactive
This commit is contained in:
commit
ed01376b74
23
pkg/interface/package-lock.json
generated
23
pkg/interface/package-lock.json
generated
@ -7700,6 +7700,24 @@
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
|
||||
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
|
||||
},
|
||||
"react-helmet": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
|
||||
"integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
|
||||
"requires": {
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-fast-compare": "^3.1.1",
|
||||
"react-side-effect": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-fast-compare": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-hot-loader": {
|
||||
"version": "4.12.21",
|
||||
"resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.12.21.tgz",
|
||||
@ -7781,6 +7799,11 @@
|
||||
"tiny-warning": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"react-side-effect": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.0.tgz",
|
||||
"integrity": "sha512-IgmcegOSi5SNX+2Snh1vqmF0Vg/CbkycU9XZbOHJlZ6kMzTmi3yc254oB1WCkgA7OQtIAoLmcSFuHTc/tlcqXg=="
|
||||
},
|
||||
"react-window": {
|
||||
"version": "1.8.5",
|
||||
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.5.tgz",
|
||||
|
@ -23,6 +23,7 @@
|
||||
"react": "^16.5.2",
|
||||
"react-codemirror2": "^6.0.1",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-markdown": "^4.3.1",
|
||||
"react-router-dom": "^5.0.0",
|
||||
"react-window": "^1.8.5",
|
||||
|
@ -4,6 +4,7 @@ import * as React from 'react';
|
||||
import { BrowserRouter as Router, Route, withRouter, Switch } from 'react-router-dom';
|
||||
import styled, { ThemeProvider, createGlobalStyle } from 'styled-components';
|
||||
import { sigil as sigiljs, stringRenderer } from 'urbit-sigil-js';
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
import Mousetrap from 'mousetrap';
|
||||
import 'mousetrap-global-bind';
|
||||
@ -50,7 +51,7 @@ class App extends React.Component {
|
||||
new GlobalSubscription(this.store, this.api, this.appChannel);
|
||||
|
||||
this.updateTheme = this.updateTheme.bind(this);
|
||||
this.setFavicon = this.setFavicon.bind(this);
|
||||
this.faviconString = this.faviconString.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -64,39 +65,30 @@ class App extends React.Component {
|
||||
e.stopImmediatePropagation();
|
||||
this.api.local.setOmnibox();
|
||||
});
|
||||
this.setFavicon();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.themeWatcher.removeListener(this.updateTheme);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
this.setFavicon();
|
||||
}
|
||||
|
||||
updateTheme(e) {
|
||||
this.api.local.setDark(e.matches);
|
||||
}
|
||||
|
||||
setFavicon() {
|
||||
if (window.ship.length < 14) {
|
||||
let background = '#ffffff';
|
||||
if (this.state.contacts.hasOwnProperty('/~/default')) {
|
||||
background = `#${uxToHex(this.state.contacts['/~/default'][window.ship].color)}`;
|
||||
}
|
||||
const foreground = foregroundFromBackground(background);
|
||||
const svg = sigiljs({
|
||||
patp: window.ship,
|
||||
renderer: stringRenderer,
|
||||
size: 16,
|
||||
colors: [background, foreground]
|
||||
});
|
||||
const dataurl = 'data:image/svg+xml;base64,' + btoa(svg);
|
||||
const favicon = document.querySelector('[rel=icon]');
|
||||
favicon.href = dataurl;
|
||||
favicon.type = 'image/svg+xml';
|
||||
faviconString() {
|
||||
let background = '#ffffff';
|
||||
if (this.state.contacts.hasOwnProperty('/~/default')) {
|
||||
background = `#${uxToHex(this.state.contacts['/~/default'][window.ship].color)}`;
|
||||
}
|
||||
const foreground = foregroundFromBackground(background);
|
||||
const svg = sigiljs({
|
||||
patp: window.ship,
|
||||
renderer: stringRenderer,
|
||||
size: 16,
|
||||
colors: [background, foreground]
|
||||
});
|
||||
const dataurl = 'data:image/svg+xml;base64,' + btoa(svg);
|
||||
return dataurl;
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -107,6 +99,11 @@ class App extends React.Component {
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<Helmet>
|
||||
{window.ship.length < 14
|
||||
? <link rel="icon" type="image/svg+xml" href={this.faviconString()} />
|
||||
: null}
|
||||
</Helmet>
|
||||
<Root>
|
||||
<Router>
|
||||
<StatusBarWithRouter
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
import './css/custom.css';
|
||||
|
||||
@ -24,14 +25,11 @@ type ChatAppProps = StoreState & {
|
||||
};
|
||||
|
||||
export default class ChatApp extends React.Component<ChatAppProps, {}> {
|
||||
totalUnreads = 0;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
document.title = 'OS1 - Chat';
|
||||
// preload spinner asset
|
||||
new Image().src = '/~landscape/img/Spinner.png';
|
||||
|
||||
@ -79,12 +77,6 @@ export default class ChatApp extends React.Component<ChatAppProps, {}> {
|
||||
}
|
||||
});
|
||||
|
||||
if (totalUnreads !== this.totalUnreads) {
|
||||
document.title =
|
||||
totalUnreads > 0 ? `(${totalUnreads}) OS1 - Chat` : 'OS1 - Chat';
|
||||
this.totalUnreads = totalUnreads;
|
||||
}
|
||||
|
||||
const {
|
||||
invites,
|
||||
s3,
|
||||
@ -113,208 +105,213 @@ export default class ChatApp extends React.Component<ChatAppProps, {}> {
|
||||
);
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat"
|
||||
render={(props) => {
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
chatHideonMobile={true}
|
||||
sidebarShown={sidebarShown}
|
||||
sidebar={renderChannelSidebar(props)}
|
||||
>
|
||||
<div className="h-100 w-100 overflow-x-hidden flex flex-column bg-white bg-gray0-d">
|
||||
<div className="pl3 pr3 pt2 dt pb3 w-100 h-100">
|
||||
<p className="f8 pt3 gray2 w-100 h-100 dtc v-mid tc">
|
||||
Select, create, or join a chat to begin.
|
||||
</p>
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{totalUnreads > 0 ? `(${totalUnreads}) ` : ''}OS1 - Chat</title>
|
||||
</Helmet>
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat"
|
||||
render={(props) => {
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
chatHideonMobile={true}
|
||||
sidebarShown={sidebarShown}
|
||||
sidebar={renderChannelSidebar(props)}
|
||||
>
|
||||
<div className="h-100 w-100 overflow-x-hidden flex flex-column bg-white bg-gray0-d">
|
||||
<div className="pl3 pr3 pt2 dt pb3 w-100 h-100">
|
||||
<p className="f8 pt3 gray2 w-100 h-100 dtc v-mid tc">
|
||||
Select, create, or join a chat to begin.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/new/dm/:ship?"
|
||||
render={(props) => {
|
||||
const ship = props.match.params.ship;
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/new/dm/:ship?"
|
||||
render={(props) => {
|
||||
const ship = props.match.params.ship;
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
sidebar={renderChannelSidebar(props)}
|
||||
sidebarShown={sidebarShown}
|
||||
>
|
||||
<NewDmScreen
|
||||
api={api}
|
||||
inbox={inbox}
|
||||
groups={groups || {}}
|
||||
contacts={contacts || {}}
|
||||
associations={associations.contacts}
|
||||
chatSynced={chatSynced || {}}
|
||||
autoCreate={ship}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/new"
|
||||
render={(props) => {
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
sidebar={renderChannelSidebar(props)}
|
||||
sidebarShown={sidebarShown}
|
||||
>
|
||||
<NewScreen
|
||||
api={api}
|
||||
inbox={inbox || {}}
|
||||
groups={groups}
|
||||
contacts={contacts || {}}
|
||||
associations={associations.contacts}
|
||||
chatSynced={chatSynced || {}}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/join/:ship?/:station?"
|
||||
render={(props) => {
|
||||
let station = `/${props.match.params.ship}/${props.match.params.station}`;
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
sidebar={renderChannelSidebar(props)}
|
||||
sidebarShown={sidebarShown}
|
||||
>
|
||||
<NewDmScreen
|
||||
api={api}
|
||||
inbox={inbox}
|
||||
groups={groups || {}}
|
||||
contacts={contacts || {}}
|
||||
associations={associations.contacts}
|
||||
chatSynced={chatSynced || {}}
|
||||
autoCreate={ship}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/new"
|
||||
render={(props) => {
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
sidebar={renderChannelSidebar(props)}
|
||||
sidebarShown={sidebarShown}
|
||||
>
|
||||
<NewScreen
|
||||
api={api}
|
||||
inbox={inbox || {}}
|
||||
groups={groups}
|
||||
contacts={contacts || {}}
|
||||
associations={associations.contacts}
|
||||
chatSynced={chatSynced || {}}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/join/:ship?/:station?"
|
||||
render={(props) => {
|
||||
let station = `/${props.match.params.ship}/${props.match.params.station}`;
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
sidebar={renderChannelSidebar(props)}
|
||||
sidebarShown={sidebarShown}
|
||||
>
|
||||
<JoinScreen
|
||||
api={api}
|
||||
inbox={inbox}
|
||||
autoJoin={station}
|
||||
chatSynced={chatSynced || {}}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/(popout)?/room/(~)?/:ship/:station+"
|
||||
render={(props) => {
|
||||
let station = `/${props.match.params.ship}/${props.match.params.station}`;
|
||||
const mailbox = inbox[station] || {
|
||||
config: {
|
||||
read: 0,
|
||||
length: 0
|
||||
},
|
||||
envelopes: []
|
||||
};
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
sidebar={renderChannelSidebar(props)}
|
||||
sidebarShown={sidebarShown}
|
||||
>
|
||||
<JoinScreen
|
||||
api={api}
|
||||
inbox={inbox}
|
||||
autoJoin={station}
|
||||
chatSynced={chatSynced || {}}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/(popout)?/room/(~)?/:ship/:station+"
|
||||
render={(props) => {
|
||||
let station = `/${props.match.params.ship}/${props.match.params.station}`;
|
||||
const mailbox = inbox[station] || {
|
||||
config: {
|
||||
read: 0,
|
||||
length: 0
|
||||
},
|
||||
envelopes: []
|
||||
};
|
||||
|
||||
let roomContacts = {};
|
||||
const associatedGroup =
|
||||
station in associations['chat'] &&
|
||||
'group-path' in associations.chat[station]
|
||||
? associations.chat[station]['group-path']
|
||||
: '';
|
||||
let roomContacts = {};
|
||||
const associatedGroup =
|
||||
station in associations['chat'] &&
|
||||
'group-path' in associations.chat[station]
|
||||
? associations.chat[station]['group-path']
|
||||
: '';
|
||||
|
||||
if (associations.chat[station] && associatedGroup in contacts) {
|
||||
roomContacts = contacts[associatedGroup];
|
||||
}
|
||||
if (associations.chat[station] && associatedGroup in contacts) {
|
||||
roomContacts = contacts[associatedGroup];
|
||||
}
|
||||
|
||||
const association =
|
||||
station in associations['chat'] ? associations.chat[station] : {};
|
||||
const association =
|
||||
station in associations['chat'] ? associations.chat[station] : {};
|
||||
|
||||
const group = groups[association['group-path']] || groupBunts.group();
|
||||
const group = groups[association['group-path']] || groupBunts.group();
|
||||
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
sidebar={renderChannelSidebar(props, station)}
|
||||
>
|
||||
<ChatScreen
|
||||
chatSynced={chatSynced || {}}
|
||||
station={station}
|
||||
association={association}
|
||||
api={api}
|
||||
read={mailbox.config.read}
|
||||
length={mailbox.config.length}
|
||||
envelopes={mailbox.envelopes}
|
||||
inbox={inbox}
|
||||
contacts={roomContacts}
|
||||
group={group}
|
||||
pendingMessages={pendingMessages}
|
||||
s3={s3}
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
chatInitialized={chatInitialized}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/(popout)?/settings/(~)?/:ship/:station+"
|
||||
render={(props) => {
|
||||
let station = `/${props.match.params.ship}/${props.match.params.station}`;
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
sidebar={renderChannelSidebar(props, station)}
|
||||
>
|
||||
<ChatScreen
|
||||
chatSynced={chatSynced || {}}
|
||||
station={station}
|
||||
association={association}
|
||||
api={api}
|
||||
read={mailbox.config.read}
|
||||
length={mailbox.config.length}
|
||||
envelopes={mailbox.envelopes}
|
||||
inbox={inbox}
|
||||
contacts={roomContacts}
|
||||
group={group}
|
||||
pendingMessages={pendingMessages}
|
||||
s3={s3}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
chatInitialized={chatInitialized}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~chat/(popout)?/settings/(~)?/:ship/:station+"
|
||||
render={(props) => {
|
||||
let station = `/${props.match.params.ship}/${props.match.params.station}`;
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
|
||||
const association =
|
||||
station in associations['chat'] ? associations.chat[station] : {};
|
||||
const group = groups[association['group-path']] || groupBunts.group();
|
||||
const association =
|
||||
station in associations['chat'] ? associations.chat[station] : {};
|
||||
const group = groups[association['group-path']] || groupBunts.group();
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
sidebar={renderChannelSidebar(props, station)}
|
||||
>
|
||||
<SettingsScreen
|
||||
{...props}
|
||||
station={station}
|
||||
association={association}
|
||||
groups={groups || {}}
|
||||
group={group}
|
||||
contacts={contacts || {}}
|
||||
associations={associations.contacts}
|
||||
api={api}
|
||||
inbox={inbox}
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
sidebarHideOnMobile={true}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
sidebar={renderChannelSidebar(props, station)}
|
||||
>
|
||||
<SettingsScreen
|
||||
{...props}
|
||||
station={station}
|
||||
association={association}
|
||||
groups={groups || {}}
|
||||
group={group}
|
||||
contacts={contacts || {}}
|
||||
associations={associations.contacts}
|
||||
api={api}
|
||||
inbox={inbox}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Route, Link } from 'react-router-dom';
|
||||
import classnames from 'classnames';
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
import { Popout } from './components/lib/icons/popout';
|
||||
import { History } from './components/history';
|
||||
@ -28,8 +29,6 @@ export default class DojoApp extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
document.title = 'OS1 - Dojo';
|
||||
|
||||
const channel = new window.channel();
|
||||
this.api = new Api(this.props.ship, channel);
|
||||
this.store.api = this.api;
|
||||
@ -46,56 +45,61 @@ export default class DojoApp extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
className="bg-white bg-gray0-d"
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
<Route
|
||||
exact
|
||||
path="/~dojo/:popout?"
|
||||
render={(props) => {
|
||||
const popout = Boolean(props.match.params.popout);
|
||||
<>
|
||||
<Helmet>
|
||||
<title>OS1 - Dojo</title>
|
||||
</Helmet>
|
||||
<div
|
||||
className="bg-white bg-gray0-d"
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
<Route
|
||||
exact
|
||||
path="/~dojo/:popout?"
|
||||
render={(props) => {
|
||||
const popout = Boolean(props.match.params.popout);
|
||||
|
||||
const popoutClasses = classnames({
|
||||
'mh4-m mh4-l mh4-xl': !popout,
|
||||
'mb4-m mb4-l mb4-xl': !popout,
|
||||
'ba-m ba-l ba-xl': !popout
|
||||
});
|
||||
const popoutClasses = classnames({
|
||||
'mh4-m mh4-l mh4-xl': !popout,
|
||||
'mb4-m mb4-l mb4-xl': !popout,
|
||||
'ba-m ba-l ba-xl': !popout
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="w-100 h-100 flex-m flex-l flex-xl">
|
||||
<div
|
||||
className="db dn-m dn-l dn-xl inter bg-white bg-gray0-d dt w-100"
|
||||
style={{ height: 40 }}
|
||||
>
|
||||
return (
|
||||
<div className="w-100 h-100 flex-m flex-l flex-xl">
|
||||
<div
|
||||
className="db dn-m dn-l dn-xl inter bg-white bg-gray0-d dt w-100"
|
||||
style={{ height: 40 }}
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
'pa3 bg-white bg-gray0-d black white-d mono w-100 f8 relative' +
|
||||
' h-100-m40-s b--gray2 br1 flex-auto flex flex-column ' +
|
||||
popoutClasses
|
||||
}
|
||||
style={{
|
||||
lineHeight: '1.4',
|
||||
cursor: 'text'
|
||||
}}
|
||||
>
|
||||
<Popout popout={popout} />
|
||||
<History commandLog={this.state.txt} />
|
||||
<Input
|
||||
ship={this.props.ship}
|
||||
cursor={this.state.cursor}
|
||||
prompt={this.state.prompt}
|
||||
input={this.state.input}
|
||||
api={this.api}
|
||||
store={this.store}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
'pa3 bg-white bg-gray0-d black white-d mono w-100 f8 relative' +
|
||||
' h-100-m40-s b--gray2 br1 flex-auto flex flex-column ' +
|
||||
popoutClasses
|
||||
}
|
||||
style={{
|
||||
lineHeight: '1.4',
|
||||
cursor: 'text'
|
||||
}}
|
||||
>
|
||||
<Popout popout={popout} />
|
||||
<History commandLog={this.state.txt} />
|
||||
<Input
|
||||
ship={this.props.ship}
|
||||
cursor={this.state.cursor}
|
||||
prompt={this.state.prompt}
|
||||
input={this.state.input}
|
||||
api={this.api}
|
||||
store={this.store}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
import './css/custom.css';
|
||||
|
||||
@ -25,7 +26,6 @@ type GroupsAppProps = StoreState & {
|
||||
|
||||
export default class GroupsApp extends Component<GroupsAppProps, {}> {
|
||||
componentDidMount() {
|
||||
document.title = 'OS1 - Groups';
|
||||
// preload spinner asset
|
||||
new Image().src = '/~landscape/img/Spinner.png';
|
||||
|
||||
@ -55,6 +55,10 @@ export default class GroupsApp extends Component<GroupsAppProps, {}> {
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>OS1 - Groups</title>
|
||||
</Helmet>
|
||||
<Switch>
|
||||
<Route exact path="/~groups"
|
||||
render={(props) => {
|
||||
@ -357,6 +361,7 @@ export default class GroupsApp extends Component<GroupsAppProps, {}> {
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
import './css/custom.css';
|
||||
|
||||
@ -8,7 +9,6 @@ import Welcome from './components/welcome';
|
||||
export default class LaunchApp extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
document.title = 'OS1 - Home';
|
||||
// preload spinner asset
|
||||
new Image().src = '/~landscape/img/Spinner.png';
|
||||
|
||||
@ -18,19 +18,24 @@ export default class LaunchApp extends React.Component {
|
||||
const { props } = this;
|
||||
|
||||
return (
|
||||
<div className="h-100 flex flex-column h-100">
|
||||
<div className='v-mid ph2 dtc-m dtc-l dtc-xl flex justify-between flex-wrap' style={{ maxWidth: '40rem' }}>
|
||||
<Welcome firstTime={props.launch.firstTime} api={props.api} />
|
||||
<Tiles
|
||||
tiles={props.launch.tiles}
|
||||
tileOrdering={props.launch.tileOrdering}
|
||||
api={props.api}
|
||||
location={props.userLocation}
|
||||
weather={props.weather}
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute mono bottom-0 left-0 f9 gray2 ml4 mb4 f8"> {props.baseHash} </div>
|
||||
</div>
|
||||
<>
|
||||
<Helmet>
|
||||
<title>OS1 - Home</title>
|
||||
</Helmet>
|
||||
<div className="h-100 flex flex-column h-100">
|
||||
<div className='v-mid ph2 dtc-m dtc-l dtc-xl flex justify-between flex-wrap' style={{ maxWidth: '40rem' }}>
|
||||
<Welcome firstTime={props.launch.firstTime} api={props.api} />
|
||||
<Tiles
|
||||
tiles={props.launch.tiles}
|
||||
tileOrdering={props.launch.tileOrdering}
|
||||
api={props.api}
|
||||
location={props.userLocation}
|
||||
weather={props.weather}
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute mono bottom-0 left-0 f9 gray2 ml4 mb4 f8"> {props.baseHash} </div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
@ -22,11 +23,9 @@ import {
|
||||
export class LinksApp extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.totalUnseen = 0;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
document.title = 'OS1 - Links';
|
||||
// preload spinner asset
|
||||
new Image().src = '/~landscape/img/Spinner.png';
|
||||
|
||||
@ -61,11 +60,6 @@ export class LinksApp extends Component {
|
||||
0
|
||||
);
|
||||
|
||||
if(totalUnseen !== this.totalUnseen) {
|
||||
document.title = totalUnseen !== 0 ? `(${totalUnseen}) OS1 - Links` : 'OS1 - Links';
|
||||
this.totalUnseen = totalUnseen;
|
||||
}
|
||||
|
||||
const invites = props.invites ?
|
||||
props.invites : {};
|
||||
|
||||
@ -75,167 +69,77 @@ export class LinksApp extends Component {
|
||||
const { api, sidebarShown } = this.props;
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route exact path="/~link"
|
||||
render={ (props) => {
|
||||
return (
|
||||
<Skeleton
|
||||
active="collections"
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
groups={groups}
|
||||
rightPanelHide={true}
|
||||
sidebarShown={sidebarShown}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<MessageScreen text="Select or create a collection to begin." />
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/new"
|
||||
render={(props) => {
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
groups={groups}
|
||||
sidebarShown={sidebarShown}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<NewScreen
|
||||
associations={associations}
|
||||
groups={groups}
|
||||
contacts={contacts}
|
||||
api={api}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/join/:resource"
|
||||
render={ (props) => {
|
||||
const resourcePath = '/' + props.match.params.resource;
|
||||
|
||||
const autoJoin = () => {
|
||||
try {
|
||||
api.links.joinCollection(resourcePath);
|
||||
props.history.push(makeRoutePath(resourcePath));
|
||||
} catch(err) {
|
||||
setTimeout(autoJoin, 2000);
|
||||
}
|
||||
};
|
||||
autoJoin();
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/(popout)?/:resource/members"
|
||||
render={(props) => {
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
const resourcePath = '/' + props.match.params.resource;
|
||||
const resource = associations.link[resourcePath] || { metadata: {} };
|
||||
|
||||
const contactDetails = contacts[resource['group-path']] || {};
|
||||
const group = groups[resource['group-path']] || new Set([]);
|
||||
const amOwner = amOwnerOfGroup(resource['group-path']);
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
groups={groups}
|
||||
selected={resourcePath}
|
||||
sidebarShown={sidebarShown}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<MemberScreen
|
||||
sidebarShown={sidebarShown}
|
||||
resource={resource}
|
||||
contacts={contacts}
|
||||
contactDetails={contactDetails}
|
||||
groupPath={resource['group-path']}
|
||||
group={group}
|
||||
groups={groups}
|
||||
associations={associations}
|
||||
amOwner={amOwner}
|
||||
resourcePath={resourcePath}
|
||||
popout={popout}
|
||||
api={api}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/(popout)?/:resource/settings"
|
||||
render={ (props) => {
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
const resourcePath = '/' + props.match.params.resource;
|
||||
const resource = associations.link[resourcePath] || false;
|
||||
|
||||
const contactDetails = contacts[resource['group-path']] || {};
|
||||
const group = groups[resource['group-path']] || new Set([]);
|
||||
const amOwner = amOwnerOfGroup(resource['group-path']);
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
groups={groups}
|
||||
selected={resourcePath}
|
||||
sidebarShown={sidebarShown}
|
||||
popout={popout}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<SettingsScreen
|
||||
sidebarShown={sidebarShown}
|
||||
resource={resource}
|
||||
contacts={contacts}
|
||||
contactDetails={contactDetails}
|
||||
groupPath={resource['group-path']}
|
||||
group={group}
|
||||
amOwner={amOwner}
|
||||
resourcePath={resourcePath}
|
||||
popout={popout}
|
||||
api={api}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/(popout)?/:resource/:page?"
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{totalUnseen > 0 ? `(${totalUnseen}) ` : ''}OS1 - Links</title>
|
||||
</Helmet>
|
||||
<Switch>
|
||||
<Route exact path="/~link"
|
||||
render={ (props) => {
|
||||
return (
|
||||
<Skeleton
|
||||
active="collections"
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
groups={groups}
|
||||
rightPanelHide={true}
|
||||
sidebarShown={sidebarShown}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<MessageScreen text="Select or create a collection to begin." />
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/new"
|
||||
render={(props) => {
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
groups={groups}
|
||||
sidebarShown={sidebarShown}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<NewScreen
|
||||
associations={associations}
|
||||
groups={groups}
|
||||
contacts={contacts}
|
||||
api={api}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/join/:resource"
|
||||
render={ (props) => {
|
||||
const resourcePath = '/' + props.match.params.resource;
|
||||
|
||||
const autoJoin = () => {
|
||||
try {
|
||||
api.links.joinCollection(resourcePath);
|
||||
props.history.push(makeRoutePath(resourcePath));
|
||||
} catch(err) {
|
||||
setTimeout(autoJoin, 2000);
|
||||
}
|
||||
};
|
||||
autoJoin();
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/(popout)?/:resource/members"
|
||||
render={(props) => {
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
const resourcePath = '/' + props.match.params.resource;
|
||||
const resource = associations.link[resourcePath] || { metadata: {} };
|
||||
|
||||
const amOwner = amOwnerOfGroup(resource['group-path']);
|
||||
|
||||
const contactDetails = contacts[resource['group-path']] || {};
|
||||
|
||||
const page = props.match.params.page || 0;
|
||||
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
|
||||
const channelLinks = links[resourcePath]
|
||||
? links[resourcePath]
|
||||
: { local: {} };
|
||||
|
||||
const channelComments = comments[resourcePath]
|
||||
? comments[resourcePath]
|
||||
: {};
|
||||
|
||||
const channelSeen = seen[resourcePath]
|
||||
? seen[resourcePath]
|
||||
: {};
|
||||
const group = groups[resource['group-path']] || new Set([]);
|
||||
const amOwner = amOwnerOfGroup(resource['group-path']);
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
@ -244,55 +148,38 @@ export class LinksApp extends Component {
|
||||
groups={groups}
|
||||
selected={resourcePath}
|
||||
sidebarShown={sidebarShown}
|
||||
sidebarHideMobile={true}
|
||||
popout={popout}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<Links
|
||||
{...props}
|
||||
contacts={contactDetails}
|
||||
links={channelLinks}
|
||||
comments={channelComments}
|
||||
seen={channelSeen}
|
||||
page={page}
|
||||
resourcePath={resourcePath}
|
||||
resource={resource}
|
||||
amOwner={amOwner}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
api={api}
|
||||
<MemberScreen
|
||||
sidebarShown={sidebarShown}
|
||||
resource={resource}
|
||||
contacts={contacts}
|
||||
contactDetails={contactDetails}
|
||||
groupPath={resource['group-path']}
|
||||
group={group}
|
||||
groups={groups}
|
||||
associations={associations}
|
||||
amOwner={amOwner}
|
||||
resourcePath={resourcePath}
|
||||
popout={popout}
|
||||
api={api}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/(popout)?/:resource/:page/:index/:encodedUrl/:commentpage?"
|
||||
<Route exact path="/~link/(popout)?/:resource/settings"
|
||||
render={ (props) => {
|
||||
const resourcePath = '/' + props.match.params.resource;
|
||||
const resource = associations.link[resourcePath] || { metadata: {} };
|
||||
|
||||
const amOwner = amOwnerOfGroup(resource['group-path']);
|
||||
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
const resourcePath = '/' + props.match.params.resource;
|
||||
const resource = associations.link[resourcePath] || false;
|
||||
|
||||
const contactDetails = contacts[resource['group-path']] || {};
|
||||
|
||||
const index = props.match.params.index || 0;
|
||||
const page = props.match.params.page || 0;
|
||||
const url = base64urlDecode(props.match.params.encodedUrl);
|
||||
|
||||
const data = links[resourcePath]
|
||||
? links[resourcePath][page]
|
||||
? links[resourcePath][page][index]
|
||||
: {}
|
||||
: {};
|
||||
const coms = !comments[resourcePath]
|
||||
? undefined
|
||||
: comments[resourcePath][url];
|
||||
|
||||
const commentPage = props.match.params.commentpage || 0;
|
||||
const group = groups[resource['group-path']] || new Set([]);
|
||||
const amOwner = amOwnerOfGroup(resource['group-path']);
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
@ -301,34 +188,146 @@ export class LinksApp extends Component {
|
||||
groups={groups}
|
||||
selected={resourcePath}
|
||||
sidebarShown={sidebarShown}
|
||||
sidebarHideMobile={true}
|
||||
popout={popout}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<LinkDetail
|
||||
{...props}
|
||||
resource={resource}
|
||||
page={page}
|
||||
url={url}
|
||||
linkIndex={index}
|
||||
contacts={contactDetails}
|
||||
resourcePath={resourcePath}
|
||||
groupPath={resource['group-path']}
|
||||
amOwner={amOwner}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
data={data}
|
||||
comments={coms}
|
||||
commentPage={commentPage}
|
||||
api={api}
|
||||
<SettingsScreen
|
||||
sidebarShown={sidebarShown}
|
||||
resource={resource}
|
||||
contacts={contacts}
|
||||
contactDetails={contactDetails}
|
||||
groupPath={resource['group-path']}
|
||||
group={group}
|
||||
amOwner={amOwner}
|
||||
resourcePath={resourcePath}
|
||||
popout={popout}
|
||||
api={api}
|
||||
{...props}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
<Route exact path="/~link/(popout)?/:resource/:page?"
|
||||
render={ (props) => {
|
||||
const resourcePath = '/' + props.match.params.resource;
|
||||
const resource = associations.link[resourcePath] || { metadata: {} };
|
||||
|
||||
const amOwner = amOwnerOfGroup(resource['group-path']);
|
||||
|
||||
const contactDetails = contacts[resource['group-path']] || {};
|
||||
|
||||
const page = props.match.params.page || 0;
|
||||
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
|
||||
const channelLinks = links[resourcePath]
|
||||
? links[resourcePath]
|
||||
: { local: {} };
|
||||
|
||||
const channelComments = comments[resourcePath]
|
||||
? comments[resourcePath]
|
||||
: {};
|
||||
|
||||
const channelSeen = seen[resourcePath]
|
||||
? seen[resourcePath]
|
||||
: {};
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
groups={groups}
|
||||
selected={resourcePath}
|
||||
sidebarShown={sidebarShown}
|
||||
sidebarHideMobile={true}
|
||||
popout={popout}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<Links
|
||||
{...props}
|
||||
contacts={contactDetails}
|
||||
links={channelLinks}
|
||||
comments={channelComments}
|
||||
seen={channelSeen}
|
||||
page={page}
|
||||
resourcePath={resourcePath}
|
||||
resource={resource}
|
||||
amOwner={amOwner}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
api={api}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~link/(popout)?/:resource/:page/:index/:encodedUrl/:commentpage?"
|
||||
render={ (props) => {
|
||||
const resourcePath = '/' + props.match.params.resource;
|
||||
const resource = associations.link[resourcePath] || { metadata: {} };
|
||||
|
||||
const amOwner = amOwnerOfGroup(resource['group-path']);
|
||||
|
||||
const popout = props.match.url.includes('/popout/');
|
||||
|
||||
const contactDetails = contacts[resource['group-path']] || {};
|
||||
|
||||
const index = props.match.params.index || 0;
|
||||
const page = props.match.params.page || 0;
|
||||
const url = base64urlDecode(props.match.params.encodedUrl);
|
||||
|
||||
const data = links[resourcePath]
|
||||
? links[resourcePath][page]
|
||||
? links[resourcePath][page][index]
|
||||
: {}
|
||||
: {};
|
||||
const coms = !comments[resourcePath]
|
||||
? undefined
|
||||
: comments[resourcePath][url];
|
||||
|
||||
const commentPage = props.match.params.commentpage || 0;
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
associations={associations}
|
||||
invites={invites}
|
||||
groups={groups}
|
||||
selected={resourcePath}
|
||||
sidebarShown={sidebarShown}
|
||||
sidebarHideMobile={true}
|
||||
popout={popout}
|
||||
links={links}
|
||||
listening={listening}
|
||||
api={api}
|
||||
>
|
||||
<LinkDetail
|
||||
{...props}
|
||||
resource={resource}
|
||||
page={page}
|
||||
url={url}
|
||||
linkIndex={index}
|
||||
contacts={contactDetails}
|
||||
resourcePath={resourcePath}
|
||||
groupPath={resource['group-path']}
|
||||
amOwner={amOwner}
|
||||
popout={popout}
|
||||
sidebarShown={sidebarShown}
|
||||
data={data}
|
||||
comments={coms}
|
||||
commentPage={commentPage}
|
||||
api={api}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import React, { useRef, useEffect } from "react";
|
||||
import { Route, Switch, useLocation, withRouter } from "react-router-dom";
|
||||
import { Center, Text } from "@tlon/indigo-react";
|
||||
import _ from "lodash";
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
import "./css/custom.css";
|
||||
|
||||
@ -61,99 +62,104 @@ export default function PublishApp(props: PublishAppProps) {
|
||||
: "rightPanel";
|
||||
|
||||
return (
|
||||
<Route
|
||||
path={[
|
||||
"/~publish/notebook/:ship/:notebook/note/:noteId",
|
||||
"/~publish/notebook/:ship/:notebook/*",
|
||||
"/~publish/notebook/:ship/:notebook",
|
||||
"/~publish",
|
||||
]}
|
||||
>
|
||||
<RouterSkeleton
|
||||
popout={location.pathname.includes("popout/")}
|
||||
active={active}
|
||||
sidebarShown={sidebarShown}
|
||||
invites={invites}
|
||||
notebooks={notebooks}
|
||||
associations={associations}
|
||||
contacts={contacts}
|
||||
api={api}
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{unreadTotal > 0 ? `(${unreadTotal}) ` : ''}OS1 - Publish</title>
|
||||
</Helmet>
|
||||
<Route
|
||||
path={[
|
||||
"/~publish/notebook/:ship/:notebook/note/:noteId",
|
||||
"/~publish/notebook/:ship/:notebook/*",
|
||||
"/~publish/notebook/:ship/:notebook",
|
||||
"/~publish",
|
||||
]}
|
||||
>
|
||||
<Switch>
|
||||
<Route exact path="/~publish">
|
||||
<Center width="100%" height="100%">
|
||||
<Text color="lightGray">
|
||||
Select or create a notebook to begin.
|
||||
</Text>
|
||||
</Center>
|
||||
</Route>
|
||||
<Route
|
||||
exact
|
||||
path="/~publish/new"
|
||||
render={(props) => {
|
||||
return (
|
||||
<NewScreen
|
||||
associations={associations}
|
||||
api={api}
|
||||
notebooks={notebooks}
|
||||
groups={groups}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~publish/join/:ship/:notebook"
|
||||
render={(props) => {
|
||||
const ship = props.match.params.ship || "";
|
||||
const notebook = props.match.params.notebook || "";
|
||||
return (
|
||||
<JoinScreen
|
||||
notebooks={notebooks}
|
||||
ship={ship}
|
||||
book={notebook}
|
||||
api={api}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
path="/~publish/notebook/:ship/:notebook"
|
||||
render={(props) => {
|
||||
const view = props.match.params.view
|
||||
? props.match.params.view
|
||||
: "posts";
|
||||
|
||||
|
||||
const ship = props.match.params.ship || "";
|
||||
const book = props.match.params.notebook || "";
|
||||
|
||||
const bookGroupPath =
|
||||
notebooks?.[ship]?.[book]?.["subscribers-group-path"];
|
||||
|
||||
const notebookContacts =
|
||||
bookGroupPath in contacts ? contacts[bookGroupPath] : {};
|
||||
|
||||
const notebook = notebooks?.[ship]?.[book];
|
||||
<RouterSkeleton
|
||||
popout={location.pathname.includes("popout/")}
|
||||
active={active}
|
||||
sidebarShown={sidebarShown}
|
||||
invites={invites}
|
||||
notebooks={notebooks}
|
||||
associations={associations}
|
||||
contacts={contacts}
|
||||
api={api}
|
||||
>
|
||||
<Switch>
|
||||
<Route exact path="/~publish">
|
||||
<Center width="100%" height="100%">
|
||||
<Text color="lightGray">
|
||||
Select or create a notebook to begin.
|
||||
</Text>
|
||||
</Center>
|
||||
</Route>
|
||||
<Route
|
||||
exact
|
||||
path="/~publish/new"
|
||||
render={(props) => {
|
||||
return (
|
||||
<NotebookRoutes
|
||||
notebook={notebook}
|
||||
ship={ship}
|
||||
book={book}
|
||||
<NewScreen
|
||||
associations={associations}
|
||||
api={api}
|
||||
notebooks={notebooks}
|
||||
groups={groups}
|
||||
contacts={contacts}
|
||||
notebookContacts={notebookContacts}
|
||||
sidebarShown={sidebarShown}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/~publish/join/:ship/:notebook"
|
||||
render={(props) => {
|
||||
const ship = props.match.params.ship || "";
|
||||
const notebook = props.match.params.notebook || "";
|
||||
return (
|
||||
<JoinScreen
|
||||
notebooks={notebooks}
|
||||
ship={ship}
|
||||
book={notebook}
|
||||
api={api}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
</RouterSkeleton>
|
||||
</Route>
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
path="/~publish/notebook/:ship/:notebook"
|
||||
render={(props) => {
|
||||
const view = props.match.params.view
|
||||
? props.match.params.view
|
||||
: "posts";
|
||||
|
||||
|
||||
const ship = props.match.params.ship || "";
|
||||
const book = props.match.params.notebook || "";
|
||||
|
||||
const bookGroupPath =
|
||||
notebooks?.[ship]?.[book]?.["subscribers-group-path"];
|
||||
|
||||
const notebookContacts =
|
||||
bookGroupPath in contacts ? contacts[bookGroupPath] : {};
|
||||
|
||||
const notebook = notebooks?.[ship]?.[book];
|
||||
return (
|
||||
<NotebookRoutes
|
||||
notebook={notebook}
|
||||
ship={ship}
|
||||
book={book}
|
||||
groups={groups}
|
||||
contacts={contacts}
|
||||
notebookContacts={notebookContacts}
|
||||
sidebarShown={sidebarShown}
|
||||
api={api}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
</RouterSkeleton>
|
||||
</Route>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user