received marker in message previews

This commit is contained in:
or-else
2021-01-19 18:50:18 -08:00
parent 4445a90437
commit 1f5a76e481
10 changed files with 125 additions and 69 deletions
+5
View File
@@ -551,6 +551,11 @@ div.alert .content {
margin-left: 1rem;
}
/* Extra spece on the right */
.space-right {
margin-right: 0.25rem;
}
/* Container with whitish background and rounded corners */
.rounded-container {
position: relative;
+1 -1
View File
File diff suppressed because one or more lines are too long
+19
View File
@@ -1,5 +1,7 @@
// Odds and ends
import Tinode from 'tinode-sdk';
// Make shortcut icon appear with a green dot + show unread count in title.
export function updateFavicon(count) {
const oldIcon = document.getElementById('shortcut-icon');
@@ -144,3 +146,20 @@ export function sanitizeImageUrl(url) {
return null;
}
// Given message's received status, return name and color of a delivery indicator icon.
export function deliveryMarker(received) {
switch (received) {
case Tinode.MESSAGE_STATUS_SENDING:
return { name: 'access_time' }; // watch face
case Tinode.MESSAGE_STATUS_FAILED:
return { name: 'warning', color: 'amber' }; // yellow icon /!\
case Tinode.MESSAGE_STATUS_SENT:
return { name: 'done' }; // checkmark
case Tinode.MESSAGE_STATUS_RECEIVED:
return { name: 'done_all' }; // double checkmark
case Tinode.MESSAGE_STATUS_READ:
return { name: 'done_all', color: 'blue' }; // blue double checkmark
}
return null;
}
+9 -4
View File
@@ -77,11 +77,15 @@ class ContactList extends React.Component {
const comment = Array.isArray(c.private) ?
c.private.join(',') : (c.private ? c.private.comment : null);
let preview;
let deliveryStatus;
if (!this.props.showMode) {
const content = (c.latestMessage() || { content: '' }).content;
preview = typeof content == 'string' ?
content.substr(0, MESSAGE_PREVIEW_LENGTH) :
Drafty.preview(content, MESSAGE_PREVIEW_LENGTH);
const msg = c.latestMessage();
if (msg) {
deliveryStatus = c.msgStatus(msg);
preview = typeof msg.content == 'string' ?
msg.content.substr(0, MESSAGE_PREVIEW_LENGTH) :
Drafty.preview(msg.content, MESSAGE_PREVIEW_LENGTH);
}
}
contactNodes.push(
<Contact
@@ -89,6 +93,7 @@ class ContactList extends React.Component {
avatar={makeImageUrl(c.public ? c.public.photo : null)}
comment={comment}
preview={preview}
received={deliveryStatus}
unread={this.props.showUnread ? c.unread : 0}
now={c.online && this.props.connected}
acs={c.acs}
+9 -3
View File
@@ -2,12 +2,15 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import LetterTile from './letter-tile.jsx';
import ContactBadges from './contact-badges.jsx';
import LetterTile from './letter-tile.jsx';
import ReceivedMarker from './received-marker.jsx'
import UnreadBadge from './unread-badge.jsx';
import { Drafty } from 'tinode-sdk';
import { deliveryMarker } from '../lib/utils.js';
export default class Contact extends React.Component {
constructor(props) {
super(props);
@@ -60,8 +63,11 @@ export default class Contact extends React.Component {
React.createElement(React.Fragment, null, Drafty.format(this.props.preview, draftyFormatter, this))) :
this.props.comment;
const icon = deliveryMarker(this.props.received);
const marker = icon ? <i className={'material-icons small space-right ' + icon.color}>{icon.name}</i> : null;
return (
<li className={!this.props.showCheckmark && this.props.selected ? "selected" : null} onClick={this.handleClick}>
<li className={!this.props.showCheckmark && this.props.selected ? 'selected' : null} onClick={this.handleClick}>
<div className="avatar-box">
<LetterTile
avatar={avatar}
@@ -77,7 +83,7 @@ export default class Contact extends React.Component {
{this.props.isChannel ? <img src="/img/channel.png" className="channel" alt="channel" /> : null}
<UnreadBadge count={this.props.unread} /><ContactBadges badges={icon_badges} />
</div>
<div className="contact-comment">{subtitle || '\u00A0'}</div>
<div className="contact-comment">{marker}{subtitle || '\u00A0'}</div>
<span><ContactBadges badges={badges} /></span>
</div>
{this.props.showContextMenu ?
+3 -12
View File
@@ -5,6 +5,7 @@ import { defineMessages, injectIntl } from 'react-intl';
import Tinode from 'tinode-sdk';
import { shortDateFormat } from '../lib/strformat.js';
import { deliveryMarker } from '../lib/utils.js';
const messages = defineMessages({
'sending': {
@@ -31,18 +32,8 @@ class ReceivedMarker extends React.PureComponent {
timestamp = shortDateFormat(this.props.timestamp, this.props.intl.locale);
}
let marker = null;
if (this.props.received <= Tinode.MESSAGE_STATUS_SENDING) {
marker = (<i className="material-icons small">access_time</i>); // watch face
} else if (this.props.received == Tinode.MESSAGE_STATUS_FAILED) {
marker = (<i className="material-icons small amber">warning</i>); // yellow icon /!\
} else if (this.props.received == Tinode.MESSAGE_STATUS_SENT) {
marker = (<i className="material-icons small">done</i>); // checkmark
} else if (this.props.received == Tinode.MESSAGE_STATUS_RECEIVED) {
marker = (<i className="material-icons small">done_all</i>); // double checkmark
} else if (this.props.received == Tinode.MESSAGE_STATUS_READ) {
marker = (<i className="material-icons small blue">done_all</i>); // blue double checkmark
}
const icon = deliveryMarker(this.props.received);
const marker = icon ? <i className={'material-icons small ' + icon.color}>{icon.name}</i> : null;
return (
<span className="timestamp">
+71 -41
View File
@@ -564,8 +564,12 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ "asEmail": function() { return /* binding */ asEmail; },
/* harmony export */ "isUrlRelative": function() { return /* binding */ isUrlRelative; },
/* harmony export */ "sanitizeUrl": function() { return /* binding */ sanitizeUrl; },
/* harmony export */ "sanitizeImageUrl": function() { return /* binding */ sanitizeImageUrl; }
/* harmony export */ "sanitizeImageUrl": function() { return /* binding */ sanitizeImageUrl; },
/* harmony export */ "deliveryMarker": function() { return /* binding */ deliveryMarker; }
/* harmony export */ });
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tinode-sdk */ "tinode-sdk");
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_0__);
function updateFavicon(count) {
const oldIcon = document.getElementById('shortcut-icon');
const head = document.head || document.getElementsByTagName('head')[0];
@@ -689,6 +693,38 @@ function sanitizeImageUrl(url) {
return null;
}
function deliveryMarker(received) {
switch (received) {
case (tinode_sdk__WEBPACK_IMPORTED_MODULE_0___default().MESSAGE_STATUS_SENDING):
return {
name: 'access_time'
};
case (tinode_sdk__WEBPACK_IMPORTED_MODULE_0___default().MESSAGE_STATUS_FAILED):
return {
name: 'warning',
color: 'amber'
};
case (tinode_sdk__WEBPACK_IMPORTED_MODULE_0___default().MESSAGE_STATUS_SENT):
return {
name: 'done'
};
case (tinode_sdk__WEBPACK_IMPORTED_MODULE_0___default().MESSAGE_STATUS_RECEIVED):
return {
name: 'done_all'
};
case (tinode_sdk__WEBPACK_IMPORTED_MODULE_0___default().MESSAGE_STATUS_READ):
return {
name: 'done_all',
color: 'blue'
};
}
return null;
}
/***/ }),
@@ -7244,12 +7280,15 @@ class ContactList extends (react__WEBPACK_IMPORTED_MODULE_0___default().Componen
const comment = Array.isArray(c.private) ? c.private.join(',') : c.private ? c.private.comment : null;
let preview;
let deliveryStatus;
if (!this.props.showMode) {
const content = (c.latestMessage() || {
content: ''
}).content;
preview = typeof content == 'string' ? content.substr(0, _config_js__WEBPACK_IMPORTED_MODULE_6__.MESSAGE_PREVIEW_LENGTH) : tinode_sdk__WEBPACK_IMPORTED_MODULE_2__.Drafty.preview(content, _config_js__WEBPACK_IMPORTED_MODULE_6__.MESSAGE_PREVIEW_LENGTH);
const msg = c.latestMessage();
if (msg) {
deliveryStatus = c.msgStatus(msg);
preview = typeof msg.content == 'string' ? msg.content.substr(0, _config_js__WEBPACK_IMPORTED_MODULE_6__.MESSAGE_PREVIEW_LENGTH) : tinode_sdk__WEBPACK_IMPORTED_MODULE_2__.Drafty.preview(msg.content, _config_js__WEBPACK_IMPORTED_MODULE_6__.MESSAGE_PREVIEW_LENGTH);
}
}
contactNodes.push(react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
@@ -7257,6 +7296,7 @@ class ContactList extends (react__WEBPACK_IMPORTED_MODULE_0___default().Componen
avatar: (0,_lib_blob_helpers_js__WEBPACK_IMPORTED_MODULE_5__.makeImageUrl)(c.public ? c.public.photo : null),
comment: comment,
preview: preview,
received: deliveryStatus,
unread: this.props.showUnread ? c.unread : 0,
now: c.online && this.props.connected,
acs: c.acs,
@@ -7310,11 +7350,15 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-intl */ "react-intl");
/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_intl__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _letter_tile_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./letter-tile.jsx */ "./src/widgets/letter-tile.jsx");
/* harmony import */ var _contact_badges_jsx__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./contact-badges.jsx */ "./src/widgets/contact-badges.jsx");
/* harmony import */ var _unread_badge_jsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./unread-badge.jsx */ "./src/widgets/unread-badge.jsx");
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! tinode-sdk */ "tinode-sdk");
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var _contact_badges_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./contact-badges.jsx */ "./src/widgets/contact-badges.jsx");
/* harmony import */ var _letter_tile_jsx__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./letter-tile.jsx */ "./src/widgets/letter-tile.jsx");
/* harmony import */ var _received_marker_jsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./received-marker.jsx */ "./src/widgets/received-marker.jsx");
/* harmony import */ var _unread_badge_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./unread-badge.jsx */ "./src/widgets/unread-badge.jsx");
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! tinode-sdk */ "tinode-sdk");
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_6__);
/* harmony import */ var _lib_utils_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../lib/utils.js */ "./src/lib/utils.js");
@@ -7384,13 +7428,17 @@ class Contact extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component) {
}
}
const subtitle = this.props.preview ? typeof this.props.preview == 'string' ? this.props.preview : react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, tinode_sdk__WEBPACK_IMPORTED_MODULE_5__.Drafty.format(this.props.preview, draftyFormatter, this)) : this.props.comment;
const subtitle = this.props.preview ? typeof this.props.preview == 'string' ? this.props.preview : react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, tinode_sdk__WEBPACK_IMPORTED_MODULE_6__.Drafty.format(this.props.preview, draftyFormatter, this)) : this.props.comment;
const icon = (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_7__.deliveryMarker)(this.props.received);
const marker = icon ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: 'material-icons small space-right ' + icon.color
}, icon.name) : null;
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", {
className: !this.props.showCheckmark && this.props.selected ? "selected" : null,
className: !this.props.showCheckmark && this.props.selected ? 'selected' : null,
onClick: this.handleClick
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "avatar-box"
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_letter_tile_jsx__WEBPACK_IMPORTED_MODULE_2__.default, {
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_letter_tile_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
avatar: avatar,
title: this.props.title,
topic: this.props.item
@@ -7406,13 +7454,13 @@ class Contact extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component) {
src: "/img/channel.png",
className: "channel",
alt: "channel"
}) : null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_unread_badge_jsx__WEBPACK_IMPORTED_MODULE_4__.default, {
}) : null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_unread_badge_jsx__WEBPACK_IMPORTED_MODULE_5__.default, {
count: this.props.unread
}), react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_badges_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
}), react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_badges_jsx__WEBPACK_IMPORTED_MODULE_2__.default, {
badges: icon_badges
})), react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "contact-comment"
}, subtitle || '\u00A0'), react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_badges_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
}, marker, subtitle || '\u00A0'), react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_badges_jsx__WEBPACK_IMPORTED_MODULE_2__.default, {
badges: badges
}))), this.props.showContextMenu ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", {
className: "menuTrigger"
@@ -7428,7 +7476,7 @@ class Contact extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component) {
;
function draftyFormatter(style, data, values, key) {
let el = tinode_sdk__WEBPACK_IMPORTED_MODULE_5__.Drafty.tagName(style);
let el = tinode_sdk__WEBPACK_IMPORTED_MODULE_6__.Drafty.tagName(style);
const attr = {
key: key
};
@@ -9561,6 +9609,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! tinode-sdk */ "tinode-sdk");
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _lib_strformat_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../lib/strformat.js */ "./src/lib/strformat.js");
/* harmony import */ var _lib_utils_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../lib/utils.js */ "./src/lib/utils.js");
@@ -9593,30 +9643,10 @@ class ReceivedMarker extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureC
timestamp = (0,_lib_strformat_js__WEBPACK_IMPORTED_MODULE_3__.shortDateFormat)(this.props.timestamp, this.props.intl.locale);
}
let marker = null;
if (this.props.received <= (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().MESSAGE_STATUS_SENDING)) {
marker = react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: "material-icons small"
}, "access_time");
} else if (this.props.received == (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().MESSAGE_STATUS_FAILED)) {
marker = react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: "material-icons small amber"
}, "warning");
} else if (this.props.received == (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().MESSAGE_STATUS_SENT)) {
marker = react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: "material-icons small"
}, "done");
} else if (this.props.received == (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().MESSAGE_STATUS_RECEIVED)) {
marker = react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: "material-icons small"
}, "done_all");
} else if (this.props.received == (tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default().MESSAGE_STATUS_READ)) {
marker = react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: "material-icons small blue"
}, "done_all");
}
const icon = (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_4__.deliveryMarker)(this.props.received);
const marker = icon ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: 'material-icons small ' + icon.color
}, icon.name) : null;
return react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", {
className: "timestamp"
}, timestamp, '\u00a0', marker);
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long