Merge pull request #2410 from urbit/mp/os1/invite-launch

launch: subscribe to invite-view, show group invite count in tile
This commit is contained in:
ixv 2020-03-10 12:17:34 -07:00 committed by GitHub
commit 9d0fe998c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 159 additions and 13 deletions

View File

@ -119,7 +119,7 @@ export class NewScreen extends Component {
"focus-b--black focus-b--white-d" "focus-b--black focus-b--white-d"
} }
rows={1} rows={1}
placeholder="Two trumpeteers and a microphone" placeholder="Two trumpeters and a microphone"
style={{ style={{
resize: "none", resize: "none",
height: 48, height: 48,

View File

@ -8,13 +8,36 @@ export default class ContactTile extends Component {
render() { render() {
const { props } = this; const { props } = this;
let data = _.get(props.data, "invites", false);
let inviteNum = 0;
if (data && "/contacts" in data) {
inviteNum = Object.keys(data["/contacts"]).length;
}
let numNotificationsElem =
inviteNum > 0 ? (
<p
className="absolute green2 white-d"
style={{
bottom: 6,
fontWeight: 400,
fontSize: 12,
lineHeight: "20px"
}}>
{inviteNum > 99 ? "99+" : inviteNum}
</p>
) : (
<div />
);
return ( return (
<div className={"w-100 h-100 relative bg-white bg-gray0-d " + <div
"b--black b--gray1-d ba"}> className={
"w-100 h-100 relative bg-white bg-gray0-d " + "b--black b--gray1-d ba"
}>
<a className="w-100 h-100 db pa2 bn" href="/~groups"> <a className="w-100 h-100 db pa2 bn" href="/~groups">
<p <p className="black white-d absolute f9" style={{ left: 8, top: 8 }}>
className="black white-d absolute f9"
style={{ left: 8, top: 8 }}>
Groups Groups
</p> </p>
<img <img
@ -24,6 +47,7 @@ export default class ContactTile extends Component {
width={48} width={48}
height={48} height={48}
/> />
{numNotificationsElem}
</a> </a>
</div> </div>
); );

View File

@ -1,8 +1,50 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Sigil } from './sigil'; import { Sigil } from './sigil';
import _ from 'lodash';
export default class Header extends Component { export default class Header extends Component {
render() { render() {
let data = _.get(this.props.data, "invites", false);
let inviteNum = 0;
if (data && "/contacts" in data) {
inviteNum = Object.keys(data["/contacts"]).length;
}
let numNotificationsElem =
inviteNum > 0 ? (
<a href="/~groups">
<p
className="absolute ph1 br2 ba b--gray2 green2 white-d f9 lh-solid"
title={"Invitations to new groups"}
style={{
bottom: "-2",
fontWeight: 600,
fontSize: "8pt",
padding: "0.15rem 0.4rem",
right: 64
}}>
{inviteNum > 99 ? "99+" : inviteNum}
</p>
</a>
) : (
<a href="/~groups">
<p
className="absolute ph1 br2 ba b--gray2 gray2 white-d f9 lh-solid"
title={"No new invitations to new groups"}
style={{
bottom: "-2",
fontWeight: 600,
fontSize: "8pt",
padding: "0.15rem 0.4rem",
right: 64
}}>
0
</p>
</a>
);
return ( return (
<header <header
className="bg-white bg-gray0-d w-100 justify-between relative tc pt3" className="bg-white bg-gray0-d w-100 justify-between relative tc pt3"
@ -16,6 +58,7 @@ export default class Header extends Component {
Home Home
</span> </span>
<div className="absolute right-1 lh-copy" style={{ top: 12 }}> <div className="absolute right-1 lh-copy" style={{ top: 12 }}>
{numNotificationsElem}
<Sigil <Sigil
ship={"~" + window.ship} ship={"~" + window.ship}
size={16} color={"#000000"} size={16} color={"#000000"}

View File

@ -17,14 +17,25 @@ export default class Home extends Component {
render() { render() {
let keys = [...this.props.keys]; let keys = [...this.props.keys];
let tileElems = keys.map((tile) => { let tileElems = keys.map((tile) => {
return ( let tileData = {};
<Tile key={tile} type={tile} data={this.props.data[tile]} /> if (tile in this.props.data && tile !== "invites") {
); tileData = this.props.data[tile] !== null
? this.props.data[tile] : {};
tileData["invites"] = ("invites" in this.props.data)
? this.props.data["invites"] : {};
}
return <Tile key={tile} type={tile} data={tileData} />;
}); });
let headerData = {};
if ("invites" in this.props.data) {
headerData["invites"] = this.props.data["invites"];
}
return ( return (
<div className="fl w-100 h-100 bg-white bg-gray0-d center"> <div className="fl w-100 h-100 bg-white bg-gray0-d center">
<Header /> <Header data={headerData}/>
<div className={"v-mid pa2 dtc-m dtc-l dtc-xl " + <div className={"v-mid pa2 dtc-m dtc-l dtc-xl " +
"flex justify-between flex-wrap"} "flex justify-between flex-wrap"}
style={{maxWidth: "40rem"}}> style={{maxWidth: "40rem"}}>

View File

@ -0,0 +1,55 @@
import _ from 'lodash';
export class InviteReducer {
reduce(json, state) {
let data = _.get(json, "invite-initial", false);
if (data) {
state.invites = data;
}
data = _.get(json, "invite-update", false);
if (data) {
this.create(data, state);
this.delete(data, state);
this.invite(data, state);
this.accepted(data, state);
this.decline(data, state);
}
}
create(json, state) {
let data = _.get(json, "create", false);
if (data) {
state.invites[data.path] = {};
}
}
delete(json, state) {
let data = _.get(json, "delete", false);
if (data) {
delete state.invites[data.path];
}
}
invite(json, state) {
let data = _.get(json, "invite", false);
if (data) {
state.invites[data.path][data.uid] = data.invite;
}
}
accepted(json, state) {
let data = _.get(json, "accepted", false);
if (data) {
console.log(data);
delete state.invites[data.path][data.uid];
}
}
decline(json, state) {
let data = _.get(json, "decline", false);
if (data) {
delete state.invites[data.path][data.uid];
}
}
}

View File

@ -1,8 +1,12 @@
import { InviteReducer } from '/reducers/invite.js';
class Store { class Store {
constructor() { constructor() {
this.state = {}; this.state = {
invites: {}
};
this.setState = () => {}; this.setState = () => {};
this.inviteReducer = new InviteReducer();
} }
setStateHandler(setState) { setStateHandler(setState) {
@ -10,9 +14,14 @@ class Store {
} }
handleEvent(data) { handleEvent(data) {
if (("from" in data) && data.from.app === "invite-view") {
this.inviteReducer.reduce(data.data, this.state)
}
else {
let json = data.data; let json = data.data;
this.setState(json); this.setState(json);
}
this.setState(this.state);
} }
} }

View File

@ -26,7 +26,11 @@ export class Subscription {
this.handleEvent.bind(this), this.handleEvent.bind(this),
this.handleError.bind(this), this.handleError.bind(this),
ship); ship);
} api.bind("invite-view", '/primary',
this.handleEvent.bind(this),
this.handleError.bind(this),
ship);
}
handleEvent(diff) { handleEvent(diff) {
store.handleEvent(diff); store.handleEvent(diff);