archiving kind of works but buggy
This commit is contained in:
+3
-2
@@ -777,8 +777,9 @@ i.search {
|
|||||||
|
|
||||||
.contact-box .action-text {
|
.contact-box .action-text {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.05rem;
|
font-size: 0.95rem;
|
||||||
margin: 0.5rem auto 0.5rem auto;
|
line-height: 3.5rem;
|
||||||
|
margin: 0 auto 0 auto;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"archived_contacts": "Archived contacts ({count})",
|
"archived_contacts": "Archived contacts ({count})",
|
||||||
|
"contacts_not_found": "You have no chats<br />¯∖_(ツ)_/¯",
|
||||||
"full_name_prompt": "Full name, e.g. John Doe",
|
"full_name_prompt": "Full name, e.g. John Doe",
|
||||||
"email_prompt": "Email, e.g. jdoe@example.com",
|
"email_prompt": "Email, e.g. jdoe@example.com",
|
||||||
"button_sign_up": "Sign up",
|
"button_sign_up": "Sign up",
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"contacts_not_found": ":!![OBSOLETE]!!:Чатов нет<br />¯∖_(ツ)_/¯",
|
"contacts_not_found": "Чатов нет<br />¯∖_(ツ)_/¯",
|
||||||
"full_name_prompt": "Полное имя, напр. Иван Петров",
|
"full_name_prompt": "Полное имя, напр. Иван Петров",
|
||||||
"email_prompt": "Email, напр. ivan@example.com",
|
"email_prompt": "Email, напр. ivan@example.com",
|
||||||
"button_sign_up": "Создать счет",
|
"button_sign_up": "Создать счет",
|
||||||
@@ -125,5 +125,5 @@
|
|||||||
"save_attachment": "сохранить",
|
"save_attachment": "сохранить",
|
||||||
"menu_item_archive_topic": "В архив",
|
"menu_item_archive_topic": "В архив",
|
||||||
"archived_contacts": "Чаты в архиве ({count})",
|
"archived_contacts": "Чаты в архиве ({count})",
|
||||||
"sidepanel_title_archive": "Архив"
|
"sidepanel_title_archive": "Архив чатов"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"en": {
|
"en": {
|
||||||
"archived_contacts": "Archived contacts ({count})",
|
"archived_contacts": "Archived contacts ({count})",
|
||||||
|
"contacts_not_found": "You have no chats<br />¯∖_(ツ)_/¯",
|
||||||
"full_name_prompt": "Full name, e.g. John Doe",
|
"full_name_prompt": "Full name, e.g. John Doe",
|
||||||
"email_prompt": "Email, e.g. jdoe@example.com",
|
"email_prompt": "Email, e.g. jdoe@example.com",
|
||||||
"button_sign_up": "Sign up",
|
"button_sign_up": "Sign up",
|
||||||
@@ -128,6 +129,7 @@
|
|||||||
"title_manage_tags": "Manage tags"
|
"title_manage_tags": "Manage tags"
|
||||||
},
|
},
|
||||||
"ru": {
|
"ru": {
|
||||||
|
"contacts_not_found": "Чатов нет<br />¯∖_(ツ)_/¯",
|
||||||
"full_name_prompt": "Полное имя, напр. Иван Петров",
|
"full_name_prompt": "Полное имя, напр. Иван Петров",
|
||||||
"email_prompt": "Email, напр. ivan@example.com",
|
"email_prompt": "Email, напр. ivan@example.com",
|
||||||
"button_sign_up": "Создать счет",
|
"button_sign_up": "Создать счет",
|
||||||
|
|||||||
+34
-14
@@ -1,46 +1,69 @@
|
|||||||
/* ContactsView holds all contacts-related stuff */
|
/* ContactsView holds all contacts-related stuff */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedHTMLMessage } from 'react-intl';
|
import { FormattedHTMLMessage, defineMessages } from 'react-intl';
|
||||||
|
|
||||||
import ContactList from '../widgets/contact-list.jsx';
|
import ContactList from '../widgets/contact-list.jsx';
|
||||||
|
|
||||||
import { updateFavicon } from '../lib/utils.js';
|
import { updateFavicon } from '../lib/utils.js';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
archived_contacts_title: {
|
||||||
|
id: "archived_contacts",
|
||||||
|
defaultMessage: "Archived contacts ({count})",
|
||||||
|
description: "Label for archived chats"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default class ContactsView extends React.Component {
|
export default class ContactsView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
this.handleAction = this.handleAction.bind(this);
|
||||||
|
|
||||||
this.state = ContactsView.getDerivedStateFromProps(props, {});
|
this.state = ContactsView.getDerivedStateFromProps(props, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDerivedStateFromProps(nextProps, prevState) {
|
static getDerivedStateFromProps(nextProps, prevState) {
|
||||||
console.log(nextProps.archive ? "show archive" : "show active");
|
const contacts = [];
|
||||||
let contacts = [];
|
|
||||||
let unreadThreads = 0;
|
let unreadThreads = 0;
|
||||||
let archivedCount = 0;
|
let archivedCount = 0;
|
||||||
nextProps.chatList.map((c) => {
|
nextProps.chatList.map((c) => {
|
||||||
if (c.private && c.private.arch) {
|
if (c.private && c.private.arch) {
|
||||||
console.log("Archived topic", c);
|
if (nextProps.archive) {
|
||||||
|
contacts.push(c);
|
||||||
|
} else {
|
||||||
archivedCount ++;
|
archivedCount ++;
|
||||||
}
|
}
|
||||||
unreadThreads += c.unread > 0 ? 1 : 0;
|
} else if (!nextProps.archive) {
|
||||||
contacts.push(c);
|
contacts.push(c);
|
||||||
|
unreadThreads += c.unread > 0 ? 1 : 0;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
contacts.sort(function(a, b){
|
contacts.sort(function(a, b) {
|
||||||
return (b.touched || 0) - (a.touched || 0);
|
return (b.touched || 0) - (a.touched || 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (archivedCount > 0) {
|
||||||
|
contacts.push({
|
||||||
|
action: 'archive',
|
||||||
|
title: messages.archived_contacts_title,
|
||||||
|
values: {count: archivedCount}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
updateFavicon(unreadThreads);
|
updateFavicon(unreadThreads);
|
||||||
|
|
||||||
return {contactList: contacts, archivedCount: archivedCount};
|
return {contactList: contacts, archivedCount: archivedCount};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleAction(action) {
|
||||||
|
this.props.onShowArchive();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const archivedCount = this.state.archivedCount;
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
|
||||||
<FormattedHTMLMessage id="contacts_not_found"
|
<FormattedHTMLMessage id="contacts_not_found"
|
||||||
defaultMesage="You have no chats<br />¯∖_(ツ)_/¯"
|
defaultMessage="You have no chats<br />¯∖_(ツ)_/¯"
|
||||||
description="HTML message shown in ContactList when no contacts are found">{
|
description="HTML message shown in ContactList when no contacts are found">{
|
||||||
(no_contacts) => <ContactList
|
(no_contacts) => <ContactList
|
||||||
connected={this.props.connected}
|
connected={this.props.connected}
|
||||||
@@ -51,12 +74,9 @@ export default class ContactsView extends React.Component {
|
|||||||
showOnline={true}
|
showOnline={true}
|
||||||
showUnread={true}
|
showUnread={true}
|
||||||
onTopicSelected={this.props.onTopicSelected}
|
onTopicSelected={this.props.onTopicSelected}
|
||||||
showContextMenu={this.props.showContextMenu} />
|
showContextMenu={this.props.showContextMenu}
|
||||||
|
onAction={this.handleAction} />
|
||||||
}</FormattedHTMLMessage>
|
}</FormattedHTMLMessage>
|
||||||
{archivedCount > 0 ? <FormattedMessage id="archived_contacts"
|
|
||||||
defaultMessage="Archived contacts ({count})"
|
|
||||||
description="Label for archived chats" values={{count: archivedCount}}/> : null}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ class InfoView extends React.Component {
|
|||||||
|
|
||||||
// No need to separately handle component mount.
|
// No need to separately handle component mount.
|
||||||
componentDidUpdate(props) {
|
componentDidUpdate(props) {
|
||||||
let topic = this.props.tinode.getTopic(props.topic);
|
const topic = this.props.tinode.getTopic(props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ class InfoView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
var topic = this.props.tinode.getTopic(this.props.topic);
|
const topic = this.props.tinode.getTopic(this.props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -185,7 +185,7 @@ class InfoView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMetaDesc(desc) {
|
onMetaDesc(desc) {
|
||||||
var topic = this.props.tinode.getTopic(this.props.topic);
|
const topic = this.props.tinode.getTopic(this.props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -197,7 +197,7 @@ class InfoView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSubsUpdated() {
|
onSubsUpdated() {
|
||||||
var topic = this.props.tinode.getTopic(this.props.topic);
|
const topic = this.props.tinode.getTopic(this.props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const messages = defineMessages({
|
|||||||
'archive': {
|
'archive': {
|
||||||
id: 'sidepanel_title_archive',
|
id: 'sidepanel_title_archive',
|
||||||
description: 'Sidepanel title for ContactsView-Archive.',
|
description: 'Sidepanel title for ContactsView-Archive.',
|
||||||
defaultMessage: 'Archived'
|
defaultMessage: 'Archived Chats'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -148,7 +148,8 @@ class SidepanelView extends React.Component {
|
|||||||
archive={view == 'archive'}
|
archive={view == 'archive'}
|
||||||
chatList={this.props.chatList}
|
chatList={this.props.chatList}
|
||||||
showContextMenu={this.props.showContextMenu}
|
showContextMenu={this.props.showContextMenu}
|
||||||
onTopicSelected={this.props.onTopicSelected} /> :
|
onTopicSelected={this.props.onTopicSelected}
|
||||||
|
onShowArchive={this.props.onShowArchive} /> :
|
||||||
|
|
||||||
view === 'newtpk' ?
|
view === 'newtpk' ?
|
||||||
<NewTopicView
|
<NewTopicView
|
||||||
|
|||||||
+17
-10
@@ -80,6 +80,7 @@ class TinodeWeb extends React.Component {
|
|||||||
this.handleUpdateAccountTagsRequest = this.handleUpdateAccountTagsRequest.bind(this);
|
this.handleUpdateAccountTagsRequest = this.handleUpdateAccountTagsRequest.bind(this);
|
||||||
this.handleSettings = this.handleSettings.bind(this);
|
this.handleSettings = this.handleSettings.bind(this);
|
||||||
this.handleGlobalSettings = this.handleGlobalSettings.bind(this);
|
this.handleGlobalSettings = this.handleGlobalSettings.bind(this);
|
||||||
|
this.handleShowArchive = this.handleShowArchive.bind(this);
|
||||||
this.handleToggleMessageSounds = this.handleToggleMessageSounds.bind(this);
|
this.handleToggleMessageSounds = this.handleToggleMessageSounds.bind(this);
|
||||||
this.initDesktopAlerts = this.initDesktopAlerts.bind(this);
|
this.initDesktopAlerts = this.initDesktopAlerts.bind(this);
|
||||||
this.togglePushToken = this.togglePushToken.bind(this);
|
this.togglePushToken = this.togglePushToken.bind(this);
|
||||||
@@ -106,7 +107,7 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBlankState() {
|
getBlankState() {
|
||||||
let settings = LocalStorageUtil.getObject("settings") || {};
|
const settings = LocalStorageUtil.getObject("settings") || {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
connected: false,
|
connected: false,
|
||||||
@@ -206,10 +207,10 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let token = LocalStorageUtil.getObject('keep-logged-in') ?
|
const token = LocalStorageUtil.getObject('keep-logged-in') ?
|
||||||
LocalStorageUtil.getObject('auth-token') : undefined;
|
LocalStorageUtil.getObject('auth-token') : undefined;
|
||||||
|
|
||||||
let parsedNav = HashNavigation.parseUrlHash(window.location.hash);
|
const parsedNav = HashNavigation.parseUrlHash(window.location.hash);
|
||||||
if (token) {
|
if (token) {
|
||||||
// When reading from storage, date is returned as string.
|
// When reading from storage, date is returned as string.
|
||||||
token.expires = new Date(token.expires);
|
token.expires = new Date(token.expires);
|
||||||
@@ -793,6 +794,12 @@ class TinodeWeb extends React.Component {
|
|||||||
HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, ''));
|
HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User chose 'Archived chats'.
|
||||||
|
handleShowArchive() {
|
||||||
|
HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash,
|
||||||
|
this.state.myUserId ? 'archive' : ''));
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize desktop alerts = push notifications.
|
// Initialize desktop alerts = push notifications.
|
||||||
initDesktopAlerts() {
|
initDesktopAlerts() {
|
||||||
// Google could not be bothered to mention that
|
// Google could not be bothered to mention that
|
||||||
@@ -859,7 +866,7 @@ class TinodeWeb extends React.Component {
|
|||||||
|
|
||||||
// User clicked Cancel button in Setting or Sign Up panel.
|
// User clicked Cancel button in Setting or Sign Up panel.
|
||||||
handleSidepanelCancel() {
|
handleSidepanelCancel() {
|
||||||
var parsed = HashNavigation.parseUrlHash(window.location.hash);
|
const parsed = HashNavigation.parseUrlHash(window.location.hash);
|
||||||
parsed.path[0] = this.state.myUserId ? 'contacts' : '';
|
parsed.path[0] = this.state.myUserId ? 'contacts' : '';
|
||||||
if (parsed.params) {
|
if (parsed.params) {
|
||||||
delete parsed.params.code;
|
delete parsed.params.code;
|
||||||
@@ -877,7 +884,7 @@ class TinodeWeb extends React.Component {
|
|||||||
|
|
||||||
// Request to start a new topic. New P2P topic requires peer's name.
|
// Request to start a new topic. New P2P topic requires peer's name.
|
||||||
handleNewTopicRequest(peerName, pub, priv, tags) {
|
handleNewTopicRequest(peerName, pub, priv, tags) {
|
||||||
var topicName = peerName || this.tinode.newGroupTopicName();
|
const topicName = peerName || this.tinode.newGroupTopicName();
|
||||||
if (!peerName) {
|
if (!peerName) {
|
||||||
this.setState(
|
this.setState(
|
||||||
{newGroupTopicParams: {desc: {public: pub, private: {comment: priv}}, tags: tags}},
|
{newGroupTopicParams: {desc: {public: pub, private: {comment: priv}}, tags: tags}},
|
||||||
@@ -938,9 +945,8 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleTagsUpdated(topicName, tags) {
|
handleTagsUpdated(topicName, tags) {
|
||||||
var topic = this.tinode.getTopic(topicName);
|
const topic = this.tinode.getTopic(topicName);
|
||||||
if (topic) {
|
if (topic) {
|
||||||
var instance = this;
|
|
||||||
topic.setMeta({tags: tags}).catch((err) => {
|
topic.setMeta({tags: tags}).catch((err) => {
|
||||||
this.handleError(err.message, 'err');
|
this.handleError(err.message, 'err');
|
||||||
});
|
});
|
||||||
@@ -962,7 +968,7 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleLeaveUnsubRequest(topicName) {
|
handleLeaveUnsubRequest(topicName) {
|
||||||
var topic = this.tinode.getTopic(topicName);
|
const topic = this.tinode.getTopic(topicName);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -998,7 +1004,7 @@ class TinodeWeb extends React.Component {
|
|||||||
if (topic.isSubscribed()) {
|
if (topic.isSubscribed()) {
|
||||||
subscribed = true;
|
subscribed = true;
|
||||||
|
|
||||||
let acs = topic.getAccessMode();
|
const acs = topic.getAccessMode();
|
||||||
muted = acs && acs.isMuted();
|
muted = acs && acs.isMuted();
|
||||||
blocked = acs && !acs.isJoiner();
|
blocked = acs && !acs.isJoiner();
|
||||||
deleter = acs && acs.isDeleter();
|
deleter = acs && acs.isDeleter();
|
||||||
@@ -1041,7 +1047,7 @@ class TinodeWeb extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var topic = this.tinode.getTopic(topicName);
|
const topic = this.tinode.getTopic(topicName);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1159,6 +1165,7 @@ class TinodeWeb extends React.Component {
|
|||||||
onValidateCredentials={this.handleValidateCredentialsRequest}
|
onValidateCredentials={this.handleValidateCredentialsRequest}
|
||||||
onPasswordResetRequest={this.handlePasswordResetRequest}
|
onPasswordResetRequest={this.handlePasswordResetRequest}
|
||||||
onResetPassword={this.handleResetPassword}
|
onResetPassword={this.handleResetPassword}
|
||||||
|
onShowArchive={this.handleShowArchive}
|
||||||
|
|
||||||
onInitFind={this.tnInitFind}
|
onInitFind={this.tnInitFind}
|
||||||
searchResults={this.state.searchResults}
|
searchResults={this.state.searchResults}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// A panel included into a list of contacts with an action text.
|
||||||
|
import React from 'react';
|
||||||
|
import { injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
class ContactAction extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleClick = this.handleClick.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
this.props.onAction(this.props.action);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {formatMessage} = this.props.intl;
|
||||||
|
return (
|
||||||
|
<li onClick={this.handleClick}>
|
||||||
|
<div className="action-text">{formatMessage(this.props.title, this.props.values)}</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default injectIntl(ContactAction);
|
||||||
@@ -31,7 +31,12 @@ class ContactList extends React.Component {
|
|||||||
this.props.contacts.map((c) => {
|
this.props.contacts.map((c) => {
|
||||||
if (c.action) {
|
if (c.action) {
|
||||||
// Action item
|
// Action item
|
||||||
contactNodes.push(<ContactAction title={c.title} action={c.action} />);
|
contactNodes.push(
|
||||||
|
<ContactAction
|
||||||
|
title={c.title} action={c.action} values={c.values}
|
||||||
|
key={c.action}
|
||||||
|
onAction={this.props.onAction}
|
||||||
|
/>);
|
||||||
} else {
|
} else {
|
||||||
// Normal contact
|
// Normal contact
|
||||||
const key = c.topic ? c.topic : c.user;
|
const key = c.topic ? c.topic : c.user;
|
||||||
|
|||||||
+140
-27
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user