Merge pull request #2318 from urbit/mp/os1/chat/spinner

chat: add new spinner, behaviours
This commit is contained in:
Logan 2020-02-20 13:40:45 -08:00 committed by GitHub
commit a0b9e84ae5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 71 additions and 85 deletions

View File

@ -108,6 +108,20 @@ h2 {
font-family: "Inter", sans-serif; font-family: "Inter", sans-serif;
} }
/* spinner */
.spin-active {
animation: spin 2s infinite;
}
@keyframes spin {
0% {transform: rotate(0deg);}
25% {transform: rotate(90deg);}
50% {transform: rotate(180deg);}
75% {transform: rotate(270deg);}
100% {transform: rotate(360deg);}
}
/* embeds */ /* embeds */
.embed-container { .embed-container {
position: relative; position: relative;

View File

@ -1,38 +0,0 @@
.spinner-pending {
position: relative;
content: "";
border-radius: 100%;
height: 16px;
width: 16px;
background-color: rgba(255,255,255,1);
}
.spinner-pending::after {
content: "";
background-color: rgba(128,128,128,1);
width: 16px;
height: 16px;
position: absolute;
border-radius: 100%;
clip: rect(0, 16px, 16px, 8px);
animation: spin 1s cubic-bezier(0.745, 0.045, 0.355, 1.000) infinite;
}
@keyframes spin {
0% {transform:rotate(0deg)}
25% {transform:rotate(90deg)}
50% {transform:rotate(180deg)}
75% {transform:rotate(270deg)}
100% {transform:rotate(360deg)}
}
.spinner-nostart {
width: 8px;
height: 8px;
border-radius: 100%;
content:'';
background-color: black;
}

View File

@ -125,11 +125,11 @@ class UrbitApi {
} }
chatViewAction(data) { chatViewAction(data) {
this.action("chat-view", "json", data); return this.action("chat-view", "json", data);
} }
chatViewCreate(path, security, members, allowHistory) { chatViewCreate(path, security, members, allowHistory) {
this.chatViewAction({ return this.chatViewAction({
create: { create: {
path, security, members, path, security, members,
'allow-history': allowHistory 'allow-history': allowHistory
@ -185,6 +185,16 @@ class UrbitApi {
} }
}); });
} }
setSpinner(boolean) {
store.handleEvent({
data: {
local: {
spinner: boolean
}
}
})
}
} }
export let api = new UrbitApi(); export let api = new UrbitApi();

View File

@ -1,23 +1,23 @@
import React, { Component } from "react"; import React, { Component } from "react";
import classnames from "classnames"; import classnames from "classnames";
import { IconHome } from "/components/lib/icons/icon-home"; import { IconHome } from "/components/lib/icons/icon-home";
import { IconSpinner } from "/components/lib/icons/icon-spinner";
import { Sigil } from "/components/lib/icons/sigil"; import { Sigil } from "/components/lib/icons/sigil";
export class HeaderBar extends Component { export class HeaderBar extends Component {
render() { render() {
// let spin = (this.props.spinner)
// ? <div className="absolute"
// style={{width: 16, height: 16, top: 16, left: 55}}>
// <IconSpinner/>
// </div>
// : null;
let popout = window.location.href.includes("popout/") let popout = window.location.href.includes("popout/")
? "dn" : "dn db-m db-l db-xl"; ? "dn" : "dn db-m db-l db-xl";
let title = document.title === "Home" ? "" : document.title; let title = document.title === "Home" ? "" : document.title;
let spinner = !!this.props.spinner
? this.props.spinner : false;
let spinnerClasses = "";
if (spinner === true) {
spinnerClasses = "spin-active";
}
return ( return (
<div <div
className={ className={
@ -28,7 +28,7 @@ export class HeaderBar extends Component {
className="dib gray2 f9 inter absolute left-0" className="dib gray2 f9 inter absolute left-0"
href="/" href="/"
style={{ top: 14 }}> style={{ top: 14 }}>
<IconHome /> <IconHome classes={spinnerClasses} />
<span <span
className="ml2 white-d v-top lh-title" className="ml2 white-d v-top lh-title"
style={{ paddingTop: 3 }}> style={{ paddingTop: 3 }}>
@ -43,10 +43,14 @@ export class HeaderBar extends Component {
}}> }}>
{title} {title}
</span> </span>
{/* {spin} */} <div className="absolute right-0 lh-copy" style={{ top: 9 }}>
<div className="absolute right-0 lh-copy" style={{ top: 12 }}> <Sigil
<Sigil ship={"~" + window.ship} size={16} color={"#000000"} /> ship={"~" + window.ship}
<span className="mono white-d f9 ml2 v-top">{"~" + window.ship}</span> size={16}
color={"#000000"}
classes="v-mid mix-blend-diff"
/>
<span className="mono white-d f9 ml2">{"~" + window.ship}</span>
</div> </div>
</div> </div>
); );

View File

@ -2,10 +2,10 @@ import React, { Component } from "react";
export class IconHome extends Component { export class IconHome extends Component {
render() { render() {
let classes = !!this.props.classes ? this.props.classes : "";
return ( return (
//TODO relocate to ~launch when OS1 is ported
<img <img
className="invert-d" className={"invert-d " + classes}
src="/~chat/img/Home.png" src="/~chat/img/Home.png"
width={16} width={16}
height={16} height={16}

View File

@ -1,9 +0,0 @@
import React, { Component } from 'react';
export class IconSpinner extends Component {
render() {
return (
<div className="spinner-pending"></div>
);
}
}

View File

@ -145,7 +145,7 @@ export class NewScreen extends Component {
group: [], group: [],
ships: [] ships: []
}, () => { }, () => {
props.setSpinner(true); props.api.setSpinner(true);
// if we want a "proper group" that can be managed from the contacts UI, // if we want a "proper group" that can be managed from the contacts UI,
// we make a path of the form /~zod/cool-group // we make a path of the form /~zod/cool-group
// if not, we make a path of the form /~/~zod/free-chat // if not, we make a path of the form /~/~zod/free-chat
@ -153,10 +153,13 @@ export class NewScreen extends Component {
if (!state.createGroup && state.groups.length === 0) { if (!state.createGroup && state.groups.length === 0) {
chatPath = `/~${chatPath}`; chatPath = `/~${chatPath}`;
} }
props.api.chatView.create( let submit = props.api.chatView.create(
chatPath, state.security, aud, state.allowHistory chatPath, state.security, aud, state.allowHistory
); );
props.history.push(`/~chat/room${chatPath}`); submit.then(() => {
props.api.setSpinner(false);
props.history.push(`/~chat/room${chatPath}`);
})
}); });
} }

View File

@ -21,13 +21,6 @@ export class Root extends Component {
this.state = store.state; this.state = store.state;
store.setStateHandler(this.setState.bind(this)); store.setStateHandler(this.setState.bind(this));
this.setSpinner = this.setSpinner.bind(this);
}
setSpinner(spinner) {
this.setState({
spinner
});
} }
render() { render() {
@ -95,12 +88,11 @@ export class Root extends Component {
return ( return (
<Skeleton <Skeleton
sidebarHideOnMobile={true} sidebarHideOnMobile={true}
spinner={this.state.spinner} spinner={state.spinner}
sidebar={renderChannelSidebar(props)} sidebar={renderChannelSidebar(props)}
sidebarShown={state.sidebarShown} sidebarShown={state.sidebarShown}
> >
<NewScreen <NewScreen
setSpinner={this.setSpinner}
api={api} api={api}
inbox={state.inbox || {}} inbox={state.inbox || {}}
groups={state.groups || {}} groups={state.groups || {}}
@ -124,6 +116,7 @@ export class Root extends Component {
return ( return (
<Skeleton <Skeleton
spinner={state.spinner}
sidebarHideOnMobile={true} sidebarHideOnMobile={true}
sidebar={renderChannelSidebar(props)} sidebar={renderChannelSidebar(props)}
sidebarShown={state.sidebarShown} sidebarShown={state.sidebarShown}
@ -146,7 +139,7 @@ export class Root extends Component {
let sig = props.match.url.includes("/~/"); let sig = props.match.url.includes("/~/");
if (sig) { if (sig) {
station = '/~' + station; station = '/~' + station;
} }
let mailbox = state.inbox[station] || { let mailbox = state.inbox[station] || {
config: { config: {
read: 0, read: 0,
@ -164,6 +157,7 @@ export class Root extends Component {
return ( return (
<Skeleton <Skeleton
sidebarHideOnMobile={true} sidebarHideOnMobile={true}
spinner={state.spinner}
popout={popout} popout={popout}
sidebarShown={state.sidebarShown} sidebarShown={state.sidebarShown}
sidebar={renderChannelSidebar(props)} sidebar={renderChannelSidebar(props)}
@ -197,7 +191,7 @@ export class Root extends Component {
let sig = props.match.url.includes("/~/"); let sig = props.match.url.includes("/~/");
if (sig) { if (sig) {
station = '/~' + station; station = '/~' + station;
} }
let permission = state.permissions[station] || { let permission = state.permissions[station] || {
kind: "", kind: "",
@ -211,6 +205,7 @@ export class Root extends Component {
return ( return (
<Skeleton <Skeleton
sidebarHideOnMobile={true} sidebarHideOnMobile={true}
spinner={state.spinner}
sidebarShown={state.sidebarShown} sidebarShown={state.sidebarShown}
popout={popout} popout={popout}
sidebar={renderChannelSidebar(props)} sidebar={renderChannelSidebar(props)}
@ -238,7 +233,7 @@ export class Root extends Component {
let sig = props.match.url.includes("/~/"); let sig = props.match.url.includes("/~/");
if (sig) { if (sig) {
station = '/~' + station; station = '/~' + station;
} }
let group = state.groups[station] || new Set([]); let group = state.groups[station] || new Set([]);
let popout = props.match.url.includes("/popout/"); let popout = props.match.url.includes("/popout/");
@ -246,7 +241,7 @@ export class Root extends Component {
return ( return (
<Skeleton <Skeleton
sidebarHideOnMobile={true} sidebarHideOnMobile={true}
spinner={this.state.spinner} spinner={state.spinner}
popout={popout} popout={popout}
sidebarShown={state.sidebarShown} sidebarShown={state.sidebarShown}
sidebar={renderChannelSidebar(props)} sidebar={renderChannelSidebar(props)}
@ -254,7 +249,6 @@ export class Root extends Component {
<SettingsScreen <SettingsScreen
{...props} {...props}
station={station} station={station}
setSpinner={this.setSpinner}
api={api} api={api}
station={station} station={station}
group={group} group={group}

View File

@ -26,7 +26,7 @@ export class SettingsScreen extends Component {
this.setState({ this.setState({
isLoading: false isLoading: false
}, () => { }, () => {
props.setSpinner(false); props.api.setSpinner(false);
props.history.push('/~chat'); props.history.push('/~chat');
}); });
} }
@ -36,7 +36,7 @@ export class SettingsScreen extends Component {
const { props, state } = this; const { props, state } = this;
props.api.chatView.delete(props.station); props.api.chatView.delete(props.station);
props.setSpinner(true); props.api.setSpinner(true);
this.setState({ this.setState({
isLoading: true isLoading: true

View File

@ -5,6 +5,7 @@ export class LocalReducer {
let data = _.get(json, 'local', false); let data = _.get(json, 'local', false);
if (data) { if (data) {
this.sidebarToggle(data, state); this.sidebarToggle(data, state);
this.setSpinner(data, state);
} }
} }
@ -14,4 +15,11 @@ export class LocalReducer {
state.sidebarShown = obj.sidebarToggle; state.sidebarShown = obj.sidebarToggle;
} }
} }
setSpinner(obj, state) {
let data = _.has(obj, 'spinner', false);
if (data) {
state.spinner = obj.spinner;
}
}
} }