mirror of
https://github.com/urbit/shrub.git
synced 2025-01-01 17:16:47 +03:00
Merge branch 'lf/unread-day-indicators' (#2768)
* origin/lf/unread-day-indicators: chat-fe: fix unreadnotice position on mobile chat-fe: add unread and day indicators Signed-off-by: Jared Tobin <jared@tlon.io>
This commit is contained in:
commit
995b92650e
@ -169,6 +169,14 @@ h2 {
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.green3 {
|
||||
color: #7ea899;
|
||||
}
|
||||
|
||||
.unread-notice {
|
||||
top: 48px;
|
||||
}
|
||||
|
||||
/* responsive */
|
||||
|
||||
@media all and (max-width: 34.375em) {
|
||||
@ -187,6 +195,9 @@ h2 {
|
||||
.embed-container {
|
||||
padding-bottom: 56.25%;
|
||||
}
|
||||
.unread-notice {
|
||||
top: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 34.375em) and (max-width: 46.875em) {
|
||||
|
@ -120,7 +120,9 @@ class UrbitApi {
|
||||
}
|
||||
};
|
||||
|
||||
this.action("chat-hook", "json", data);
|
||||
this.action("chat-hook", "json", data).then(() => {
|
||||
this.chatRead(path);
|
||||
})
|
||||
data.message.envelope.author = data.message.envelope.author.substr(1);
|
||||
this.addPendingMessage(data.message);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
import { Route, Link } from "react-router-dom";
|
||||
import { store } from "/store";
|
||||
@ -10,6 +11,7 @@ import { Message } from '/components/lib/message';
|
||||
import { SidebarSwitcher } from '/components/lib/icons/icon-sidebar-switch.js';
|
||||
import { ChatTabBar } from '/components/lib/chat-tabbar';
|
||||
import { ChatInput } from '/components/lib/chat-input';
|
||||
import { UnreadNotice } from '/components/lib/unread-notice';
|
||||
import { deSig } from '/lib/util';
|
||||
|
||||
function getNumPending(props) {
|
||||
@ -37,24 +39,26 @@ export class ChatScreen extends Component {
|
||||
this.scrollContainer = null;
|
||||
this.onScroll = this.onScroll.bind(this);
|
||||
|
||||
this.updateReadInterval = setInterval(
|
||||
this.updateReadNumber.bind(this),
|
||||
1000
|
||||
);
|
||||
this.unreadMarker = null;
|
||||
|
||||
moment.updateLocale('en', {
|
||||
calendar: {
|
||||
sameDay: '[Today]',
|
||||
nextDay: '[Tomorrow]',
|
||||
nextWeek: 'dddd',
|
||||
lastDay: '[Yesterday]',
|
||||
lastWeek: '[Last] dddd',
|
||||
sameElse: 'DD/MM/YYYY'
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.scrollToBottom();
|
||||
this.updateReadNumber();
|
||||
this.askForMessages();
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.updateReadInterval) {
|
||||
clearInterval(this.updateReadInterval);
|
||||
this.updateReadInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { props, state } = this;
|
||||
@ -69,17 +73,10 @@ export class ChatScreen extends Component {
|
||||
this.askForMessages();
|
||||
}
|
||||
|
||||
clearInterval(this.updateReadInterval);
|
||||
|
||||
this.setState(
|
||||
{ scrollLocked: false },
|
||||
() => {
|
||||
this.scrollToBottom();
|
||||
this.updateReadInterval = setInterval(
|
||||
this.updateReadNumber.bind(this),
|
||||
1000
|
||||
);
|
||||
this.updateReadNumber();
|
||||
}
|
||||
);
|
||||
} else if (props.chatInitialized &&
|
||||
@ -113,13 +110,6 @@ export class ChatScreen extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
updateReadNumber() {
|
||||
const { props, state } = this;
|
||||
if (props.read < props.length) {
|
||||
props.api.chat.read(props.station);
|
||||
}
|
||||
}
|
||||
|
||||
askForMessages() {
|
||||
const { props, state } = this;
|
||||
|
||||
@ -230,9 +220,23 @@ export class ChatScreen extends Component {
|
||||
} else {
|
||||
console.log("Your browser is not supported.");
|
||||
}
|
||||
if(!!this.unreadMarker) {
|
||||
if(
|
||||
!navigator.userAgent.includes('Firefox') &&
|
||||
e.target.scrollHeight - e.target.scrollTop - (e.target.clientHeight * 1.5) + this.unreadMarker.offsetTop > 50
|
||||
) {
|
||||
this.props.api.chat.read(this.props.station);
|
||||
} else if(navigator.userAgent.includes('Firefox') &&
|
||||
this.unreadMarker.offsetTop - e.target.scrollTop - (e.target.clientHeight / 2) > 0
|
||||
) {
|
||||
this.props.api.chat.read(this.props.station);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
chatWindow() {
|
||||
chatWindow(unread) {
|
||||
|
||||
// Replace with just the "not Firefox" implementation
|
||||
// when Firefox #1042151 is patched.
|
||||
@ -255,6 +259,7 @@ export class ChatScreen extends Component {
|
||||
return (value.pending = true);
|
||||
});
|
||||
|
||||
|
||||
messages = pendingMessages.concat(messages);
|
||||
|
||||
let messageElements = messages.map((msg, i) => {
|
||||
@ -268,7 +273,12 @@ export class ChatScreen extends Component {
|
||||
_.get(messages[i - 1], aut) !==
|
||||
_.get(msg, aut, msg.author);
|
||||
|
||||
return (
|
||||
let when = ['when'];
|
||||
let dayBreak =
|
||||
moment(_.get(messages[i+1], when)).format('YYYY.MM.DD') !==
|
||||
moment(_.get(messages[i], when)).format('YYYY.MM.DD');
|
||||
|
||||
const messageElem = (
|
||||
<Message
|
||||
key={msg.uid}
|
||||
msg={msg}
|
||||
@ -279,6 +289,39 @@ export class ChatScreen extends Component {
|
||||
pending={!!msg.pending}
|
||||
/>
|
||||
);
|
||||
if(unread > 0 && i === unread) {
|
||||
return (
|
||||
<>
|
||||
{messageElem}
|
||||
<div key={'unreads'+ msg.uid} ref={ref => (this.unreadMarker = ref)} className="mv2 green2 flex items-center f9">
|
||||
<hr className="ma0 w2 b--green2 bt-0" />
|
||||
<p className="mh4">
|
||||
New messages below
|
||||
</p>
|
||||
<hr className="ma0 flex-grow-1 b--green2 bt-0" />
|
||||
{ dayBreak && (
|
||||
<p className="gray2 mh4">
|
||||
{moment(_.get(messages[i], when)).calendar()}
|
||||
</p>
|
||||
)}
|
||||
<hr style={{ width: 'calc(50% - 48px)' }} className="b--green2 ma0 bt-0"/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
} else if(dayBreak) {
|
||||
return (
|
||||
<>
|
||||
{messageElem}
|
||||
<div key={'daybreak' + msg.uid} className="pv3 gray2 b--gray2 flex items-center justify-center f9 ">
|
||||
<p>
|
||||
{moment(_.get(messages[i], when)).calendar()}
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return messageElem;
|
||||
}
|
||||
});
|
||||
|
||||
if (navigator.userAgent.includes("Firefox")) {
|
||||
@ -357,10 +400,14 @@ export class ChatScreen extends Component {
|
||||
: props.station.substr(1);
|
||||
}
|
||||
|
||||
const unread = props.length - props.read;
|
||||
|
||||
const unreadMsg = unread > 0 && messages[unread - 1];
|
||||
|
||||
return (
|
||||
<div
|
||||
key={props.station}
|
||||
className="h-100 w-100 overflow-hidden flex flex-column">
|
||||
className="h-100 w-100 overflow-hidden flex flex-column relative">
|
||||
<div
|
||||
className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8"
|
||||
style={{ height: "1rem" }}>
|
||||
@ -392,7 +439,14 @@ export class ChatScreen extends Component {
|
||||
api={props.api}
|
||||
/>
|
||||
</div>
|
||||
{this.chatWindow()}
|
||||
{ !!unreadMsg && (
|
||||
<UnreadNotice
|
||||
unread={unread}
|
||||
unreadMsg={unreadMsg}
|
||||
onRead={() => props.api.chat.read(props.station)}
|
||||
/>
|
||||
) }
|
||||
{this.chatWindow(unread)}
|
||||
<ChatInput
|
||||
api={props.api}
|
||||
numMsgs={lastMsgNum}
|
||||
|
40
pkg/interface/chat/src/js/components/lib/unread-notice.js
Normal file
40
pkg/interface/chat/src/js/components/lib/unread-notice.js
Normal file
@ -0,0 +1,40 @@
|
||||
import React, { Component } from "react";
|
||||
import classnames from "classnames";
|
||||
import moment from "moment";
|
||||
|
||||
export class UnreadNotice extends Component {
|
||||
render() {
|
||||
let { unread, unreadMsg, onRead } = this.props;
|
||||
|
||||
let when = moment.unix(unreadMsg.when / 10000);
|
||||
|
||||
let datestamp = moment.unix(unreadMsg.when / 1000).format("YYYY.M.D");
|
||||
let timestamp = moment.unix(unreadMsg.when / 1000).format("HH:mm");
|
||||
|
||||
if (datestamp === moment().format("YYYY.M.D")) {
|
||||
datestamp = null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ left: "0px" }}
|
||||
className="pa4 w-100 absolute z-1 unread-notice"
|
||||
>
|
||||
<div className="ba b--green2 green2 bg-white bg-gray0-d flex items-center pa2 f9 justify-between br1">
|
||||
<p className="lh-copy db">
|
||||
{unread} new messages since{" "}
|
||||
{datestamp && (
|
||||
<>
|
||||
<span className="green3">~{datestamp}</span> at{" "}
|
||||
</>
|
||||
)}
|
||||
<span className="green3">{timestamp}</span>
|
||||
</p>
|
||||
<div onClick={onRead} className="ml4 inter b--green2 pointer tr lh-copy">
|
||||
Mark as Read
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user