kind of works, no crashes, but inefficient and not everything is refreshed
This commit is contained in:
@@ -89,6 +89,7 @@ export default class ContactsView extends React.Component {
|
||||
defaultMessage="You have no chats<br />¯∖_(ツ)_/¯"
|
||||
description="HTML message shown in ContactList when no contacts are found">{
|
||||
(no_contacts) => <ContactList
|
||||
tinode={this.props.tinode}
|
||||
connected={this.props.connected}
|
||||
contacts={this.state.contactList}
|
||||
emptyListMessage={no_contacts}
|
||||
|
||||
@@ -429,6 +429,7 @@ class InfoView extends React.Component {
|
||||
onClearError={this.props.onError} /> : null}
|
||||
{view == 'members' ?
|
||||
<GroupManager
|
||||
tinode={this.props.tinode}
|
||||
members={this.state.contactList}
|
||||
requiredMember={this.props.myUserId}
|
||||
keepInitialMembers={!this.state.admin && !this.state.owner}
|
||||
@@ -439,6 +440,7 @@ class InfoView extends React.Component {
|
||||
:
|
||||
view == 'perm' && args.length > 0 ?
|
||||
<PermissionsEditor
|
||||
tinode={this.props.tinode}
|
||||
mode={this.state.editedPermissions}
|
||||
compare={this.state.immutablePermissions}
|
||||
skip={this.state.editedPermissionsSkipped}
|
||||
@@ -559,6 +561,7 @@ class InfoView extends React.Component {
|
||||
<FormattedMessage id="group_has_no_members" defaultMessage="No members"
|
||||
description="Shown in place of group members">{
|
||||
(no_members) => <ContactList
|
||||
tinode={this.props.tinode}
|
||||
contacts={this.state.contactList}
|
||||
myUserId={this.props.myUserId}
|
||||
emptyListMessage={no_members}
|
||||
|
||||
@@ -931,6 +931,7 @@ class MessagesView extends React.Component {
|
||||
null}
|
||||
<div className="avatar-box">
|
||||
<LetterTile
|
||||
tinode={this.props.tinode}
|
||||
avatar={avatar}
|
||||
topic={this.state.topic}
|
||||
title={this.state.title} />
|
||||
@@ -946,6 +947,7 @@ class MessagesView extends React.Component {
|
||||
</div>
|
||||
{groupTopic ?
|
||||
<GroupSubs
|
||||
tinode={this.props.tinode}
|
||||
subscribers={this.state.onlineSubs} /> :
|
||||
<div id="topic-users" />
|
||||
}
|
||||
|
||||
@@ -1214,10 +1214,11 @@ class TinodeWeb extends React.Component {
|
||||
const topic = this.tinode.getTopic(topicName);
|
||||
if (topic) {
|
||||
const params = {};
|
||||
let attachments;
|
||||
if (pub) {
|
||||
params.public = pub;
|
||||
if (pub.photo && pub.photo.ref) {
|
||||
params.attachments = [pub.photo.ref];
|
||||
attachments = [pub.photo.ref];
|
||||
}
|
||||
}
|
||||
if (priv) {
|
||||
@@ -1227,7 +1228,7 @@ class TinodeWeb extends React.Component {
|
||||
if (defacs) {
|
||||
params.defacs = defacs;
|
||||
}
|
||||
topic.setMeta({desc: params}).catch((err) => {
|
||||
topic.setMeta({desc: params, attachments: attachments}).catch((err) => {
|
||||
this.handleError(err.message, 'err');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ export default class AvatarUpload extends React.Component {
|
||||
this.props.readOnly && this.props.uid ?
|
||||
<div className="avatar-box">
|
||||
<LetterTile
|
||||
tinode={this.props.tinode}
|
||||
avatar={true}
|
||||
topic={this.props.uid}
|
||||
title={this.props.title} />
|
||||
|
||||
@@ -120,6 +120,7 @@ export default class ChatMessage extends React.Component {
|
||||
<div className="avatar-box">
|
||||
{fullDisplay ?
|
||||
<LetterTile
|
||||
tinode={this.props.tinode}
|
||||
topic={this.props.userFrom}
|
||||
title={this.props.userName}
|
||||
avatar={avatar} /> :
|
||||
|
||||
@@ -118,6 +118,7 @@ export default class ChipInput extends React.Component {
|
||||
this.state.sortedChips.map((item) => {
|
||||
chips.push(
|
||||
<Chip
|
||||
tinode={this.props.tinode}
|
||||
onCancel={this.handleChipCancel}
|
||||
avatar={makeImageUrl(item.public ? item.public.photo : null)}
|
||||
title={item.public ? item.public.fn : undefined}
|
||||
|
||||
@@ -23,6 +23,7 @@ export default class Chip extends React.PureComponent {
|
||||
<span className="spacer" /> :
|
||||
<div className="avatar-box">
|
||||
<LetterTile
|
||||
tinode={this.props.tinode}
|
||||
avatar={this.props.avatar || true}
|
||||
topic={this.props.topic}
|
||||
title={this.props.title} />
|
||||
|
||||
@@ -89,6 +89,7 @@ class ContactList extends React.Component {
|
||||
}
|
||||
contactNodes.push(
|
||||
<Contact
|
||||
tinode={this.props.tinode}
|
||||
title={c.public ? c.public.fn : null}
|
||||
avatar={makeImageUrl(c.public ? c.public.photo : null)}
|
||||
comment={comment}
|
||||
|
||||
@@ -99,6 +99,7 @@ class Contact extends React.Component {
|
||||
<li className={!this.props.showCheckmark && this.props.selected ? 'selected' : null} onClick={this.handleClick}>
|
||||
<div className="avatar-box">
|
||||
<LetterTile
|
||||
tinode={this.props.tinode}
|
||||
avatar={avatar}
|
||||
title={this.props.title}
|
||||
topic={this.props.item} />
|
||||
|
||||
@@ -165,6 +165,7 @@ class GroupManager extends React.Component {
|
||||
</div>
|
||||
<div className="panel-form-row">
|
||||
<ChipInput
|
||||
tinode={this.props.tinode}
|
||||
chips={this.state.members}
|
||||
staticMembers={this.state.staticMembers}
|
||||
prompt="add members"
|
||||
@@ -178,6 +179,7 @@ class GroupManager extends React.Component {
|
||||
</label>
|
||||
</div>
|
||||
<ContactList
|
||||
tinode={this.props.tinode}
|
||||
contacts={this.props.contacts}
|
||||
myUserId={this.props.myUserId}
|
||||
topicSelected={this.state.selectedContacts}
|
||||
|
||||
@@ -22,6 +22,7 @@ export default class GroupSubs extends React.Component {
|
||||
usersOnline.push(
|
||||
<div className="avatar-box" key={sub.user}>
|
||||
<LetterTile
|
||||
tinode={this.props.tinode}
|
||||
topic={sub.user}
|
||||
avatar={makeImageUrl(sub.public ? sub.public.photo : null) || true}
|
||||
title={sub.public ? sub.public.fn : null} />
|
||||
|
||||
@@ -3,6 +3,7 @@ import React from 'react';
|
||||
import Tinode from 'tinode-sdk';
|
||||
|
||||
import { stringHash } from '../lib/strformat.js';
|
||||
import { sanitizeImageUrl } from '../lib/utils.js';
|
||||
|
||||
export default class LetterTile extends React.PureComponent {
|
||||
render() {
|
||||
@@ -21,8 +22,9 @@ export default class LetterTile extends React.PureComponent {
|
||||
<i className={className}>group</i> : <i className={className}>person</i>;
|
||||
}
|
||||
} else if (this.props.avatar) {
|
||||
const url = this.props.tinode.authorizeURL(sanitizeImageUrl(this.props.avatar));
|
||||
// If avatar image is invalid, show a placeholder.
|
||||
avatar = <img className="avatar" alt="avatar" src={this.props.avatar}
|
||||
avatar = <img className="avatar" alt="avatar" src={url}
|
||||
onError={(e)=>{e.target.onerror = null; e.target.src="../img/broken_image.png"}} />;
|
||||
} else {
|
||||
avatar = null;
|
||||
|
||||
@@ -118,10 +118,10 @@ export default class NewTopicGroup extends React.PureComponent {
|
||||
<FormattedMessage id="title_tag_manager" defaultMessage="Tags (search & discovery)"
|
||||
description="Section title for TagManager">{
|
||||
(title) => <TagManager
|
||||
tinode={this.props.tinode}
|
||||
tags={this.state.tags}
|
||||
activated={true}
|
||||
onTagsChanged={this.handleTagsChanged}
|
||||
tinode={this.props.tinode}
|
||||
tabIndex={4}
|
||||
title={title} />
|
||||
}</FormattedMessage>
|
||||
|
||||
@@ -133,6 +133,7 @@ class PermissionsEditor extends React.Component {
|
||||
<div className="panel-form-column">
|
||||
{this.props.userTitle ?
|
||||
<ul className="contact-box small"><Contact
|
||||
tinode={this.props.tinode}
|
||||
item={this.props.item}
|
||||
title={this.props.userTitle}
|
||||
small={true}
|
||||
|
||||
@@ -26,6 +26,7 @@ export default class SideNavbar extends React.PureComponent {
|
||||
{avatar ?
|
||||
<div id="self-avatar" className="avatar-box">
|
||||
<LetterTile
|
||||
tinode={this.props.tinode}
|
||||
avatar={avatar}
|
||||
topic={this.props.myUserId}
|
||||
title={this.props.title} />
|
||||
|
||||
@@ -12,7 +12,7 @@ export default class TagManager extends React.Component {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
tags: this.props.tags,
|
||||
tags: this.props.tags || [],
|
||||
tagInput: '',
|
||||
activated: this.props.activated
|
||||
};
|
||||
@@ -25,8 +25,9 @@ export default class TagManager extends React.Component {
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (!arrayEqual(nextProps.tags, prevState.tags) && !prevState.activated) {
|
||||
return {tags: nextProps.tags};
|
||||
const tags = nextProps.tags || [];
|
||||
if (!arrayEqual(tags, prevState.tags) && !prevState.activated) {
|
||||
return {tags: tags};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -75,11 +76,11 @@ export default class TagManager extends React.Component {
|
||||
handleSubmit() {
|
||||
// Add unprocessed input to tags, submit the list.
|
||||
this.props.onSubmit(this.handleAddTag(this.state.tagInput.trim()));
|
||||
this.setState({activated: false, tags: this.props.tags});
|
||||
this.setState({activated: false, tags: this.props.tags || []});
|
||||
}
|
||||
|
||||
handleCancel() {
|
||||
this.setState({activated: false, tagInput: '', tags: this.props.tags});
|
||||
this.setState({activated: false, tagInput: '', tags: this.props.tags || []});
|
||||
if (this.props.onCancel) {
|
||||
this.props.onCancel();
|
||||
}
|
||||
@@ -116,6 +117,7 @@ export default class TagManager extends React.Component {
|
||||
<FormattedMessage id="tags_editor_no_tags" defaultMessage="Add some tags"
|
||||
description="Tag editor prompt when no tags are found.">{
|
||||
(add_tags_prompt) => <ChipInput
|
||||
tinode={this.props.tinode}
|
||||
chips={tags}
|
||||
avatarDisabled={true}
|
||||
prompt={add_tags_prompt}
|
||||
|
||||
@@ -265,10 +265,10 @@ export default class TopicDescEdit extends React.Component {
|
||||
<FormattedMessage id="title_tag_manager" defaultMessage="Tags (search & discovery)"
|
||||
description="Section title for TagManager">{
|
||||
(title_tag_manager) => <TagManager
|
||||
tinode={this.props.tinode}
|
||||
title={title_tag_manager}
|
||||
activated={false}
|
||||
tags={this.state.tags}
|
||||
tinode={this.props.tinode}
|
||||
onSubmit={this.handleTagsUpdated} />
|
||||
}</FormattedMessage>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user