adding support for delayed removal of deleted topics

This commit is contained in:
or-else
2022-02-19 20:58:35 -08:00
parent 9a811708ba
commit 0598a42164
12 changed files with 3858 additions and 6217 deletions
+20 -1
View File
@@ -1007,6 +1007,10 @@ i.search {
height: 2rem; height: 2rem;
} }
.avatar.disabled {
opacity: 0.5;
}
.contact-box .avatar-box > .material-icons { .contact-box .avatar-box > .material-icons {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -1087,7 +1091,6 @@ img.channel {
width: 1.5rem; width: 1.5rem;
height: 1.5rem; height: 1.5rem;
font-size: 1.5rem; font-size: 1.5rem;
line-height: 1.5rem;
color: #0097A7; color: #0097A7;
position: absolute; position: absolute;
right: 0.05rem; right: 0.05rem;
@@ -1096,6 +1099,18 @@ img.channel {
overflow: visible; overflow: visible;
border: 0.0px solid transparent; border: 0.0px solid transparent;
} }
.contact-box .deleted.material-icons {
width: 1.5rem;
height: 1.5rem;
font-size: 1.5rem;
color: gray;
position: absolute;
right: 0.05rem;
bottom: 0.05rem;
background-color: white;
}
/* END of avatar box */ /* END of avatar box */
#add-topic { #add-topic {
@@ -2013,6 +2028,10 @@ ul.tabbar li.active > a {
color: white; color: white;
} }
.lettertile.disabled {
opacity: 0.5;
}
/* Colors of letter tiles */ /* Colors of letter tiles */
.lt-bg-0 { .lt-bg-0 {
background-color: #ef9a9a; background-color: #ef9a9a;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -2
View File
@@ -1033,7 +1033,6 @@ class MessagesView extends React.Component {
<ChatMessage <ChatMessage
tinode={this.props.tinode} tinode={this.props.tinode}
content={msg.content} content={msg.content}
deleted={msg.hi}
mimeType={msg.head ? msg.head.mime : null} mimeType={msg.head ? msg.head.mime : null}
timestamp={msg.ts} timestamp={msg.ts}
response={isReply} response={isReply}
@@ -1159,7 +1158,7 @@ class MessagesView extends React.Component {
<SendMessage <SendMessage
tinode={this.props.tinode} tinode={this.props.tinode}
noInput={!!this.props.forwardMessage} noInput={!!this.props.forwardMessage}
disabled={!this.state.isWriter} disabled={!this.state.isWriter || topic.deleted}
onKeyPress={this.sendKeyPress} onKeyPress={this.sendKeyPress}
onSendMessage={this.sendMessage} onSendMessage={this.sendMessage}
onAttachFile={this.props.forwardMessage ? null : this.handleAttachFile} onAttachFile={this.props.forwardMessage ? null : this.handleAttachFile}
+1
View File
@@ -115,6 +115,7 @@ class ContactList extends React.Component {
isVerified={c.trusted && c.trusted.verified} isVerified={c.trusted && c.trusted.verified}
isStaff={c.trusted && c.trusted.staff} isStaff={c.trusted && c.trusted.staff}
isDangerous={c.trusted && c.trusted.danger} isDangerous={c.trusted && c.trusted.danger}
deleted={c.deleted}
item={key} item={key}
index={contactNodes.length} index={contactNodes.length}
key={key} /> key={key} />
+6 -5
View File
@@ -4,7 +4,6 @@ import { FormattedMessage, injectIntl } from 'react-intl';
import ContactBadges from './contact-badges.jsx'; import ContactBadges from './contact-badges.jsx';
import LetterTile from './letter-tile.jsx'; import LetterTile from './letter-tile.jsx';
import ReceivedMarker from './received-marker.jsx'
import UnreadBadge from './unread-badge.jsx'; import UnreadBadge from './unread-badge.jsx';
import { Drafty } from 'tinode-sdk'; import { Drafty } from 'tinode-sdk';
@@ -95,11 +94,13 @@ class Contact extends React.Component {
tinode={this.props.tinode} tinode={this.props.tinode}
avatar={avatar} avatar={avatar}
title={this.props.title} title={this.props.title}
topic={this.props.item} /> topic={this.props.item}
{this.props.showOnline ? <span className={online} /> : disabled={this.props.deleted} />
(this.props.showCheckmark && this.props.selected ? {this.props.deleted ? <i className="deleted material-icons">cancel</i> :
this.props.showOnline ? <span className={online} /> :
(this.props.showCheckmark && this.props.selected) ?
<i className="checkmark material-icons">check_circle</i> <i className="checkmark material-icons">check_circle</i>
: null)} : null}
</div> </div>
<div className="text-box"> <div className="text-box">
<div><span className="contact-title">{title}</span> <div><span className="contact-title">{title}</span>
+6 -6
View File
@@ -9,21 +9,21 @@ export default class LetterTile extends React.PureComponent {
render() { render() {
let avatar; let avatar;
if (this.props.avatar === true) { if (this.props.avatar === true) {
const isGroup = (Tinode.topicType(this.props.topic) == 'grp'); const isGroup = Tinode.isGroupTopicName(this.props.topic);
const iconColor = idToColorClass(this.props.topic, isGroup); const iconColor = idToColorClass(this.props.topic, isGroup);
if (this.props.topic && this.props.title && this.props.title.trim()) { if (this.props.topic && this.props.title && this.props.title.trim()) {
const letter = this.props.title.trim().charAt(0); const letter = this.props.title.trim().charAt(0);
const className = 'lettertile ' + iconColor; const className = 'lettertile ' + iconColor + (this.props.disabled ? ' disabled' : '');
avatar = (<div className={className}><div>{letter}</div></div>) avatar = (<div className={className}><div>{letter}</div></div>)
} else { } else {
const className = 'material-icons ' + iconColor; const className = 'material-icons ' + iconColor + (this.props.disabled ? ' disabled' : '');
avatar = isGroup ? avatar = isGroup ? <i className={className}>group</i> : <i className={className}>person</i>;
<i className={className}>group</i> : <i className={className}>person</i>;
} }
} else if (this.props.avatar) { } else if (this.props.avatar) {
const url = this.props.tinode.authorizeURL(sanitizeImageUrl(this.props.avatar)); const url = this.props.tinode.authorizeURL(sanitizeImageUrl(this.props.avatar));
// If avatar image is invalid, show a placeholder. // If avatar image is invalid, show a placeholder.
avatar = <img className="avatar" alt="avatar" src={url} const className = 'avatar' + (this.props.disabled ? ' disabled' : '');
avatar = <img className={className} alt="avatar" src={url}
onError={(e)=>{e.target.onerror = null; e.target.src="../img/broken_image.png"}} />; onError={(e)=>{e.target.onerror = null; e.target.src="../img/broken_image.png"}} />;
} else { } else {
avatar = null; avatar = null;
+21 -19
View File
@@ -4380,7 +4380,6 @@ class MessagesView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
messageNodes.push(react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_chat_message_jsx__WEBPACK_IMPORTED_MODULE_3__["default"], { messageNodes.push(react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_chat_message_jsx__WEBPACK_IMPORTED_MODULE_3__["default"], {
tinode: this.props.tinode, tinode: this.props.tinode,
content: msg.content, content: msg.content,
deleted: msg.hi,
mimeType: msg.head ? msg.head.mime : null, mimeType: msg.head ? msg.head.mime : null,
timestamp: msg.ts, timestamp: msg.ts,
response: isReply, response: isReply,
@@ -4525,7 +4524,7 @@ class MessagesView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
}) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_send_message_jsx__WEBPACK_IMPORTED_MODULE_14__["default"], { }) : react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_widgets_send_message_jsx__WEBPACK_IMPORTED_MODULE_14__["default"], {
tinode: this.props.tinode, tinode: this.props.tinode,
noInput: !!this.props.forwardMessage, noInput: !!this.props.forwardMessage,
disabled: !this.state.isWriter, disabled: !this.state.isWriter || topic.deleted,
onKeyPress: this.sendKeyPress, onKeyPress: this.sendKeyPress,
onSendMessage: this.sendMessage, onSendMessage: this.sendMessage,
onAttachFile: this.props.forwardMessage ? null : this.handleAttachFile, onAttachFile: this.props.forwardMessage ? null : this.handleAttachFile,
@@ -8567,6 +8566,7 @@ class ContactList extends (react__WEBPACK_IMPORTED_MODULE_0___default().Componen
isVerified: c.trusted && c.trusted.verified, isVerified: c.trusted && c.trusted.verified,
isStaff: c.trusted && c.trusted.staff, isStaff: c.trusted && c.trusted.staff,
isDangerous: c.trusted && c.trusted.danger, isDangerous: c.trusted && c.trusted.danger,
deleted: c.deleted,
item: key, item: key,
index: contactNodes.length, index: contactNodes.length,
key: key key: key
@@ -8611,13 +8611,11 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_intl__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_intl__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _contact_badges_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./contact-badges.jsx */ "./src/widgets/contact-badges.jsx"); /* 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 _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_4__ = __webpack_require__(/*! ./unread-badge.jsx */ "./src/widgets/unread-badge.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_5__ = __webpack_require__(/*! tinode-sdk */ "tinode-sdk");
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_6__ = __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 tinode_sdk__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var _lib_formatters_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../lib/formatters.js */ "./src/lib/formatters.js");
/* harmony import */ var _lib_formatters_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../lib/formatters.js */ "./src/lib/formatters.js"); /* harmony import */ var _lib_utils_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../lib/utils.js */ "./src/lib/utils.js");
/* harmony import */ var _lib_utils_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../lib/utils.js */ "./src/lib/utils.js");
@@ -8719,8 +8717,8 @@ class Contact extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component) {
if (typeof this.props.preview == 'string') { if (typeof this.props.preview == 'string') {
preview = this.props.preview; preview = this.props.preview;
} else if (tinode_sdk__WEBPACK_IMPORTED_MODULE_6__.Drafty.isValid(this.props.preview)) { } else if (tinode_sdk__WEBPACK_IMPORTED_MODULE_5__.Drafty.isValid(this.props.preview)) {
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, _lib_formatters_js__WEBPACK_IMPORTED_MODULE_7__.previewFormatter, { 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, _lib_formatters_js__WEBPACK_IMPORTED_MODULE_6__.previewFormatter, {
formatMessage: this.props.intl.formatMessage formatMessage: this.props.intl.formatMessage
})); }));
} else if (this.props.preview) { } else if (this.props.preview) {
@@ -8737,7 +8735,7 @@ class Contact extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component) {
}))); })));
} }
const icon = (0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_8__.deliveryMarker)(this.props.received); 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", { const marker = icon ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: 'material-icons small space-right' + (icon.color ? ' ' + icon.color : '') className: 'material-icons small space-right' + (icon.color ? ' ' + icon.color : '')
}, icon.name) : null; }, icon.name) : null;
@@ -8750,8 +8748,11 @@ class Contact extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component) {
tinode: this.props.tinode, tinode: this.props.tinode,
avatar: avatar, avatar: avatar,
title: this.props.title, title: this.props.title,
topic: this.props.item topic: this.props.item,
}), this.props.showOnline ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { disabled: this.props.deleted
}), this.props.deleted ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: "deleted material-icons"
}, "cancel") : this.props.showOnline ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", {
className: online className: online
}) : this.props.showCheckmark && this.props.selected ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", { }) : this.props.showCheckmark && this.props.selected ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: "checkmark material-icons" className: "checkmark material-icons"
@@ -8765,7 +8766,7 @@ class Contact extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component) {
alt: "channel" alt: "channel"
}) : null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_badges_jsx__WEBPACK_IMPORTED_MODULE_2__["default"], { }) : null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_badges_jsx__WEBPACK_IMPORTED_MODULE_2__["default"], {
badges: icon_badges badges: icon_badges
}), react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_unread_badge_jsx__WEBPACK_IMPORTED_MODULE_5__["default"], { }), react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_unread_badge_jsx__WEBPACK_IMPORTED_MODULE_4__["default"], {
count: this.props.unread count: this.props.unread
})), this.props.showMode ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null, react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_contact_badges_jsx__WEBPACK_IMPORTED_MODULE_2__["default"], { })), this.props.showMode ? 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 badges: badges
@@ -10776,17 +10777,17 @@ class LetterTile extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompo
let avatar; let avatar;
if (this.props.avatar === true) { if (this.props.avatar === true) {
const isGroup = tinode_sdk__WEBPACK_IMPORTED_MODULE_1___default().topicType(this.props.topic) == 'grp'; const isGroup = tinode_sdk__WEBPACK_IMPORTED_MODULE_1___default().isGroupTopicName(this.props.topic);
const iconColor = (0,_lib_strformat_js__WEBPACK_IMPORTED_MODULE_2__.idToColorClass)(this.props.topic, isGroup); const iconColor = (0,_lib_strformat_js__WEBPACK_IMPORTED_MODULE_2__.idToColorClass)(this.props.topic, isGroup);
if (this.props.topic && this.props.title && this.props.title.trim()) { if (this.props.topic && this.props.title && this.props.title.trim()) {
const letter = this.props.title.trim().charAt(0); const letter = this.props.title.trim().charAt(0);
const className = 'lettertile ' + iconColor; const className = 'lettertile ' + iconColor + (this.props.disabled ? ' disabled' : '');
avatar = react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { avatar = react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: className className: className
}, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, letter)); }, react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, letter));
} else { } else {
const className = 'material-icons ' + iconColor; const className = 'material-icons ' + iconColor + (this.props.disabled ? ' disabled' : '');
avatar = isGroup ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", { avatar = isGroup ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
className: className className: className
}, "group") : react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", { }, "group") : react__WEBPACK_IMPORTED_MODULE_0___default().createElement("i", {
@@ -10795,8 +10796,9 @@ class LetterTile extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCompo
} }
} else if (this.props.avatar) { } else if (this.props.avatar) {
const url = this.props.tinode.authorizeURL((0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_3__.sanitizeImageUrl)(this.props.avatar)); const url = this.props.tinode.authorizeURL((0,_lib_utils_js__WEBPACK_IMPORTED_MODULE_3__.sanitizeImageUrl)(this.props.avatar));
const className = 'avatar' + (this.props.disabled ? ' disabled' : '');
avatar = react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", { avatar = react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", {
className: "avatar", className: className,
alt: "avatar", alt: "avatar",
src: url, src: url,
onError: e => { onError: e => {
+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
+3798 -6179
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