Merge branch 'os1-rc' of https://github.com/urbit/urbit into m/link-meta

This commit is contained in:
Fang 2020-03-03 00:16:41 +01:00
commit a382f7d41b
No known key found for this signature in database
GPG Key ID: EB035760C1BBA972
54 changed files with 527 additions and 270 deletions

View File

@ -202,15 +202,21 @@
?- -.act
%create
?> ?=(^ app-path.act)
?> |(=(group-path.act app-path.act) =(~(tap in members.act) ~))
?^ (chat-scry app-path.act)
~& %chat-already-exists
~
%- zing
:~ (create-chat app-path.act security.act allow-history.act)
(create-managed-group group-path.act security.act members.act)
%- create-group
:* group-path.act
app-path.act
security.act
members.act
title.act
description.act
==
(create-metadata title.act description.act group-path.act app-path.act)
(create-security group-path.act security.act)
~[(permission-hook-poke [%add-owned group-path.act group-path.act])]
==
::
%delete
@ -223,9 +229,7 @@
==
::
?: (is-managed group-path) ~
:~ (permission-hook-poke [%remove group-path])
(permission-poke [%delete group-path])
(group-poke [%unbundle group-path])
:~ (group-poke [%unbundle group-path])
(metadata-hook-poke [%remove group-path])
==
==
@ -247,18 +251,40 @@
(chat-hook-poke [%add-owned path security history])
==
::
++ create-managed-group
|= [=path security=rw-security ships=(set ship)]
++ create-group
|= [=path app-path=path sec=rw-security ships=(set ship) title=@t desc=@t]
^- (list card)
?^ (group-scry path) ~
=/ group (group-scry path)
?^ group
%- zing
%+ turn ~(tap in u.group)
|= =ship
?: =(ship our.bol) ~
[(send-invite app-path ship)]~
:: do not create a managed group if this is a sig path or a blacklist
::
?: =(security %channel)
~[(group-poke [%bundle path])]
?: =(sec %channel)
:~ (group-poke [%bundle path])
(create-security path sec)
(permission-hook-poke [%add-owned path path])
==
?: (is-managed path)
~[(contact-view-poke [%create path ships])]
~[(contact-view-poke [%create path ships title desc])]
:~ (group-poke [%bundle path])
(group-poke [%add ships path])
(create-security path sec)
(permission-hook-poke [%add-owned path path])
==
::
++ create-security
|= [pax=path sec=rw-security]
^- card
?+ sec !!
%channel
(perm-group-hook-poke [%associate pax [[pax %black] ~ ~]])
::
%village
(perm-group-hook-poke [%associate pax [[pax %white] ~ ~]])
==
::
++ create-metadata
@ -278,19 +304,8 @@
(metadata-hook-poke [%add-owned group-path])
==
::
++ create-security
|= [pax=path sec=rw-security]
^- (list card)
?+ sec ~
%channel
~[(perm-group-hook-poke [%associate pax [[pax %black] ~ ~]])]
::
%village
~[(perm-group-hook-poke [%associate pax [[pax %white] ~ ~]])]
==
::
++ contact-view-poke
|= act=[%create =path ships=(set ship)]
|= act=[%create =path ships=(set ship) title=@t description=@t]
^- card
[%pass / %agent [our.bol %contact-view] %poke %contact-view-action !>(act)]
::
@ -308,7 +323,7 @@
!>(act)
==
::
++ send-invite-poke
++ send-invite
|= [=path =ship]
^- card
=/ =invite

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,11 @@
:: contact-hook:
::
/- *group-store, *group-hook, *contact-hook, *invite-store
/- *group-store,
*group-hook,
*contact-hook,
*invite-store,
*metadata-hook,
*metadata-store
/+ *contact-json, default-agent
|%
+$ card card:agent:gall
@ -242,7 +247,10 @@
%delete
=. synced (~(del by synced) path.fact)
:_ state
[(group-poke [%unbundle path.fact])]~
:~ (group-poke [%unbundle path.fact])
(metadata-hook-poke [%remove path.fact])
(metadata-poke [%remove path.fact [%contacts path.fact]])
==
==
::
++ foreign
@ -352,7 +360,9 @@
(poke-hook-action [%add-synced ship.invite.fact path.invite.fact])
:-
%+ welp
[(group-hook-poke [%add ship.invite.fact path.invite.fact])]~
:~ (group-hook-poke [%add ship.invite.fact path.invite.fact])
(metadata-hook-poke [%add-synced ship.invite.fact path.invite.fact])
==
-.changes
+.changes
==
@ -377,6 +387,16 @@
^- card
[%pass / %agent [our.bol %group-store] %poke %group-action !>(act)]
::
++ metadata-poke
|= act=metadata-action
^- card
[%pass / %agent [our.bol %metadata-store] %poke %metadata-action !>(act)]
::
++ metadata-hook-poke
|= act=metadata-hook-action
^- card
[%pass / %agent [our.bol %metadata-hook] %poke %metadata-hook-action !>(act)]
::
++ contacts-scry
|= pax=path
^- (unit contacts)

View File

@ -1,7 +1,14 @@
:: contact-view: sets up contact JS client and combines commands
:: into semantic actions for the UI
::
/- *group-store, *group-hook, *invite-store, *contact-hook
/- *group-store,
*group-hook,
*invite-store,
*contact-hook,
*metadata-store,
*metadata-hook,
*permission-group-hook,
*permission-hook
/+ *server, *contact-json, base64, default-agent
/= index
/^ octs
@ -126,18 +133,24 @@
?- -.act
%create
?> ?=([@ *] path.act)
:~ (group-poke [%bundle path.act])
(contact-poke [%create path.act])
(contact-hook-poke [%add-owned path.act])
(group-hook-poke [%add our.bol path.act])
(group-poke [%add (~(put in ships.act) our.bol) path.act])
==
%+ weld
:~ (group-poke [%bundle path.act])
(contact-poke [%create path.act])
(contact-hook-poke [%add-owned path.act])
(group-hook-poke [%add our.bol path.act])
(group-poke [%add (~(put in ships.act) our.bol) path.act])
(perm-group-hook-poke [%associate path.act [[path.act %white] ~ ~]])
(permission-hook-poke [%add-owned path.act path.act])
==
(create-metadata path.act title.act description.act)
::
%delete
%+ weld
:~ (group-poke [%unbundle path.act])
(contact-poke [%delete path.act])
(contact-hook-poke [%remove path.act])
==
(delete-metadata path.act)
::
%remove
:~ (group-poke [%remove [ship.act ~ ~] path.act])
@ -218,6 +231,51 @@
^- card
[%pass / %agent [our.bol %group-hook] %poke %group-hook-action !>(act)]
::
++ metadata-poke
|= act=metadata-action
^- card
[%pass / %agent [our.bol %metadata-store] %poke %metadata-action !>(act)]
::
++ metadata-hook-poke
|= act=metadata-hook-action
^- card
[%pass / %agent [our.bol %metadata-hook] %poke %metadata-hook-action !>(act)]
::
++ perm-group-hook-poke
|= act=permission-group-hook-action
^- card
:* %pass / %agent [our.bol %permission-group-hook]
%poke %permission-group-hook-action !>(act)
==
::
++ permission-hook-poke
|= act=permission-hook-action
^- card
:* %pass / %agent [our.bol %permission-hook]
%poke %permission-hook-action !>(act)
==
::
++ create-metadata
|= [=path title=@t description=@t]
^- (list card)
=/ =metadata
%* . *metadata
title title
description description
date-created now.bol
creator our.bol
==
:~ (metadata-poke [%add path [%contacts path] metadata])
(metadata-hook-poke [%add-owned path])
==
::
++ delete-metadata
|= =path
^- (list card)
:~ (metadata-poke [%remove path [%contacts path]])
(metadata-hook-poke [%remove path])
==
::
++ all-scry
^- rolodex
.^(rolodex %gx /=contact-store/(scot %da now.bol)/all/noun)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -196,7 +196,7 @@
=/ book=notebook-info
[title.old '' =(%open comments.old) / /]
=+ ^- [grp-car=(list card) write-pax=path read-pax=path]
(make-groups:main book-name group-pax ~ %.n %.n)
(make-groups:main book-name [group-pax ~ %.n %.n] '' '')
=. writers.book write-pax
=. subscribers.book read-pax
=/ inv-car (send-invites book-name (~(get ju old-subs) book-name))
@ -563,7 +563,7 @@
=+ ^- [grp-car=(list card) write-pax=path read-pax=path]
?: =(writers.new-book /)
=/ group-path /~/publish/(scot %p our.bol)/[book-name]
(make-groups book-name group-path ~ %.n %.n)
(make-groups book-name [group-path ~ %.n %.n] '' '')
[~ writers.info subscribers.info]
=. writers.new-book write-pax
=. subscribers.new-book read-pax
@ -876,7 +876,8 @@
[%pass / %agent [our.bol %group-hook] %poke %group-hook-action !>(act)]
::
++ contact-view-create
|= act=[%create path (set ship)]
|= [=path ships=(set ship) title=@t description=@t]
=/ act [%create path ships title description]
^- card
[%pass / %agent [our.bol %contact-view] %poke %contact-view-action !>(act)]
::
@ -923,18 +924,6 @@
(perm-group-hook-poke [%associate write [[write write-type] ~ ~]])
==
::
++ create-managed-group
|= [pax=path security=rw-security ships=(set ship)]
^- (list card)
=/ grp
.^((unit group) %gx ;:(weld /=group-store/(scot %da now.bol) pax /noun))
?^ grp
~
?> ?=(^ pax)
?: |(=('~' i.pax) !=(%village security))
[(group-poke [%bundle pax])]~
[(contact-view-create [%create pax ships])]~
::
++ generate-invites
|= [book=@tas invitees=(set ship)]
^- (list card)
@ -949,7 +938,7 @@
[%pass / %agent [our.bol %invite-hook] %poke %invite-action !>(act)]
::
++ make-groups
|= [book=@tas group=group-info]
|= [book=@tas group=group-info title=@t about=@t]
^- [(list card) write=path read=path]
?> ?=(^ group-path.group)
?: use-preexisting.group
@ -976,7 +965,7 @@
=/ whole-grp (~(put in invitees.group) our.bol)
:_ [group-path.group group-path.group]
%- zing
:~ [(contact-view-create [%create group-path.group whole-grp])]~
:~ [(contact-view-create [group-path.group whole-grp title about])]~
(create-security group-path.group group-path.group %village)
[(perm-hook-poke [%add-owned group-path.group group-path.group])]~
(generate-invites book (~(del in invitees.group) our.bol))
@ -1013,7 +1002,7 @@
?: (~(has by books) book.act)
~|("notebook already exists: {<book.act>}" !!)
=+ ^- [cards=(list card) write-pax=path read-pax=path]
(make-groups book.act group.act)
(make-groups book.act group.act title.act about.act)
=/ new-book=notebook-info
:* title.act
about.act
@ -1086,7 +1075,7 @@
=+ ^- [cards=(list card) write-pax=path read-pax=path]
?~ group.act
[~ writers.u.book subscribers.u.book]
(make-groups book.act u.group.act)
(make-groups book.act u.group.act title.act about.act)
=/ new-info=notebook-info
:* title.act
about.act

View File

@ -109,6 +109,8 @@
%- ot
:~ [%path pa]
[%ships (as (su ;~(pfix sig fed:ag)))]
[%title so]
[%description so]
==
::
++ delete (ot [%path pa]~)

View File

@ -3,7 +3,7 @@
+$ contact-view-action
$% :: %create: create in both groups and contacts
::
[%create =path ships=(set ship)]
[%create =path ships=(set ship) title=@t description=@t]
:: %remove: remove from both groups and contacts
::
[%remove =path =ship]

View File

@ -276,7 +276,7 @@ h2 {
a {
color: #fff;
}
.hover-black-d:hover {
color: #000;
.hover-bg-gray1-d:hover {
color: #4d4d4d;
}
}

View File

@ -78,11 +78,11 @@ class UrbitApi {
}
groupsAction(data) {
this.action("group-store", "group-action", data);
return this.action("group-store", "group-action", data);
}
groupAdd(members, path) {
this.groupsAction({
return this.groupsAction({
add: {
members, path
}
@ -152,7 +152,7 @@ class UrbitApi {
chatViewJoin(ship, path, askHistory) {
this.chatViewAction({
join: {
ship,
ship,
'app-path': path,
'ask-history': askHistory
}

View File

@ -33,6 +33,7 @@ export class ChatScreen extends Component {
componentDidMount() {
this.updateReadNumber();
this.scrollToBottom("auto");
}
componentWillUnmount() {

View File

@ -1,40 +1,25 @@
import React, { Component } from 'react';
import classnames from 'classnames';
import { Sigil } from '/components/lib/icons/sigil';
import { deSig } from '/lib/util';
import urbitOb from 'urbit-ob';
import { InviteSearch } from './invite-search';
export class InviteElement extends Component {
constructor(props) {
super(props);
this.state = {
members: '',
members: [],
error: false,
success: false
};
this.setInvite = this.setInvite.bind(this);
}
modifyMembers() {
const { props, state } = this;
let aud = [];
let isValid = true;
if (state.members.length > 2) {
aud = state.members
.split(',')
.map((mem) => `~${deSig(mem.trim())}`);
let aud = state.members.map(mem => `~${mem}`);
aud.forEach((mem) => {
if (!urbitOb.isValidPatp(mem)) {
isValid = false;
}
});
}
if (!isValid || (state.members.length > 0 && state.members.length < 3)) {
if (state.members.length === 0) {
this.setState({
error: true,
success: false
@ -42,40 +27,27 @@ export class InviteElement extends Component {
return;
}
if (this.textarea) {
this.textarea.value = '';
}
props.api.setSpinner(true);
this.setState({
error: false,
success: true,
members: ''
members: []
}, () => {
props.api.groups.add(aud, props.path);
props.api.groups.add(aud, props.path).then(() => {
props.api.setSpinner(false);
});
});
}
modifyMembersChange(e) {
this.setState({
members: e.target.value
});
setInvite(invite) {
this.setState({members: invite.ships});
}
render() {
const { props, state} = this;
let errorElem = !!state.error ? (
<p className="pt2 red2 f8">Invalid ship name.</p>
) : (
<div></div>
);
const { props, state } = this;
let successElem = !!state.success ? (
<p className="pt2 green2 f8">Success!</p>
) : (
<div></div>
);
let modifyButtonClasses = "db f9 ba pa2 white-d bg-gray0-d b--black b--gray2-d pointer";
let modifyButtonClasses = "mt4 db f9 ba pa2 white-d bg-gray0-d b--black b--gray2-d pointer";
if (state.error) {
modifyButtonClasses = modifyButtonClasses + ' gray3';
}
@ -89,23 +61,21 @@ export class InviteElement extends Component {
return (
<div>
<textarea
ref={ e => { this.textarea = e; } }
className="f7 mono ba b--gray3 bg-gray0-d white-d pa3 mb4 db w-100"
style={{
resize: 'none',
height: 50
}}
spellCheck="false"
placeholder="~zod, ~bus"
onChange={this.modifyMembersChange.bind(this)}></textarea>
<InviteSearch
groups={{}}
contacts={props.contacts}
groupResults={false}
invites={{
groups: [],
ships: this.state.members
}}
setInvite={this.setInvite}
/>
<button
onClick={this.modifyMembers.bind(this)}
className={modifyButtonClasses}>
{buttonText}
</button>
{errorElem}
{successElem}
</div>
);
}

View File

@ -222,8 +222,8 @@ export class InviteSearch extends Component {
<li
key={group}
className={
"list mono white-d f8 pv2 ph3 pointer" +
" hover-bg-gray4 hover-black-d"
"list mono mix-blend-diff white f8 pv2 ph3 pointer" +
" hover-bg-gray4 hover-bg-gray1-d"
}
onClick={e => this.addGroup(group)}>
{group}
@ -233,14 +233,16 @@ export class InviteSearch extends Component {
let shipResults = state.searchResults.ships.map(ship => {
let nicknames = (this.state.contacts.has(ship))
? this.state.contacts.get(ship).join(", ")
? this.state.contacts.get(ship)
.filter(e => { return !(e === "") })
.join(", ")
: "";
return (
<li
key={ship}
className={
"list mono white-d f8 pv1 ph3 pointer" +
" hover-bg-gray4 hover-black-d relative"
" hover-bg-gray4 hover-bg-gray1-d relative"
}
onClick={e => this.addShip(ship)}>
<Sigil
@ -249,8 +251,8 @@ export class InviteSearch extends Component {
color="#000000"
classes="mix-blend-diff v-mid"
/>
<span className="v-mid ml2 mw5 truncate dib">{"~" + ship}</span>
<span className="absolute right-1 di truncate mw4 inter f9 pt1">{nicknames}</span>
<span className="v-mid ml2 mw5 truncate dib mix-blend-diff white">{"~" + ship}</span>
<span className="absolute right-1 di truncate mw4 inter f9 pt1 mix-blend-diff white">{nicknames}</span>
</li>
);
});

View File

@ -42,6 +42,8 @@ export class SidebarItem extends Component {
return lett.url;
} else if ('code' in lett) {
return lett.code.expression;
} else if ('me' in lett) {
return lett.me;
} else {
return '';
}
@ -51,35 +53,41 @@ export class SidebarItem extends Component {
const { props, state } = this;
let unreadElem = !!props.unread
? "fw7 green2"
? "green2"
: "";
let title = props.title.substr(1);
let title = props.title;
let description = this.getLetter(props.description);
let box = props.box.substr(1);
let latest = this.getLetter(props.latest);
let selectedCss = !!props.selected ? 'bg-gray5 bg-gray1-d gray3-d' : 'bg-white bg-gray0-d gray3-d pointer';
let authorCss = (props.nickname === props.ship)
? "mono" : "";
let author = (props.nickname === props.ship)
? `~${props.ship}` : props.nickname;
return (
<div
className={"z1 pa3 pt4 pb4 bb b--gray4 b--gray1-d " + selectedCss}
className={"z1 pa3 pt2 pb2 bb b--gray4 b--gray1-d " + selectedCss}
onClick={this.onClick.bind(this)}>
<div className="w-100 v-mid">
<p className={"dib mono f8 " + unreadElem }>
<span className={(unreadElem === "") ? "gray3 gray2-d" : ""}>
{title.substr(0, title.indexOf("/"))}/
</span>
{title.substr(title.indexOf("/") + 1)}
<p className="dib f8">
{title}
</p>
<p className="f8 db mono gray3 gray2-d pt1">{box}</p>
</div>
<div className="w-100 pt1">
<p className="dib mono f9 mr3">
{props.ship === "" ? "" : "~"}
{props.ship}
<div className="w-100 pt3">
<p className={((unreadElem === "") ? "black white-d" : "") +
unreadElem + " dib f9 mr3 mw4 truncate v-mid " + authorCss}>
{(author === "~") ? "" : author}
</p>
<p className="dib mono f9 gray3">{state.timeSinceNewestMessage}</p>
<p className="dib mono f9 gray3 v-mid">{state.timeSinceNewestMessage}</p>
</div>
<p className="f8 clamp-3 pt2">{description}</p>
<p className="f8 clamp-3 pt1">{latest}</p>
</div>
);
}

View File

@ -29,9 +29,12 @@ export class MemberScreen extends Component {
modifyText = 'Invite someone to this chat.';
}
let contacts = (props.station in props.contacts)
? props.contacts[props.station] : {};
let members = perm.map((mem) => {
let contact = (mem in props.contacts)
? props.contacts[mem] : false;
let contact = (mem in contacts)
? contacts[mem] : false;
return (
<MemberElement
@ -55,7 +58,7 @@ export class MemberScreen extends Component {
<Link to="/~chat/">{"⟵ All Chats"}</Link>
</div>
<div
className={`pl4 pt2 bb b--gray4 b--gray1-d bg-gray0-d flex relative
className={`pl4 pt2 bb b--gray4 b--gray1-d bg-gray0-d flex relative
overflow-x-scroll overflow-x-auto-l overflow-x-auto-xl flex-shrink-0`}
style={{ height: 48 }}>
<SidebarSwitcher
@ -91,6 +94,7 @@ export class MemberScreen extends Component {
<InviteElement
path={props.station}
permissions={props.permission}
contacts={props.contacts}
api={props.api}
/>
) : null}

View File

@ -46,13 +46,16 @@ export class Root extends Component {
let contacts = !!state.contacts ? state.contacts : {};
const renderChannelSidebar = (props) => (
const renderChannelSidebar = (props, station) => (
<Sidebar
inbox={state.inbox}
messagePreviews={messagePreviews}
associations={state.associations || new Map}
contacts={contacts}
invites={invites}
unreads={unreads}
api={api}
station={station}
{...props}
/>
);
@ -161,7 +164,7 @@ export class Root extends Component {
spinner={state.spinner}
popout={popout}
sidebarShown={state.sidebarShown}
sidebar={renderChannelSidebar(props)}
sidebar={renderChannelSidebar(props, station)}
>
<ChatScreen
station={station}
@ -200,8 +203,6 @@ export class Root extends Component {
};
let popout = props.match.url.includes("/popout/");
let roomContacts = (station in contacts)
? contacts[station] : {};
return (
<Skeleton
@ -216,7 +217,7 @@ export class Root extends Component {
api={api}
station={station}
permission={permission}
contacts={roomContacts}
contacts={contacts}
permissions={state.permissions}
popout={popout}
sidebarShown={state.sidebarShown}

View File

@ -19,7 +19,6 @@ export class Sidebar extends Component {
render() {
const { props, state } = this;
let station = `/${props.match.params.ship}/${props.match.params.station}`;
let sidebarInvites = Object.keys(props.invites)
.map((uid) => {
@ -39,14 +38,28 @@ export class Sidebar extends Component {
: {text: 'No messages yet'};
let author = !!msg ? msg.author : '';
let when = !!msg ? msg.when : 0;
let title = box;
if ((props.associations.has(box)) && (props.associations.get(box).metadata)) {
title = (props.associations.get(box).metadata.title)
? props.associations.get(box).metadata.title : box;
}
let nickname = author;
if ((props.contacts[box]) && (author in props.contacts[box])) {
nickname = (props.contacts[box][author].nickname)
? props.contacts[box][author].nickname : author;
}
return {
msg,
when,
author,
nickname,
letter,
box,
title: box,
selected: station === box
title: title,
selected: props.station === box
};
})
.sort((a, b) => {
@ -58,10 +71,11 @@ export class Sidebar extends Component {
<SidebarItem
key={obj.box + '/' + obj.when}
title={obj.title}
description={obj.letter}
latest={obj.letter}
box={obj.box}
when={obj.when}
ship={obj.author}
nickname={obj.nickname}
selected={obj.selected}
unread={unread}
history={props.history}

View File

@ -0,0 +1,32 @@
import _ from 'lodash';
export class MetadataReducer {
reduce(json, state) {
let data = _.get(json, 'metadata-update', false);
if (data) {
this.associations(data, state);
this.add(data, state);
}
}
associations(json, state) {
let data = _.get(json, 'associations', false);
if (data) {
let metadata = new Map;
Object.keys(data).map((channel) => {
let channelObj = data[channel];
metadata.set(channelObj["app-path"], channelObj);
})
state.associations = metadata;
}
}
add(json, state) {
let data = _.get(json, 'add', false);
if (data) {
let metadata = state.associations;
metadata.set(data["app-path"], data);
state.associations = metadata;
}
}
}

View File

@ -4,6 +4,7 @@ import { ContactUpdateReducer } from '/reducers/contact-update';
import { ChatUpdateReducer } from '/reducers/chat-update';
import { InviteUpdateReducer } from '/reducers/invite-update';
import { PermissionUpdateReducer } from '/reducers/permission-update';
import { MetadataReducer } from '/reducers/metadata-update.js';
import { LocalReducer } from '/reducers/local.js';
@ -15,6 +16,7 @@ class Store {
contacts: {},
permissions: {},
invites: {},
associations: new Map,
spinner: false,
sidebarShown: true,
pendingMessages: new Map([]),
@ -27,6 +29,7 @@ class Store {
this.contactUpdateReducer = new ContactUpdateReducer();
this.chatUpdateReducer = new ChatUpdateReducer();
this.inviteUpdateReducer = new InviteUpdateReducer();
this.metadataReducer = new MetadataReducer();
this.localReducer = new LocalReducer();
this.setState = () => {};
}
@ -45,6 +48,7 @@ class Store {
this.contactUpdateReducer.reduce(json, this.state);
this.chatUpdateReducer.reduce(json, this.state);
this.inviteUpdateReducer.reduce(json, this.state);
this.metadataReducer.reduce(json, this.state);
this.localReducer.reduce(json, this.state);
this.setState(this.state);

View File

@ -113,9 +113,56 @@ a {
}
}
/* dark */
/* @media all and (prefers-color-scheme: dark) {
@media all and (prefers-color-scheme: dark) {
body {
background-color: #333;
}
.bg-black-d {
background-color: black;
}
.white-d {
color: white;
}
.gray1-d {
color: #4d4d4d;
}
.gray2-d {
color: #7f7f7f;
}
.gray3-d {
color: #b1b2b3;
}
.gray4-d {
color: #e6e6e6;
}
.bg-gray0-d {
background-color: #333;
}
.bg-gray1-d {
background-color: #4d4d4d;
}
.b--gray0-d {
border-color: #333;
}
.b--gray2-d {
border-color: #7f7f7f;
}
.b--white-d {
border-color: #fff;
}
.invert-d {
filter: invert(1);
}
} */
.o-60-d {
opacity: .6;
}
a {
color: #fff;
}
.focus-b--white-d:focus {
border-color: #fff;
}
.hover-bg-gray1-d:hover {
color: #4d4d4d;
}
}

View File

@ -69,7 +69,14 @@ class UrbitApi {
}
contactCreate(path, ships = []) {
return this.contactViewAction({ create: { path, ships }});
return this.contactViewAction({
create: {
path,
ships,
title: '',
description: ''
}
});
}
groupAdd(path, ships = []) {

View File

@ -313,7 +313,8 @@ export class ContactCard extends Component {
style={{ width: "fit-content" }}>
<p className="f9 gray2 lh-copy">Sigil Color</p>
<textarea
className="b--gray4 black f7 ba db pl2 focus-b--black"
className={"b--gray4 b--gray2-d black white-d bg-gray0-d f7 ba db pl2 " +
"focus-b--black focus-b--white-d"}
onChange={this.sigilColorSet}
defaultValue={defaultColor}
key={"default" + defaultColor}
@ -499,7 +500,8 @@ export class ContactCard extends Component {
//TODO "Share card" if it's /me -> sends to /~/default of recipient
return (
<div className="w-100 h-100 overflow-hidden">
<div className="flex justify-between w-100 bg-white bb b--gray4 ">
<div className={"flex justify-between w-100 bg-white bg-gray0-d " +
"bb b--gray4 b--gray2-d "}>
<div className="w-100 h2 dn-m dn-l dn-xl inter pb6 pl3 pt3 f8">
<Link to="/~contacts/">{"⟵"}</Link>
</div>
@ -512,16 +514,16 @@ export class ContactCard extends Component {
this.editToggle();
}
}}
className={`ml3 mt2 mb2 f9 pa1 pointer` + ourOpt}>
className={`white-d bg-gray0-d ml3 mt2 mb2 f9 pa1 pointer ` + ourOpt}>
{editInfoText}
</button>
<button className={`ml3 mt2 mb2 f9 pa1 pointer` + localOpt}>
<button className={`white-d bg-gray0-d ml3 mt2 mb2 f9 pa1 pointer ` + localOpt}>
Share
</button>
</div>
<button
className={
`pr4 mt4 mb4 f9 red2 pointer ` + adminOpt
`bg-gray0-d pr4 mt4 mb4 f9 red2 pointer ` + adminOpt
}
onClick={this.removeFromGroup}>
{(
@ -530,7 +532,7 @@ export class ContactCard extends Component {
)}
</button>
</div>
<div className="h-100 w-100 overflow-x-hidden pb8">{card}</div>
<div className="h-100 w-100 overflow-x-hidden pb8 white-d">{card}</div>
</div>
);
}

View File

@ -8,7 +8,7 @@ export class ContactItem extends Component {
render() {
const { props } = this;
let selectedClass = (props.selected) ? "bg-gray4" : "";
let selectedClass = (props.selected) ? "bg-gray4 bg-gray1-d" : "";
let hexColor = uxToHex(props.color);
let name = (props.nickname) ? props.nickname : "~" + props.ship;

View File

@ -51,7 +51,8 @@ export class ContactSidebar extends Component {
return (
<div
key={member}
className="pl4 pt1 pb1 f9 flex justify-start content-center bg-white">
className={"pl4 pt1 pb1 f9 flex justify-start content-center " +
"bg-white bg-gray0-d"}>
<Sigil
ship={member}
color="#000000"
@ -81,7 +82,7 @@ export class ContactSidebar extends Component {
className={((props.path.includes(window.ship))
? "dib"
: "dn")}>
<p className="f9 pl4 pt0 pt4-m pt4-l pt4-xl gray2 bn">Invite</p>
<p className="f9 pl4 pt0 pt4-m pt4-l pt4-xl green2 bn">Add to Group</p>
</Link>
<Link to={detailHref}
className="dib dn-m dn-l dn-xl f9 pl4 pt0 pt4-m pt4-l pt4-xl gray2 bn">Channels</Link>

View File

@ -29,7 +29,8 @@ export class EditElement extends Component {
<div className="w-100 flex">
<textarea
ref={props.title}
className="w-100 ba pl3 b--gray4 focus-b--black"
className={"w-100 ba pl3 white-d bg-gray0-d b--gray4 b--gray2-d " +
"focus-b--black focus-b--white-d"}
style={ inputStyles }
onChange={(e) => {
let val = (' ' + e.target.value).slice(1);
@ -43,7 +44,7 @@ export class EditElement extends Component {
{!!props.showButtons ? (
<button
className={
"f9 pointer ml3 ba pa2 pl3 pr3 b--red2 red2 " +
"bg-gray0-d f9 pointer ml3 ba pa2 pl3 pr3 b--red2 red2 " +
(showDelete ? "dn" : "dib")
}
onClick={() => {
@ -57,8 +58,8 @@ export class EditElement extends Component {
{!!props.showButtons ? (
<button
className={
"pointer db mv2 f9 ba pa2 pl3 pr3 " +
(allowSave ? "b--black" : "b--gray4 gray4")
"bg-gray0-d white-d pointer db mv2 f9 ba pa2 pl3 pr3 " +
(allowSave ? "b--black b--white-d" : "b--gray4 gray4 b--gray2-d gray2-d")
}
onClick={() => {
if (!allowSave) { return; }

View File

@ -10,36 +10,34 @@ export class GroupDetail extends Component {
props.activeDrawer === "detail" ? "db" : "dn db-ns";
let groupPath = props.path || "";
let channelsForGroup = (groupPath in props.associations) ?
props.associations[groupPath] : {};
let groupChannels = props.associations.get(groupPath) || {};
let isEmpty = Object.keys(channelsForGroup).length === 0;
let channelList = (<div />);
let isEmpty = Object.entries(groupChannels).length === 0 &&
groupChannels.constructor === Object;
let channelList = <div/>
channelList = Object.keys(groupChannels).map((channel) => {
let channelObj = groupChannels[channel];
if (!channelObj) {
return false;
channelList = Object.keys(channelsForGroup).map((key) => {
let channel = channelsForGroup[key];
if (!('metadata' in channel)) {
return (<div />);
}
let title = channelObj.metadata.title || channelObj["app-path"] || "";
let color = uxToHex(channelObj.metadata.color) || "000000";
let app = channelObj["app-name"] || "Unknown";
let channelPath = channelObj["app-path"];
let title = channel.metadata.title || channel["app-path"] || "";
let color = uxToHex(channel.metadata.color) || "000000";
let app = channel["app-name"] || "Unknown";
let channelPath = channel["app-path"];
let link = `/~${app}/join${channelPath}`
app = app.charAt(0).toUpperCase() + app.slice(1)
return(
<li
key={channel}
className="f9 list flex pv2 w-100">
<li key={channel} className="f9 list flex pv2 w-100">
<div className="dib"
style={{backgroundColor: `#${color}`, height: 32, width: 32}}
></div>
<div className="flex flex-column flex-auto">
<p className="f9 inter ml2 w-100">{title}</p>
<p className="f9 inter ml2 w-100"
style={{marginTop: "0.35rem"}}>
style={{marginTop: "0.35rem"}}>
<span className="f9 di mr2 inter">{app}</span>
<a className="f9 di green2" href={link}>Open</a>
</p>
@ -51,12 +49,16 @@ export class GroupDetail extends Component {
let backLink = props.location.pathname;
backLink = backLink.slice(0, props.location.pathname.indexOf("/detail"));
let emptyGroup = <div className={isEmpty ? "dt w-100 h-100" : "dn"}>
<p className="gray2 f9 tc v-mid dtc">This group has no channels. To add a channel, invite this group using any application.</p>
</div>
let emptyGroup = (
<div className={isEmpty ? "dt w-100 h-100" : "dn"}>
<p className="gray2 f9 tc v-mid dtc">
This group has no channels. To add a channel, invite this group using any application.
</p>
</div>
);
return (
<div className={"h-100 w-100 overflow-x-hidden bg-white pa4 "
<div className={"h-100 w-100 overflow-x-hidden bg-white bg-gray0-d white-d pa4 "
+ responsiveClass}>
<div className="pb5 f8 db dn-m dn-l dn-xl">
<Link to={backLink}> Contacts</Link>

View File

@ -1,12 +1,12 @@
import React, { Component } from 'react'
import { Route, Link } from 'react-router-dom';
import { Route, Link } from 'react-router-dom';
export class GroupItem extends Component {
render() {
const { props } = this;
let selectedClass = (props.selected) ? "bg-gray4" : "";
let selectedClass = (props.selected) ? "bg-gray4 bg-gray1-d" : "";
let memberCount = Math.max(
props.group.size,
Object.keys(props.contacts).length

View File

@ -12,7 +12,7 @@ export class GroupSidebar extends Component {
render() {
const { props, state } = this;
let selectedClass = (props.selected === "me") ? "bg-gray4" : "bg-white";
let selectedClass = (props.selected === "me") ? "bg-gray4 bg-gray1-d" : "bg-white bg-gray0-d";
let rootIdentity = <Link
key={1}
@ -78,9 +78,9 @@ export class GroupSidebar extends Component {
let activeClasses = (this.props.activeDrawer === "groups") ? "" : "dn-s";
return (
<div className={`bn br-m br-l br-xl b--gray3 lh-copy h-100 flex-basis-100-s
flex-basis-30-ns flex-shrink-0 mw5-m mw5-l mw5-xl pt3 pt0-m pt0-l pt0-xl
relative overflow-hidden ` + activeClasses}>
<div className={"bn br-m br-l br-xl b--gray2 lh-copy h-100 flex-basis-100-s " +
"flex-basis-30-ns flex-shrink-0 mw5-m mw5-l mw5-xl pt3 pt0-m pt0-l pt0-xl " +
"relative overflow-hidden " + activeClasses}>
{/*TODO Add invite items */}
<a className="db dn-m dn-l dn-xl f8 pb6 pl3" href="/"> Landscape</a>
<div className="overflow-auto pb8 h-100">

View File

@ -222,8 +222,8 @@ export class InviteSearch extends Component {
<li
key={group}
className={
"list mono white-d f8 pv2 ph3 pointer" +
" hover-bg-gray4 hover-black-d"
"list mono mix-blend-diff white f8 pv2 ph3 pointer" +
" hover-bg-gray4 hover-bg-gray1-d"
}
onClick={e => this.addGroup(group)}>
{group}
@ -233,14 +233,16 @@ export class InviteSearch extends Component {
let shipResults = state.searchResults.ships.map(ship => {
let nicknames = (this.state.contacts.has(ship))
? this.state.contacts.get(ship).join(", ")
? this.state.contacts.get(ship)
.filter(e => {return !(e === "")})
.join(", ")
: "";
return (
<li
key={ship}
className={
"list mono white-d f8 pv1 ph3 pointer" +
" hover-bg-gray4 hover-black-d relative"
" hover-bg-gray4 hover-bg-gray1-d relative"
}
onClick={e => this.addShip(ship)}>
<Sigil
@ -249,8 +251,8 @@ export class InviteSearch extends Component {
color="#000000"
classes="mix-blend-diff v-mid"
/>
<span className="v-mid ml2 mw5 truncate dib">{"~" + ship}</span>
<span className="absolute right-1 di truncate mw4 inter f9 pt1">{nicknames}</span>
<span className="v-mid ml2 mw5 truncate dib mix-blend-diff white">{"~" + ship}</span>
<span className="absolute right-1 di truncate mw4 inter f9 pt1 mix-blend-diff white">{nicknames}</span>
</li>
);
});

View File

@ -13,7 +13,7 @@ export class ShareSheet extends Component {
return (
<div>
<p className="pt4 pb2 pl4 pr4 f8 gray2 f9">Share Your Profile</p>
<p className="pt4 pb2 pl4 pr4 f8 gray2 f9">Group Identity</p>
<ContactItem
key={props.ship}
ship={props.ship}
@ -22,11 +22,11 @@ export class ShareSheet extends Component {
path={props.path}
selected={props.selected}
share={true} />
<p className="pt2 pb3 pl4 pr4 f9">
<p className="pt2 pb3 pl4 pr4 f9 white-d">
Your personal information is hidden to others in this group
by default.
</p>
<p className="pl4 pr4 f9">
<p className="pl4 pr4 f9 white-d">
Share whenever you are ready, or edit its contents for this group.
</p>
</div>

View File

@ -91,7 +91,7 @@ export class NewScreen extends Component {
}
return (
<div className="h-100 w-100 flex flex-column overflow-y-scroll">
<div className="h-100 w-100 flex flex-column overflow-y-scroll white-d">
<div className="w-100 dn-m dn-l dn-xl inter pt1 pb6 pl3 pt3 f8">
<Link to="/~contacts/">{"⟵ All Groups"}</Link>
</div>
@ -102,7 +102,8 @@ export class NewScreen extends Component {
Alphanumeric characters and hyphens only
</p>
<textarea
className="f7 ba b--gray3 w-100 pa3 ml3 mt2 focus-b--black"
className={"f7 bg-gray0-d white-d ba b--gray3 w-100 pa3 ml3 mt2 " +
"focus-b--black focus-b--white-d"}
rows={1}
placeholder="example-group-name"
style={{

View File

@ -34,7 +34,7 @@ export class Root extends Component {
let invites =
(!!state.invites && '/contacts' in state.invites) ?
state.invites['/contacts'] : {};
let associations = !! state.associations ? state.associations : new Map;
let associations = !! state.associations ? state.associations : {};
return (
<BrowserRouter>

View File

@ -12,17 +12,15 @@ export class MetadataReducer {
associations(json, state) {
let data = _.get(json, 'associations', false);
if (data) {
let metadata = new Map;
Object.keys(data).map((channel) => {
let channelObj = data[channel];
if (metadata.has(channelObj["group-path"])) {
let groupMetadata = metadata.get(channelObj["group-path"]);
groupMetadata[channel] = channelObj;
metadata.set(channelObj["group-path"], groupMetadata);
} else {
metadata.set(channelObj["group-path"], {[channel]: channelObj});
let metadata = {};
Object.keys(data).forEach((key) => {
let val = data[key];
let groupPath = val['group-path'];
if (!(groupPath in metadata)) {
metadata[groupPath] = {};
}
})
metadata[groupPath][key] = val;
});
state.associations = metadata;
}
}
@ -31,13 +29,13 @@ export class MetadataReducer {
let data = _.get(json, 'add', false);
if (data) {
let metadata = state.associations;
if (metadata.has(data["group-path"])) {
let groupMetadata = metadata.get(data["group-path"]);
groupMetadata[`${data["group-path"]}/${data["app-name"]}${data["app-path"]}`] = data;
} else {
metadata.set(data["group-path"], data);
if (!(data['group-path'] in metadata)) {
metadata[data['group-path']] = {};
}
metadata[data['group-path']]
[`${data["group-path"]}/${data["app-name"]}${data["app-path"]}`] = data;
state.associations = metadata;
}
}
}
}

View File

@ -12,7 +12,7 @@ class Store {
this.state = {
contacts: {},
groups: {},
associations: new Map,
associations: {},
permissions: {},
invites: {},
spinner: false

View File

@ -143,7 +143,7 @@ a {
font-family: 'Source Code Pro';
}
.CodeMirror-selected { background:#BAE3FE !important; }
.CodeMirror-selected { background:#BAE3FE !important; color: black; }
.cm-s-tlon span { font-family: "Source Code Pro"}
.cm-s-tlon span.cm-meta { color: var(--gray); }
@ -192,6 +192,14 @@ a {
color: #7F7F7F;
}
.options.open {
background-color: #e6e6e6;
}
.options.closed {
background-color: white;
}
.options::after {
content: "⌃";
transform: rotate(180deg);
@ -276,4 +284,68 @@ md img {
.mix-blend-diff {
mix-blend-mode: difference;
}
@media all and (prefers-color-scheme: dark) {
body {
background-color: #333;
}
.bg-black-d {
background-color: black;
}
.white-d {
color: white;
}
.gray1-d {
color: #4d4d4d;
}
.gray2-d {
color: #7f7f7f;
}
.gray3-d {
color: #b1b2b3;
}
.gray4-d {
color: #e6e6e6;
}
.bg-gray0-d {
background-color: #333;
}
.bg-gray1-d {
background-color: #4d4d4d;
}
.b--gray0-d {
border-color: #333;
}
.b--gray2-d {
border-color: #7f7f7f;
}
.b--white-d {
border-color: #fff;
}
.invert-d {
filter: invert(1);
}
.o-60-d {
opacity: .6;
}
a {
color: #fff;
}
.focus-b--white-d:focus {
border-color: #fff;
}
.hover-bg-gray1-d:hover {
background-color: #4d4d4d;
}
.options.open {
background-color: #4d4d4d;
}
.options.closed {
background-color: #333;
}
.cm-s-tlon.CodeMirror {
background: #333;
color: #fff;
}
}

View File

@ -53,7 +53,7 @@ export class CommentItem extends Component {
return (
<div>
<div className="flex mv3 bg-white">
<div className="flex mv3 bg-white bg-gray0-d">
<Sigil
ship={commentData.author}
size={24}

View File

@ -53,8 +53,8 @@ export class Comments extends Component {
let disableComment = ((this.state.commentBody === '') || (this.state.disabled === true));
let commentClass = (disableComment)
? "f9 pa2 bg-white br1 ba b--gray2 gray2"
: "f9 pa2 bg-white br1 ba b--gray2 black pointer";
? "bg-transparent f9 pa2 br1 ba b--gray2 gray2"
: "bg-transparent f9 pa2 br1 ba b--gray2 black white-d pointer";
return (
<div>
@ -66,7 +66,7 @@ export class Comments extends Component {
name="comment"
placeholder="Leave a comment here"
className={"f9 db border-box w-100 ba b--gray3 pt3 ph3 pb8 br1 " +
"mb2 focus-b--black"}
"b--gray2-d mb2 focus-b--black focus-b--white-d white-d bg-gray0-d"}
aria-describedby="comment-desc"
onChange={this.commentChange}>
</textarea>

View File

@ -43,8 +43,8 @@ export class Dropdown extends Component {
let display = (this.state.open)
? "block" : "none";
let optionsColor = (this.state.open)
? '#e6e6e6' : 'white';
let optionsClass = (this.state.open)
? "open" : "closed";
let leftAlign = "";
let rightAlign = "0";
@ -64,14 +64,13 @@ export class Dropdown extends Component {
});
return (
<div className="options relative dib"
<div className={"options relative dib " + optionsClass}
ref={(el) => {this.optsButton = el}}>
<button className="pr3 mb1 pointer br2 pa2 pr4"
style={{backgroundColor: optionsColor}}
<button className="bg-transparent white-d pr3 mb1 pointer br2 pa2 pr4"
onClick={this.toggleDropdown}>
{this.props.buttonText}
</button>
<div className="absolute flex flex-column pv2 ba b--gray4 br2 z-1 bg-white"
<div className="absolute flex flex-column pv2 ba b--gray4 br2 z-1 bg-white bg-gray0-d"
ref={(el) => {this.optsList = el}}
style={{left: leftAlign, right: rightAlign, width:this.props.width, display: display}}>
{optionsList}

View File

@ -26,14 +26,14 @@ export class HeaderBar extends Component {
}
return (
<div className={"bg-white w-100 justify-between relative tc pt3 "
<div className={"bg-white bg-gray0-d white-d w-100 justify-between relative tc pt3 "
+ popout}
style={{ height: 40 }}>
<a className="dib gray2 f9 inter absolute left-0"
href='/'
style={{top: 14}}>
<IconHome classes={spinnerClasses}/>
<span className="ml2 v-top lh-title"
<span className="ml2 v-top lh-title white-d"
style={{paddingTop: 3}}>
Home
</span>

View File

@ -6,7 +6,10 @@ export class IconHome extends Component {
let classes = !!this.props.classes ? this.props.classes : "";
return (
<img className={classes} src="/~publish/Home.png" width={16} height={16} />
<img className={"invert-d " + classes}
src="/~publish/Home.png"
width={16}
height={16} />
);
}
}

View File

@ -16,7 +16,7 @@ export class SidebarSwitcher extends Component {
api.sidebarToggle();
}}>
<img
className={`pr3 invert-d dn ` + popoutSwitcher}
className={`pr3 dn ` + popoutSwitcher}
src={
this.props.sidebarShown
? "/~link/img/SwitcherOpen.png"

View File

@ -222,8 +222,8 @@ export class InviteSearch extends Component {
<li
key={group}
className={
"list mono white-d f8 pv2 ph3 pointer" +
" hover-bg-gray4 hover-black-d"
"list mono mix-blend-diff white f8 pv2 ph3 pointer" +
" hover-bg-gray4 hover-bg-gray1-d"
}
onClick={e => this.addGroup(group)}>
{group}
@ -233,14 +233,16 @@ export class InviteSearch extends Component {
let shipResults = state.searchResults.ships.map(ship => {
let nicknames = (this.state.contacts.has(ship))
? this.state.contacts.get(ship).join(", ")
? this.state.contacts.get(ship)
.filter(e => { return !(e === "") })
.join(", ")
: "";
return (
<li
key={ship}
className={
"list mono white-d f8 pv1 ph3 pointer" +
" hover-bg-gray4 hover-black-d relative"
" hover-bg-gray4 hover-bg-gray1-d relative"
}
onClick={e => this.addShip(ship)}>
<Sigil
@ -249,8 +251,8 @@ export class InviteSearch extends Component {
color="#000000"
classes="mix-blend-diff v-mid"
/>
<span className="v-mid ml2 mw5 truncate dib">{"~" + ship}</span>
<span className="absolute right-1 di truncate mw4 inter f9 pt1">{nicknames}</span>
<span className="v-mid ml2 mw5 truncate dib mix-blend-diff white">{"~" + ship}</span>
<span className="absolute right-1 di truncate mw4 inter f9 pt1 mix-blend-diff white">{nicknames}</span>
</li>
);
});

View File

@ -137,7 +137,7 @@ export class JoinScreen extends Component {
<textarea
ref={ e => { this.textarea = e; } }
className={"f7 mono ba bg-gray0-d white-d pa3 mb2 db " +
"focus-b--black b--gray3 b--gray2-d nowrap "}
"focus-b--black focus-b--white-d b--gray3 b--gray2-d nowrap "}
placeholder="~zod/dream-journal"
spellCheck="false"
rows={1}

View File

@ -105,7 +105,7 @@ export class NewPost extends Component {
popout={props.popout}
/>
<button
className={"v-mid w-100 mw6 tl h1 pl4"}
className={"bg-transparent v-mid w-100 mw6 tl h1 pl4"}
disabled={!state.submit}
style={submitStyle}
onClick={this.postSubmit}>
@ -126,7 +126,7 @@ export class NewPost extends Component {
<input
autoFocus
type="text"
className="w-100 pb2"
className="bg-transparent white-d w-100 pb2"
onChange={this.titleChange}
placeholder="New Post"
/>

View File

@ -139,7 +139,7 @@ export class NewScreen extends Component {
return (
<div
className={
"h-100 w-100 mw6 pa3 pt4 overflow-x-hidden flex flex-column"
"h-100 w-100 mw6 pa3 pt4 overflow-x-hidden flex flex-column white-d"
}>
<div className="w-100 dn-m dn-l dn-xl inter pt1 pb6 f8">
<Link to="/~publish/">{"⟵ All Notebooks"}</Link>
@ -152,7 +152,7 @@ export class NewScreen extends Component {
</p>
<textarea
className={"f7 ba bg-gray0-d white-d pa3 db w-100 " +
"focus-b--black b--gray3 b--gray2-d"}
"focus-b--black focus-b--white-d b--gray3 b--gray2-d"}
placeholder="eg. My Journal"
rows={1}
style={{
@ -169,7 +169,7 @@ export class NewScreen extends Component {
<p className="f9 gray2 db mb2 pt1">What's your notebook about?</p>
<textarea
className={"f7 ba bg-gray0-d white-d pa3 db w-100 " +
"focus-b--black b--gray3 b--gray2-d"}
"focus-b--black focus-b--white-d b--gray3 b--gray2-d"}
placeholder="Notebook description"
rows={1}
style={{

View File

@ -5,7 +5,7 @@ export class NotebookItem extends Component {
render() {
let { props } = this;
let selectedClass = (props.selected) ? "bg-gray5 b--gray4" : "b--gray4";
let selectedClass = (props.selected) ? "bg-gray5 bg-gray1-d b--gray4 b--gray2-d" : "b--gray4 b--gray2-d";
let postCount = (props.total === 1)
? `${props.total} post` : `${props.total} posts`;

View File

@ -81,12 +81,12 @@ export class Notebook extends Component {
let notebook = props.notebooks[props.ship][props.book];
let tabStyles = {
posts: "bb b--gray4 gray2 pv4 ph2",
about: "bb b--gray4 gray2 pv4 ph2",
subscribers: "bb b--gray4 gray2 pv4 ph2",
settings: "bb b--gray4 pr2 gray2 pv4 ph2",
posts: "bb b--gray4 b--gray2-d gray2 pv4 ph2",
about: "bb b--gray4 b--gray2-d gray2 pv4 ph2",
subscribers: "bb b--gray4 b--gray2-d gray2 pv4 ph2",
settings: "bb b--gray4 b--gray2-d pr2 gray2 pv4 ph2",
};
tabStyles[props.view] = "bb b--black black pv4 ph2";
tabStyles[props.view] = "bb b--black b--white-d black white-d pv4 ph2";
let inner = null;
switch (props.view) {
@ -154,7 +154,7 @@ export class Notebook extends Component {
let unsub = (window.ship === props.ship.slice(1))
? null
: <button onClick={this.unsubscribe}
className="NotebookButton bg-white black ba b--black ml3">
className="NotebookButton bg-white bg-gray0-d black white-d ba b--black b--gray2-d ml3">
Unsubscribe
</button>
@ -224,7 +224,7 @@ export class Notebook extends Component {
</Link>
{subsComponent}
{settingsComponent}
<div className="bb b--gray4 gray2 pv4 ph2"
<div className="bb b--gray4 b--gray2-d gray2 pv4 ph2"
style={{ flexGrow: 1 }}></div>
</div>

View File

@ -24,7 +24,7 @@ export class Settings extends Component {
<p className="f9 gray2 db mb4">
Permanently delete this notebook. (All current members will no longer see this notebook)
</p>
<button className="b--red2 red2 pointer dib f9 ba pa2"
<button className="bg-transparent b--red2 red2 pointer dib f9 ba pa2"
onClick={this.deleteNotebook}>
Delete this notebook
</button>

View File

@ -155,28 +155,28 @@ export class Sidebar extends Component {
<Link to="/~publish/join" className="f9 gray2">
Join Notebook
</Link>
<div className="pl2 pv2 bb b--gray4">
<div className="pl2 pv2 bb b--gray4 b--gray2-d">
<Dropdown
width="16rem"
align="left"
options={[
{
cls: "w-100 tl pointer db ph2 pv3 hover-bg-gray4",
cls: "white-d w-100 tl pointer db ph2 pv3 hover-bg-gray4 hover-bg-gray1-d bg-transparent",
txt: "Oldest",
action: () => {this.setState({sort: "oldest"})}
},
{
cls: "w-100 tl pointer db ph2 pv3 hover-bg-gray4",
cls: "white-d w-100 tl pointer db ph2 pv3 hover-bg-gray4 hover-bg-gray1-d bg-transparent",
txt: "Newest",
action: () => {this.setState({sort: "newest"})}
},
{
cls: "w-100 tl pointer db ph2 pv3 hover-bg-gray4",
cls: "white-d w-100 tl pointer db ph2 pv3 hover-bg-gray4 hover-bg-gray1-d bg-transparent",
txt: "A -> Z",
action: () => {this.setState({sort: "alphabetical"})}
},
{
cls: "w-100 tl pointer db ph2 pv3 hover-bg-gray4",
cls: "white-d w-100 tl pointer db ph2 pv3 hover-bg-gray4 hover-bg-gray1-d bg-transparent",
txt: "Z -> A",
action: () => {this.setState({sort: "reverseAlphabetical"})}
}

View File

@ -54,14 +54,14 @@ export class Subscribers extends Component {
width = 258;
let url = `/~contacts${writePath}`;
options = [{
cls: "tl pointer w-100 db hover-bg-gray4 ph2 pv3",
cls: "bg-transparent white-d tl pointer w-100 db hover-bg-gray4 hover-bg-gray1-d ph2 pv3",
txt: "Manage this group in the contacts view",
action: () => {this.redirect(url)}
}];
} else {
width = 157;
options = [{
cls: "tl pointer w-100 db hover-bg-gray4 ph2 pv3",
cls: "bg-transparent white-d tl pointer w-100 db hover-bg-gray4 hover-bg-gray1-d ph2 pv3",
txt: "Demote to subscriber",
action: () => {this.removeUser(`~${who}`, writePath)}
}];

View File

@ -31,7 +31,7 @@ export class Skeleton extends Component {
path={props.path}
invites={props.invites}
/>
<div className={"h-100 w-100 relative " + rightPanelHide} style={{
<div className={"h-100 w-100 relative white-d " + rightPanelHide} style={{
flexGrow: 1,
}}>
{props.children}