Merge pull request #2278 from urbit/mp/os1/publish-comments-contact

publish: add nicknames and sigils to interface
This commit is contained in:
matildepark 2020-02-12 15:34:34 -05:00 committed by GitHub
commit a6133e44b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 156 additions and 40 deletions

View File

@ -1,7 +1,8 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import moment from 'moment'; import moment from 'moment';
import { Sigil } from './icons/sigil';
import { uxToHex } from '../../lib/util';
//TODO take props and render div
export class CommentItem extends Component { export class CommentItem extends Component {
constructor(props){ constructor(props){
super(props); super(props);
@ -36,12 +37,31 @@ export class CommentItem extends Component {
}); });
let date = moment(commentData["date-created"]).fromNow(); let date = moment(commentData["date-created"]).fromNow();
let contact = !!(commentData.author.substr(1) in this.props.contacts)
? this.props.contacts[commentData.author.substr(1)] : false;
let name = commentData.author;
let color = "#000000";
if (contact) {
name = (contact.nickname.length > 0)
? contact.nickname : commentData.author;
color = `#${uxToHex(contact.color)}`;
}
return ( return (
<div> <div>
<div className="flex mv3"> <div className="flex mv3">
<div className="f9 mono mr2">{commentData.author}</div> <Sigil
<div className="f9 gray3">{date}</div> ship={commentData.author}
size={24}
color={color}
/>
<div className={"f9 mh2 pt1" +
((name === commentData.author) ? " mono" : "")}>
{name}
</div>
<div className="f9 gray3 pt1">{date}</div>
</div> </div>
<div className="f8 lh-solid mb8 mb2"> <div className="f8 lh-solid mb8 mb2">
{content} {content}

View File

@ -34,7 +34,11 @@ export class Comments extends Component {
render() { render() {
let commentArray = this.props.comments.map((com, i) => { let commentArray = this.props.comments.map((com, i) => {
return ( return (
<CommentItem comment={com} key={i}/> <CommentItem
comment={com}
key={i}
contacts={this.props.contacts}
/>
); );
}) })

View File

@ -1,18 +1,21 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { sigil, reactRenderer } from 'urbit-sigil-js'; import { sigil, reactRenderer } from 'urbit-sigil-js';
export class Sigil extends Component { export class Sigil extends Component {
render() { render() {
const { props } = this; const { props } = this;
let classes = props.classes || "";
if (props.ship.length > 14) { if (props.ship.length > 14) {
return ( return (
<div className="bg-black flex-shrink-0" style={{width: props.size, height: props.size}}> <div className="bg-black dib" style={{ width: props.size, height: props.size }}>
</div> </div>
); );
} else { } else {
return ( return (
<div className="dib flex-shrink-0" style={{ flexBasis: 32, backgroundColor: props.color }}> <div className={"dib " + classes} style={{ flexBasis: props.size, backgroundColor: props.color }}>
{sigil({ {sigil({
patp: props.ship, patp: props.ship,
renderer: reactRenderer, renderer: reactRenderer,
@ -24,3 +27,4 @@ export class Sigil extends Component {
} }
} }
} }

View File

@ -89,20 +89,30 @@ export class Note extends Component {
} }
render() { render() {
let notebook = this.props.notebooks[this.props.ship][this.props.book]; const { props } = this;
let comments = notebook.notes[this.props.note].comments; let notebook = props.notebooks[props.ship][props.book];
let title = notebook.notes[this.props.note].title; let comments = notebook.notes[props.note].comments;
let author = notebook.notes[this.props.note].author; let title = notebook.notes[props.note].title;
let file = notebook.notes[this.props.note].file; let author = notebook.notes[props.note].author;
let date = moment(notebook.notes[this.props.note]["date-created"]).fromNow(); let file = notebook.notes[props.note].file;
let date = moment(notebook.notes[props.note]["date-created"]).fromNow();
let contact = !!(author.substr(1) in props.contacts)
? props.contacts[author.substr(1)] : false;
let name = author;
if (contact) {
name = (contact.nickname.length > 0)
? contact.nickname : author;
}
if (!file) { if (!file) {
return null; return null;
} }
let newfile = file.slice(file.indexOf(';>')+2); let newfile = file.slice(file.indexOf(';>')+2);
let prevId = notebook.notes[this.props.note]["prev-note"]; let prevId = notebook.notes[props.note]["prev-note"];
let nextId = notebook.notes[this.props.note]["next-note"]; let nextId = notebook.notes[props.note]["next-note"];
let prev = (prevId === null) let prev = (prevId === null)
? null ? null
@ -129,7 +139,10 @@ export class Note extends Component {
<div className="flex flex-column"> <div className="flex flex-column">
<div className="f9 mb1">{title}</div> <div className="f9 mb1">{title}</div>
<div className="flex mb6"> <div className="flex mb6">
<div className="di f9 mono gray2 mr2">{author}</div> <div className={"di f9 gray2 mr2 " +
((name === author) ? "mono" : "")}>
{name}
</div>
<div className="di f9 gray2">{date}</div> <div className="di f9 gray2">{date}</div>
</div> </div>
</div> </div>
@ -139,12 +152,14 @@ export class Note extends Component {
<NoteNavigation <NoteNavigation
prev={prev} prev={prev}
next={next} next={next}
ship={this.props.ship} ship={props.ship}
book={this.props.book}/> book={props.book}/>
<Comments ship={this.props.ship} <Comments ship={props.ship}
book={this.props.book} book={props.book}
note={this.props.note} note={props.note}
comments={comments}/> comments={comments}
contacts={props.contacts}
/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -13,12 +13,27 @@ export class NotebookItem extends Component {
let unread = (props.unreadCount > 0) let unread = (props.unreadCount > 0)
? `${props.unreadCount} unread` : ""; ? `${props.unreadCount} unread` : "";
let notebookContacts = (props.contactsPath in props.contacts)
? props.contacts[props.contactsPath] : {};
let contact = !!(props.author.substr(1) in notebookContacts)
? notebookContacts[props.author.substr(1)] : false;
let name = props.author;
if (contact) {
name = (contact.nickname.length > 0)
? contact.nickname : props.author;
}
return ( return (
<Link <Link
to={"/~publish/notebook/" + props.path}> to={"/~publish/notebook/" + props.path}>
<div className={"w-100 v-mid f9 pl4 bb " + selectedClass}> <div className={"w-100 v-mid f9 pl4 bb " + selectedClass}>
<p className="f9 pt1">{props.title}</p> <p className="f9 pt1">{props.title}</p>
<p className="f9 mono gray2">by {props.author}</p> <p className="f9 gray2">by
<span className={"pl1 " + ((name === props.author) ? "mono" : "")}>
{name}
</span>
</p>
<p className="f9 pb1"> <p className="f9 pb1">
{postCount} {postCount}
<span className="green2 ml3"> <span className="green2 ml3">

View File

@ -30,14 +30,24 @@ export class NotebookPosts extends Component {
} }
render() { render() {
const { props } = this;
let notes = []; let notes = [];
for (var i=0; i<this.props.list.length; i++) { for (var i=0; i<props.list.length; i++) {
let noteId = this.props.list[i]; let noteId = props.list[i];
let note = this.props.notes[noteId]; let note = props.notes[noteId];
if (!note) { if (!note) {
break; break;
} }
let contact = !!(note.author.substr(1) in props.contacts)
? props.contacts[note.author.substr(1)] : false;
let name = note.author;
if (contact) {
name = (contact.nickname.length > 0)
? contact.nickname : note.author;
}
let comment = "No Comments"; let comment = "No Comments";
if (note["num-comments"] == 1) { if (note["num-comments"] == 1) {
comment = "1 Comment"; comment = "1 Comment";
@ -45,7 +55,7 @@ export class NotebookPosts extends Component {
comment = `${note["num-comments"]} Comments`; comment = `${note["num-comments"]} Comments`;
} }
let date = moment(note["date-created"]).fromNow(); let date = moment(note["date-created"]).fromNow();
let url = `/~publish/note/${this.props.host}/${this.props.notebookName}/${noteId}` let url = `/~publish/note/${props.host}/${props.notebookName}/${noteId}`
notes.push( notes.push(
<Link key={i} to={url}> <Link key={i} to={url}>
@ -53,7 +63,8 @@ export class NotebookPosts extends Component {
<div className="mb1">{note.title}</div> <div className="mb1">{note.title}</div>
<p className="mb1">{note.snippet}</p> <p className="mb1">{note.snippet}</p>
<div className="flex"> <div className="flex">
<div className="mono gray2 mr3">{note.author}</div> <div className={((note.author === name) ? "mono" : "") +
" gray2 mr3"}>{name}</div>
<div className="gray2 mr3">{date}</div> <div className="gray2 mr3">{date}</div>
<div className="gray2">{comment}</div> <div className="gray2">{comment}</div>
</div> </div>

View File

@ -69,7 +69,9 @@ export class Notebook extends Component {
} }
render() { render() {
let notebook = this.props.notebooks[this.props.ship][this.props.book]; const { props } = this;
let notebook = props.notebooks[props.ship][props.book];
let tabStyles = { let tabStyles = {
posts: "bb b--gray4 gray2 pv4 ph2", posts: "bb b--gray4 gray2 pv4 ph2",
@ -77,17 +79,19 @@ export class Notebook extends Component {
// subscribers: "bb b--gray4 gray2 pv4 ph2", // subscribers: "bb b--gray4 gray2 pv4 ph2",
// settings: "bb b--gray4 pr2 gray2 pv4 ph2", // settings: "bb b--gray4 pr2 gray2 pv4 ph2",
}; };
tabStyles[this.props.view] = "bb b--black black pv4 ph2"; tabStyles[props.view] = "bb b--black black pv4 ph2";
let inner = null; let inner = null;
switch (this.props.view) { switch (props.view) {
case "posts": case "posts":
let notesList = notebook["notes-by-date"] || []; let notesList = notebook["notes-by-date"] || [];
let notes = notebook.notes || null; let notes = notebook.notes || null;
inner = <NotebookPosts notes={notes} inner = <NotebookPosts notes={notes}
list={notesList} list={notesList}
host={this.props.ship} host={props.ship}
notebookName={this.props.book}/> notebookName={props.book}
contacts={props.contacts}
/>
break; break;
case "about": case "about":
inner = <p className="f8 lh-solid">{notebook.about}</p> inner = <p className="f8 lh-solid">{notebook.about}</p>
@ -102,16 +106,24 @@ export class Notebook extends Component {
break; break;
} }
let base = `/~publish/notebook/${this.props.ship}/${this.props.book}`; let contact = !!(props.ship.substr(1) in props.contacts)
? props.contacts[props.ship.substr(1)] : false;
let name = props.ship;
if (contact) {
name = (contact.nickname.length > 0)
? contact.nickname : props.ship;
}
let base = `/~publish/notebook/${props.ship}/${props.book}`;
let about = base + '/about'; let about = base + '/about';
let subs = base + '/subscribers'; let subs = base + '/subscribers';
let settings = base + '/settings'; let settings = base + '/settings';
let newUrl = base + '/new'; let newUrl = base + '/new';
let newPost = null; let newPost = null;
if (notebook["writers-group-path"] in this.props.groups){ if (notebook["writers-group-path"] in props.groups){
let writers = notebook["writers-group-path"]; let writers = notebook["writers-group-path"];
if (this.props.groups[writers].has(window.ship)) { if (props.groups[writers].has(window.ship)) {
newPost = newPost =
<Link to={newUrl} className="NotebookButton bg-light-green green2"> <Link to={newUrl} className="NotebookButton bg-light-green green2">
New Post New Post
@ -119,7 +131,7 @@ export class Notebook extends Component {
} }
} }
let unsub = (window.ship === this.props.ship.slice(1)) let unsub = (window.ship === props.ship.slice(1))
? null ? null
: <button onClick={this.unsubscribe} : <button onClick={this.unsubscribe}
className="NotebookButton bg-white black ba b--black ml3"> className="NotebookButton bg-white black ba b--black ml3">
@ -143,7 +155,9 @@ export class Notebook extends Component {
<div className="mb1">{notebook.title}</div> <div className="mb1">{notebook.title}</div>
<span> <span>
<span className="gray3 mr1">by</span> <span className="gray3 mr1">by</span>
<span className="mono">{this.props.ship}</span> <span className={(props.ship === name) ? "mono" : ""}>
{name}
</span>
</span> </span>
</div> </div>
<div className="flex"> <div className="flex">

View File

@ -126,6 +126,8 @@ export class Sidebar extends Component {
key={book.title} key={book.title}
title={book.title} title={book.title}
author={author} author={author}
contacts={props.contacts}
contactsPath={book["subscribers-group-path"]}
path={path} path={path}
total={book["num-notes"]} total={book["num-notes"]}
unreadCount={book["num-unread"]} unreadCount={book["num-unread"]}

View File

@ -21,6 +21,8 @@ export class Root extends Component {
render() { render() {
const { props, state } = this; const { props, state } = this;
let contacts = !!state.contacts ? state.contacts : {};
return ( return (
<BrowserRouter> <BrowserRouter>
<Route exact path="/~publish" <Route exact path="/~publish"
@ -32,7 +34,8 @@ export class Root extends Component {
rightPanelHide={true} rightPanelHide={true}
sidebarShown={true} sidebarShown={true}
invites={state.invites} invites={state.invites}
notebooks={state.notebooks}> notebooks={state.notebooks}
contacts={contacts}>
<div className={`h-100 w-100 overflow-x-hidden flex flex-column <div className={`h-100 w-100 overflow-x-hidden flex flex-column
bg-white bg-gray0-d dn db-ns`}> bg-white bg-gray0-d dn db-ns`}>
<div className="pl3 pr3 pt2 dt pb3 w-100 h-100"> <div className="pl3 pr3 pt2 dt pb3 w-100 h-100">
@ -54,7 +57,8 @@ export class Root extends Component {
rightPanelHide={false} rightPanelHide={false}
sidebarShown={true} sidebarShown={true}
invites={state.invites} invites={state.invites}
notebooks={state.notebooks}> notebooks={state.notebooks}
contacts={contacts}>
<NewScreen <NewScreen
notebooks={state.notebooks} notebooks={state.notebooks}
groups={state.groups} groups={state.groups}
@ -73,7 +77,8 @@ export class Root extends Component {
rightPanelHide={false} rightPanelHide={false}
sidebarShown={true} sidebarShown={true}
invites={state.invites} invites={state.invites}
notebooks={state.notebooks}> notebooks={state.notebooks}
contacts={contacts}>
<JoinScreen notebooks={state.notebooks} {...props} /> <JoinScreen notebooks={state.notebooks} {...props} />
</Skeleton> </Skeleton>
) )
@ -89,6 +94,11 @@ export class Root extends Component {
let path = `${ship}/${notebook}`; let path = `${ship}/${notebook}`;
let bookGroupPath =
state.notebooks[ship][notebook]["subscribers-group-path"];
let notebookContacts = (bookGroupPath in contacts)
? contacts[bookGroupPath] : {};
if (view === "new") { if (view === "new") {
return ( return (
<Skeleton <Skeleton
@ -98,6 +108,7 @@ export class Root extends Component {
sidebarShown={true} sidebarShown={true}
invites={state.invites} invites={state.invites}
notebooks={state.notebooks} notebooks={state.notebooks}
contacts={contacts}
path={path}> path={path}>
<NewPost <NewPost
notebooks={state.notebooks} notebooks={state.notebooks}
@ -117,6 +128,7 @@ export class Root extends Component {
sidebarShown={true} sidebarShown={true}
invites={state.invites} invites={state.invites}
notebooks={state.notebooks} notebooks={state.notebooks}
contacts={contacts}
path={path}> path={path}>
<Notebook <Notebook
notebooks={state.notebooks} notebooks={state.notebooks}
@ -124,6 +136,7 @@ export class Root extends Component {
ship={ship} ship={ship}
book={notebook} book={notebook}
groups={state.groups} groups={state.groups}
contacts={notebookContacts}
{...props} {...props}
/> />
</Skeleton> </Skeleton>
@ -137,6 +150,11 @@ export class Root extends Component {
let path = `${ship}/${notebook}` let path = `${ship}/${notebook}`
let note = props.match.params.note || ""; let note = props.match.params.note || "";
let bookGroupPath =
state.notebooks[ship][notebook]["subscribers-group-path"];
let notebookContacts = (bookGroupPath in state.contacts)
? contacts[bookGroupPath] : {};
return ( return (
<Skeleton <Skeleton
popout={false} popout={false}
@ -145,10 +163,12 @@ export class Root extends Component {
sidebarShown={true} sidebarShown={true}
invites={state.invites} invites={state.invites}
notebooks={state.notebooks} notebooks={state.notebooks}
contacts={contacts}
path={path}> path={path}>
<Note <Note
notebooks={state.notebooks} notebooks={state.notebooks}
book={notebook} book={notebook}
contacts={notebookContacts}
ship={ship} ship={ship}
note={note} note={note}
/> />

View File

@ -29,6 +29,7 @@ export class Skeleton extends Component {
sidebarShown={props.sidebarShown} sidebarShown={props.sidebarShown}
active={props.active} active={props.active}
notebooks={props.notebooks} notebooks={props.notebooks}
contacts={props.contacts}
path={props.path} path={props.path}
invites={props.invites} invites={props.invites}
/> />

View File

@ -36,3 +36,13 @@ export function dateToDa(d, mil) {
`${mil ? "..0000" : ""}` `${mil ? "..0000" : ""}`
  );   );
} }
export function uxToHex(ux) {
if (ux.length > 2 && ux.substr(0, 2) === '0x') {
let value = ux.substr(2).replace('.', '').padStart(6, '0');
return value;
}
let value = ux.replace('.', '').padStart(6, '0');
return value;
}