replacing global Tinode object with TindeWeb's state object
This commit is contained in:
+1
-2
@@ -39,9 +39,8 @@
|
|||||||
<!-- core tinode library -->
|
<!-- core tinode library -->
|
||||||
<script src="src/tinode.js"></script>
|
<script src="src/tinode.js"></script>
|
||||||
<!-- the application -->
|
<!-- the application -->
|
||||||
<script type="text/babel" src="src/webapp.js"></script>
|
<script type="text/babel" src="src/webapp.jsx"></script>
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
console.log(Tinode);
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<TinodeWeb />,
|
<TinodeWeb />,
|
||||||
document.getElementById('mountPoint')
|
document.getElementById('mountPoint')
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
"build": "npm run build:babel && npm run build:prod && npm run build:css",
|
"build": "npm run build:babel && npm run build:prod && npm run build:css",
|
||||||
"build:dev": "browserify ./src/index.js --standalone Webapp > ./umd/index.dev.js",
|
"build:dev": "browserify ./src/index.js --standalone Webapp > ./umd/index.dev.js",
|
||||||
"build:prod": "browserify ./src/index.js --standalone Webapp --plugin tinyify > ./umd/index.prod.js",
|
"build:prod": "browserify ./src/index.js --standalone Webapp --plugin tinyify > ./umd/index.prod.js",
|
||||||
"build:babel": "babel ./src/webapp.js --presets react --out-file ./webapp.js",
|
"build:babel": "babel ./src/webapp.jsx --presets react --out-file ./webapp.js",
|
||||||
"build:css": "postcss css/base.css > css/base.min.css",
|
"build:css": "postcss css/base.css > css/base.min.css",
|
||||||
"babel-version": "babel --version"
|
"babel-version": "babel --version"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
// Name of this application, used in the User-Agent
|
// Babel JSX
|
||||||
|
|
||||||
|
// Name of this application, used in the User-Agent.
|
||||||
const APP_NAME = "TinodeWeb/0.15";
|
const APP_NAME = "TinodeWeb/0.15";
|
||||||
|
|
||||||
const KNOWN_HOSTS = {hosted: "api.tinode.co", local: "localhost:6060"};
|
const KNOWN_HOSTS = {hosted: "api.tinode.co", local: "localhost:6060"};
|
||||||
@@ -475,7 +477,7 @@ class ContextMenu extends React.Component {
|
|||||||
"topic_unblock": {title: "Unblock", handler: this.topicPermissionSetter.bind(this, "+J")},
|
"topic_unblock": {title: "Unblock", handler: this.topicPermissionSetter.bind(this, "+J")},
|
||||||
"topic_block": {title: "Block", handler: this.topicPermissionSetter.bind(this, "-J")},
|
"topic_block": {title: "Block", handler: this.topicPermissionSetter.bind(this, "-J")},
|
||||||
"topic_delete": {title: "Delete", handler: (params, errorHandler) => {
|
"topic_delete": {title: "Delete", handler: (params, errorHandler) => {
|
||||||
var topic = Tinode.getTopic(params.topicName);
|
let topic = this.props.tinode.getTopic(params.topicName);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
console.log("Topic not found: ", params.topicName);
|
console.log("Topic not found: ", params.topicName);
|
||||||
return;
|
return;
|
||||||
@@ -489,7 +491,7 @@ class ContextMenu extends React.Component {
|
|||||||
|
|
||||||
"permissions": {title: "Edit permissions", handler: null},
|
"permissions": {title: "Edit permissions", handler: null},
|
||||||
"member_delete": {title: "Remove", handler: (params, errorHandler) => {
|
"member_delete": {title: "Remove", handler: (params, errorHandler) => {
|
||||||
var topic = Tinode.getTopic(params.topicName);
|
let topic = this.props.tinode.getTopic(params.topicName);
|
||||||
if (!topic || !params.user) {
|
if (!topic || !params.user) {
|
||||||
console.log("Topic or user not found: '" + params.topicName + "', '" + params.user + "'");
|
console.log("Topic or user not found: '" + params.topicName + "', '" + params.user + "'");
|
||||||
return;
|
return;
|
||||||
@@ -1618,8 +1620,10 @@ class SidepanelView extends React.Component {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div id="sidepanel" className={this.props.hideSelf ? 'nodisplay' : null}>
|
<div id="sidepanel" className={this.props.hideSelf ? 'nodisplay' : null}>
|
||||||
<SideNavbar state={view}
|
<SideNavbar
|
||||||
title={title} avatar={avatar}
|
state={view}
|
||||||
|
title={title}
|
||||||
|
avatar={avatar}
|
||||||
myUserId={this.props.myUserId}
|
myUserId={this.props.myUserId}
|
||||||
onSignUp={this.props.onSignUp}
|
onSignUp={this.props.onSignUp}
|
||||||
onSettings={this.props.onSettings}
|
onSettings={this.props.onSettings}
|
||||||
@@ -1632,7 +1636,8 @@ class SidepanelView extends React.Component {
|
|||||||
onClearError={this.props.onError} />
|
onClearError={this.props.onError} />
|
||||||
|
|
||||||
{view === 'login' ?
|
{view === 'login' ?
|
||||||
<LoginView login={this.props.login}
|
<LoginView
|
||||||
|
login={this.props.login}
|
||||||
disabled={this.props.loginDisabled}
|
disabled={this.props.loginDisabled}
|
||||||
serverAddress={this.props.serverAddress}
|
serverAddress={this.props.serverAddress}
|
||||||
onLogin={this.handleLoginRequested}
|
onLogin={this.handleLoginRequested}
|
||||||
@@ -1656,6 +1661,8 @@ class SidepanelView extends React.Component {
|
|||||||
|
|
||||||
view === 'edit' ?
|
view === 'edit' ?
|
||||||
<EditAccountView
|
<EditAccountView
|
||||||
|
tinode={this.props.tinode}
|
||||||
|
myUserId={this.props.myUserId}
|
||||||
login={this.props.login}
|
login={this.props.login}
|
||||||
onSubmit={this.props.onUpdateAccount}
|
onSubmit={this.props.onUpdateAccount}
|
||||||
onUpdateTags={this.props.onUpdateAccountTags}
|
onUpdateTags={this.props.onUpdateAccountTags}
|
||||||
@@ -1665,6 +1672,8 @@ class SidepanelView extends React.Component {
|
|||||||
|
|
||||||
view === 'contacts' ?
|
view === 'contacts' ?
|
||||||
<ContactsView
|
<ContactsView
|
||||||
|
tinode={this.props.tinode}
|
||||||
|
myUserId={this.props.myUserId}
|
||||||
connected={this.props.connected}
|
connected={this.props.connected}
|
||||||
topicSelected={this.props.topicSelected}
|
topicSelected={this.props.topicSelected}
|
||||||
showContextMenu={this.props.showContextMenu}
|
showContextMenu={this.props.showContextMenu}
|
||||||
@@ -1741,13 +1750,12 @@ class EditAccountView extends React.Component {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
let me = Tinode.getMeTopic();
|
let me = this.props.tinode.getMeTopic();
|
||||||
let defacs = me.getDefaultAccess();
|
let defacs = me.getDefaultAccess();
|
||||||
let fnd = Tinode.getFndTopic();
|
let fnd = this.props.tinode.getFndTopic();
|
||||||
this.state = {
|
this.state = {
|
||||||
fullName: me.public ? me.public.fn : undefined,
|
fullName: me.public ? me.public.fn : undefined,
|
||||||
avatar: makeImageUrl(me.public ? me.public.photo : null),
|
avatar: makeImageUrl(me.public ? me.public.photo : null),
|
||||||
address: Tinode.getCurrentUserID(),
|
|
||||||
auth: defacs.auth,
|
auth: defacs.auth,
|
||||||
anon: defacs.anon,
|
anon: defacs.anon,
|
||||||
tags: fnd.tags(),
|
tags: fnd.tags(),
|
||||||
@@ -1762,7 +1770,7 @@ class EditAccountView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
let fnd = Tinode.getFndTopic();
|
let fnd = this.props.tinode.getFndTopic();
|
||||||
fnd.onTagsUpdated = this.tnNewTags;
|
fnd.onTagsUpdated = this.tnNewTags;
|
||||||
if (!fnd.isSubscribed()) {
|
if (!fnd.isSubscribed()) {
|
||||||
fnd.subscribe(fnd.startMetaQuery().withLaterDesc().withTags().build()).catch((err) => {
|
fnd.subscribe(fnd.startMetaQuery().withLaterDesc().withTags().build()).catch((err) => {
|
||||||
@@ -1772,7 +1780,7 @@ class EditAccountView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
var fnd = Tinode.getFndTopic();
|
var fnd = this.props.tinode.getFndTopic();
|
||||||
fnd.onTagsUpdated = this.state.previousOnTags;
|
fnd.onTagsUpdated = this.state.previousOnTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1828,7 +1836,7 @@ class EditAccountView extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<AvatarUpload
|
<AvatarUpload
|
||||||
avatar={this.state.avatar}
|
avatar={this.state.avatar}
|
||||||
uid={this.state.address}
|
uid={this.props.myUserId}
|
||||||
title={this.state.fullName}
|
title={this.state.fullName}
|
||||||
onImageChanged={this.handleImageChanged}
|
onImageChanged={this.handleImageChanged}
|
||||||
onError={this.props.onError} />
|
onError={this.props.onError} />
|
||||||
@@ -1841,7 +1849,7 @@ class EditAccountView extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<div className="panel-form-row">
|
<div className="panel-form-row">
|
||||||
<label>Address:</label>
|
<label>Address:</label>
|
||||||
<tt>{this.state.address}</tt>
|
<tt>{this.props.myUserId}</tt>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="small">Default access mode:</label>
|
<label className="small">Default access mode:</label>
|
||||||
@@ -2125,13 +2133,13 @@ class ContactsView extends React.Component {
|
|||||||
this.tnMeSubsUpdated = this.tnMeSubsUpdated.bind(this);
|
this.tnMeSubsUpdated = this.tnMeSubsUpdated.bind(this);
|
||||||
this.resetContactList = this.resetContactList.bind(this);
|
this.resetContactList = this.resetContactList.bind(this);
|
||||||
|
|
||||||
var me = Tinode.getMeTopic();
|
var me = this.props.tinode.getMeTopic();
|
||||||
me.onContactUpdate = this.tnMeContactUpdate;
|
me.onContactUpdate = this.tnMeContactUpdate;
|
||||||
me.onSubsUpdated = this.tnMeSubsUpdated;
|
me.onSubsUpdated = this.tnMeSubsUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
var me = Tinode.getMeTopic();
|
var me = this.props.tinode.getMeTopic();
|
||||||
me.onContactUpdate = undefined;
|
me.onContactUpdate = undefined;
|
||||||
me.onSubsUpdated = undefined;
|
me.onSubsUpdated = undefined;
|
||||||
}
|
}
|
||||||
@@ -2202,21 +2210,20 @@ class ContactsView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prepareContactList() {
|
prepareContactList() {
|
||||||
var instance = this;
|
|
||||||
var contacts = [];
|
var contacts = [];
|
||||||
var unreadThreads = 0;
|
var unreadThreads = 0;
|
||||||
Tinode.getMeTopic().contacts(function(c) {
|
this.props.tinode.getMeTopic().contacts((c) => {
|
||||||
// Force to integers;
|
// Force to integers;
|
||||||
c.seq = ~~c.seq;
|
c.seq = ~~c.seq;
|
||||||
c.read = ~~c.read;
|
c.read = ~~c.read;
|
||||||
c.unread = c.seq - c.read;
|
c.unread = c.seq - c.read;
|
||||||
unreadThreads += c.unread > 0 ? 1 : 0;
|
unreadThreads += c.unread > 0 ? 1 : 0;
|
||||||
contacts.push(c);
|
contacts.push(c);
|
||||||
if (instance.props.topicSelected == c.topic) {
|
if (this.props.topicSelected == c.topic) {
|
||||||
instance.props.onOnlineChange(c.online);
|
this.props.onOnlineChange(c.online);
|
||||||
instance.props.onAcsChange(c.acs);
|
this.props.onAcsChange(c.acs);
|
||||||
}
|
}
|
||||||
}, this);
|
});
|
||||||
contacts.sort(function(a,b){
|
contacts.sort(function(a,b){
|
||||||
return b.touched - a.touched;
|
return b.touched - a.touched;
|
||||||
});
|
});
|
||||||
@@ -2235,6 +2242,7 @@ class ContactsView extends React.Component {
|
|||||||
contacts={this.state.contactList}
|
contacts={this.state.contactList}
|
||||||
emptyListMessage={<span>You have no chats<br />¯\_(ツ)_/¯</span>}
|
emptyListMessage={<span>You have no chats<br />¯\_(ツ)_/¯</span>}
|
||||||
topicSelected={this.props.topicSelected}
|
topicSelected={this.props.topicSelected}
|
||||||
|
myUserId={this.props.myUserId}
|
||||||
showOnline={true}
|
showOnline={true}
|
||||||
showUnread={true}
|
showUnread={true}
|
||||||
onTopicSelected={this.props.onTopicSelected}
|
onTopicSelected={this.props.onTopicSelected}
|
||||||
@@ -2248,7 +2256,6 @@ class ContactsView extends React.Component {
|
|||||||
* such as a list of group members in a group chat */
|
* such as a list of group members in a group chat */
|
||||||
class ContactList extends React.Component {
|
class ContactList extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
var me = Tinode.getCurrentUserID();
|
|
||||||
var contactNodes = [];
|
var contactNodes = [];
|
||||||
var showCheckmark = Array.isArray(this.props.topicSelected);
|
var showCheckmark = Array.isArray(this.props.topicSelected);
|
||||||
if (this.props.contacts && this.props.contacts.length > 0) {
|
if (this.props.contacts && this.props.contacts.length > 0) {
|
||||||
@@ -2274,7 +2281,7 @@ class ContactList extends React.Component {
|
|||||||
(this.props.topicSelected === key);
|
(this.props.topicSelected === key);
|
||||||
var badges = [];
|
var badges = [];
|
||||||
if (this.props.showMode) {
|
if (this.props.showMode) {
|
||||||
if (key === me) {
|
if (key === this.props.myUserId) {
|
||||||
badges.push({name: 'you', color: 'green'});
|
badges.push({name: 'you', color: 'green'});
|
||||||
}
|
}
|
||||||
if (c.acs && c.acs.isOwner()) {
|
if (c.acs && c.acs.isOwner()) {
|
||||||
@@ -2465,6 +2472,7 @@ class GroupManager extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<ContactList
|
<ContactList
|
||||||
contacts={this.props.contacts}
|
contacts={this.props.contacts}
|
||||||
|
myUserId={this.props.myUserId}
|
||||||
topicSelected={this.state.selectedContacts}
|
topicSelected={this.state.selectedContacts}
|
||||||
filter={this.state.contactFilter}
|
filter={this.state.contactFilter}
|
||||||
filterFunc={GroupManager.doContactFiltering}
|
filterFunc={GroupManager.doContactFiltering}
|
||||||
@@ -2559,6 +2567,7 @@ class NewTopicView extends React.Component {
|
|||||||
onSearchContacts={this.props.onSearchContacts} />
|
onSearchContacts={this.props.onSearchContacts} />
|
||||||
<ContactList
|
<ContactList
|
||||||
contacts={this.state.contactList}
|
contacts={this.state.contactList}
|
||||||
|
myUserId={this.props.myUserId}
|
||||||
emptyListMessage="Use search to find contacts"
|
emptyListMessage="Use search to find contacts"
|
||||||
topicSelected={this.state.selectedContact}
|
topicSelected={this.state.selectedContact}
|
||||||
showOnline={false}
|
showOnline={false}
|
||||||
@@ -2888,7 +2897,7 @@ class InfoView extends React.Component {
|
|||||||
|
|
||||||
// No need to separately handle component mount.
|
// No need to separately handle component mount.
|
||||||
UNSAFE_componentWillReceiveProps(props) {
|
UNSAFE_componentWillReceiveProps(props) {
|
||||||
var topic = Tinode.getTopic(props.topic);
|
var topic = this.props.tinode.getTopic(props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2916,7 +2925,7 @@ class InfoView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
var topic = Tinode.getTopic(this.props.topic);
|
var topic = this.props.tinode.getTopic(this.props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2974,7 +2983,7 @@ class InfoView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMetaDesc(desc) {
|
onMetaDesc(desc) {
|
||||||
var topic = Tinode.getTopic(this.props.topic);
|
var topic = this.props.tinode.getTopic(this.props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2986,7 +2995,7 @@ class InfoView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSubsUpdated() {
|
onSubsUpdated() {
|
||||||
var topic = Tinode.getTopic(this.props.topic);
|
var topic = this.props.tinode.getTopic(this.props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3087,7 +3096,7 @@ class InfoView extends React.Component {
|
|||||||
toSkip = 'O';
|
toSkip = 'O';
|
||||||
break;
|
break;
|
||||||
case 'user': {
|
case 'user': {
|
||||||
var topic = Tinode.getTopic(this.props.topic);
|
var topic = this.props.tinode.getTopic(this.props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3161,7 +3170,7 @@ class InfoView extends React.Component {
|
|||||||
|
|
||||||
handleContextMenu(params) {
|
handleContextMenu(params) {
|
||||||
var instance = this;
|
var instance = this;
|
||||||
var topic = Tinode.getTopic(this.props.topic);
|
var topic = this.props.tinode.getTopic(this.props.topic);
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3203,6 +3212,7 @@ class InfoView extends React.Component {
|
|||||||
<GroupManager
|
<GroupManager
|
||||||
members={this.state.contactList}
|
members={this.state.contactList}
|
||||||
requiredMember={this.props.myUserId}
|
requiredMember={this.props.myUserId}
|
||||||
|
myUserId={this.props.myUserId}
|
||||||
contacts={this.props.foundContacts}
|
contacts={this.props.foundContacts}
|
||||||
onCancel={this.handleHideAddMembers}
|
onCancel={this.handleHideAddMembers}
|
||||||
onSubmit={this.handleMemberUpdateRequest} />
|
onSubmit={this.handleMemberUpdateRequest} />
|
||||||
@@ -3347,6 +3357,7 @@ class InfoView extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<ContactList
|
<ContactList
|
||||||
contacts={this.state.contactList}
|
contacts={this.state.contactList}
|
||||||
|
myUserId={this.props.myUserId}
|
||||||
emptyListMessage="No members"
|
emptyListMessage="No members"
|
||||||
topicSelected={this.state.selectedContact}
|
topicSelected={this.state.selectedContact}
|
||||||
showOnline={false}
|
showOnline={false}
|
||||||
@@ -3451,6 +3462,7 @@ class ChatMessage extends React.Component {
|
|||||||
if (this.props.mimeType == Drafty.getContentType()) {
|
if (this.props.mimeType == Drafty.getContentType()) {
|
||||||
Drafty.attachments(content, function(att, i) {
|
Drafty.attachments(content, function(att, i) {
|
||||||
attachments.push(<Attachment
|
attachments.push(<Attachment
|
||||||
|
tinode={this.props.tinode}
|
||||||
downloadUrl={Drafty.getDownloadUrl(att)}
|
downloadUrl={Drafty.getDownloadUrl(att)}
|
||||||
filename={att.name} uploader={Drafty.isUploading(att)}
|
filename={att.name} uploader={Drafty.isUploading(att)}
|
||||||
mimetype={att.mime} size={Drafty.getEntitySize(att)}
|
mimetype={att.mime} size={Drafty.getEntitySize(att)}
|
||||||
@@ -3551,7 +3563,7 @@ class Attachment extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
downloadFile(url, filename, mimetype) {
|
downloadFile(url, filename, mimetype) {
|
||||||
var downloader = Tinode.getLargeFileHelper();
|
var downloader = this.props.tinode.getLargeFileHelper();
|
||||||
this.setState({downloader: downloader});
|
this.setState({downloader: downloader});
|
||||||
downloader.download(url, filename, mimetype, (loaded) => {
|
downloader.download(url, filename, mimetype, (loaded) => {
|
||||||
this.setState({progress: loaded / this.props.size});
|
this.setState({progress: loaded / this.props.size});
|
||||||
@@ -3691,7 +3703,7 @@ class MessagesView extends React.Component {
|
|||||||
|
|
||||||
var tryToResubscribe = !this.props.connected && props.connected;
|
var tryToResubscribe = !this.props.connected && props.connected;
|
||||||
|
|
||||||
var topic = Tinode.getTopic(props.topic);
|
var topic = this.props.tinode.getTopic(props.topic);
|
||||||
if (props.topic != this.state.topic) {
|
if (props.topic != this.state.topic) {
|
||||||
var msgs = [];
|
var msgs = [];
|
||||||
var subs = [];
|
var subs = [];
|
||||||
@@ -3707,9 +3719,8 @@ class MessagesView extends React.Component {
|
|||||||
this.leave();
|
this.leave();
|
||||||
|
|
||||||
this.handleDescChange(topic);
|
this.handleDescChange(topic);
|
||||||
var myId = this.props.myUserId;
|
topic.subscribers((sub) => {
|
||||||
topic.subscribers(function(sub) {
|
if (sub.online && sub.user != this.props.myUserId) {
|
||||||
if (sub.online && sub.user != myId) {
|
|
||||||
subs.push(sub);
|
subs.push(sub);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -3766,7 +3777,7 @@ class MessagesView extends React.Component {
|
|||||||
|
|
||||||
leave() {
|
leave() {
|
||||||
if (this.state.topic) {
|
if (this.state.topic) {
|
||||||
var oldTopic = Tinode.getTopic(this.state.topic);
|
var oldTopic = this.props.tinode.getTopic(this.state.topic);
|
||||||
if (oldTopic) {
|
if (oldTopic) {
|
||||||
if (oldTopic.isSubscribed()) {
|
if (oldTopic.isSubscribed()) {
|
||||||
oldTopic.leave(false).catch(function(err) {
|
oldTopic.leave(false).catch(function(err) {
|
||||||
@@ -3797,7 +3808,7 @@ class MessagesView extends React.Component {
|
|||||||
let newState = {scrollPosition: event.target.scrollHeight - event.target.scrollTop};
|
let newState = {scrollPosition: event.target.scrollHeight - event.target.scrollTop};
|
||||||
this.setState((prevState, props) => {
|
this.setState((prevState, props) => {
|
||||||
if (!prevState.fetchingMessages) {
|
if (!prevState.fetchingMessages) {
|
||||||
var topic = Tinode.getTopic(this.state.topic);
|
var topic = this.props.tinode.getTopic(this.state.topic);
|
||||||
if (topic && topic.isSubscribed() && topic.msgHasMoreMessages()) {
|
if (topic && topic.isSubscribed() && topic.msgHasMoreMessages()) {
|
||||||
newState.fetchingMessages = true;
|
newState.fetchingMessages = true;
|
||||||
topic.getMessagesPage(MESSAGES_PAGE).catch((err) => {
|
topic.getMessagesPage(MESSAGES_PAGE).catch((err) => {
|
||||||
@@ -3829,10 +3840,9 @@ class MessagesView extends React.Component {
|
|||||||
handleSubsUpdated() {
|
handleSubsUpdated() {
|
||||||
if (this.state.topic) {
|
if (this.state.topic) {
|
||||||
var subs = [];
|
var subs = [];
|
||||||
var myId = this.props.myUserId;
|
var topic = this.props.tinode.getTopic(this.state.topic);
|
||||||
var topic = Tinode.getTopic(this.state.topic);
|
topic.subscribers((sub) => {
|
||||||
topic.subscribers(function(sub) {
|
if (sub.online && sub.user != this.props.myUserId) {
|
||||||
if (sub.online && sub.user != myId) {
|
|
||||||
subs.push(sub);
|
subs.push(sub);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -3842,7 +3852,7 @@ class MessagesView extends React.Component {
|
|||||||
|
|
||||||
handleNewMessage(msg) {
|
handleNewMessage(msg) {
|
||||||
// Regenerate messages list
|
// Regenerate messages list
|
||||||
var topic = Tinode.getTopic(this.state.topic);
|
var topic = this.props.tinode.getTopic(this.state.topic);
|
||||||
var newState = {messages: []};
|
var newState = {messages: []};
|
||||||
topic.messages(function(m) {
|
topic.messages(function(m) {
|
||||||
if (!m.deleted) {
|
if (!m.deleted) {
|
||||||
@@ -3915,7 +3925,7 @@ class MessagesView extends React.Component {
|
|||||||
handleShowContextMenuMessage(params) {
|
handleShowContextMenuMessage(params) {
|
||||||
params.topicName = this.state.topic;
|
params.topicName = this.state.topic;
|
||||||
var menuItems = ["message_delete"];
|
var menuItems = ["message_delete"];
|
||||||
var topic = Tinode.getTopic(params.topicName);
|
var topic = this.props.tinode.getTopic(params.topicName);
|
||||||
if (topic) {
|
if (topic) {
|
||||||
var acs = topic.getAccessMode();
|
var acs = topic.getAccessMode();
|
||||||
if (acs && acs.isDeleter()) {
|
if (acs && acs.isDeleter()) {
|
||||||
@@ -3933,7 +3943,7 @@ class MessagesView extends React.Component {
|
|||||||
var component = null;
|
var component = null;
|
||||||
if (this.state.topic) {
|
if (this.state.topic) {
|
||||||
var messageNodes = [];
|
var messageNodes = [];
|
||||||
var topic = Tinode.getTopic(this.state.topic);
|
var topic = this.props.tinode.getTopic(this.state.topic);
|
||||||
var groupTopic = topic.getType() == "grp";
|
var groupTopic = topic.getType() == "grp";
|
||||||
var previousFrom = null;
|
var previousFrom = null;
|
||||||
for (var i=0; i<this.state.messages.length; i++) {
|
for (var i=0; i<this.state.messages.length; i++) {
|
||||||
@@ -3973,7 +3983,10 @@ class MessagesView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
messageNodes.push(
|
messageNodes.push(
|
||||||
<ChatMessage content={msg.content} mimeType={msg.head ? msg.head.mime : null}
|
<ChatMessage
|
||||||
|
tinode={this.props.tinode}
|
||||||
|
content={msg.content}
|
||||||
|
mimeType={msg.head ? msg.head.mime : null}
|
||||||
timestamp={msg.ts} response={isReply} seq={msg.seq}
|
timestamp={msg.ts} response={isReply} seq={msg.seq}
|
||||||
userFrom={userFrom} userName={userName} userAvatar={userAvatar}
|
userFrom={userFrom} userName={userName} userAvatar={userAvatar}
|
||||||
sequence={sequence} received={deliveryStatus} uploader={msg._uploader}
|
sequence={sequence} received={deliveryStatus} uploader={msg._uploader}
|
||||||
@@ -3986,9 +3999,8 @@ class MessagesView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let lastSeen = null;
|
let lastSeen = null;
|
||||||
let topicType = Tinode.topicType(cont.topic);
|
|
||||||
let cont = this.props.tinode.getMeTopic().getContact(this.state.topic);
|
let cont = this.props.tinode.getMeTopic().getContact(this.state.topic);
|
||||||
if (cont && topicType == "p2p") {
|
if (cont && Tinode.topicType(cont.topic) == "p2p") {
|
||||||
if (cont.online) {
|
if (cont.online) {
|
||||||
lastSeen = "online now";
|
lastSeen = "online now";
|
||||||
} else if (cont.seen) {
|
} else if (cont.seen) {
|
||||||
@@ -4052,6 +4064,7 @@ class MessagesView extends React.Component {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<SendMessage
|
<SendMessage
|
||||||
|
tinode={this.props.tinode}
|
||||||
topic={this.props.topic}
|
topic={this.props.topic}
|
||||||
disabled={this.state.readOnly}
|
disabled={this.state.readOnly}
|
||||||
sendMessage={this.props.sendMessage}
|
sendMessage={this.props.sendMessage}
|
||||||
@@ -4163,7 +4176,7 @@ class SendMessage extends React.PureComponent {
|
|||||||
" exceeds the " + bytesToHumanSize(MAX_EXTERN_ATTACHMENT_SIZE) + " limit.", "err");
|
" exceeds the " + bytesToHumanSize(MAX_EXTERN_ATTACHMENT_SIZE) + " limit.", "err");
|
||||||
} else if (file.size > MAX_INBAND_ATTACHMENT_SIZE) {
|
} else if (file.size > MAX_INBAND_ATTACHMENT_SIZE) {
|
||||||
// Too large to send inband - uploading out of band and sending as a link.
|
// Too large to send inband - uploading out of band and sending as a link.
|
||||||
let uploader = Tinode.getLargeFileHelper();
|
let uploader = this.props.tinode.getLargeFileHelper();
|
||||||
if (!uploader) {
|
if (!uploader) {
|
||||||
this.props.onError("Cannot initiate file upload.");
|
this.props.onError("Cannot initiate file upload.");
|
||||||
return;
|
return;
|
||||||
@@ -4213,7 +4226,7 @@ class SendMessage extends React.PureComponent {
|
|||||||
var newState = {message: e.target.value};
|
var newState = {message: e.target.value};
|
||||||
var now = new Date().getTime();
|
var now = new Date().getTime();
|
||||||
if (now - this.state.keypressTimestamp > KEYPRESS_DELAY) {
|
if (now - this.state.keypressTimestamp > KEYPRESS_DELAY) {
|
||||||
var topic = Tinode.getTopic(this.props.topic);
|
var topic = this.props.tinode.getTopic(this.props.topic);
|
||||||
if (topic.isSubscribed()) {
|
if (topic.isSubscribed()) {
|
||||||
topic.noteKeyPress();
|
topic.noteKeyPress();
|
||||||
}
|
}
|
||||||
@@ -4563,6 +4576,9 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleError(err, level) {
|
handleError(err, level) {
|
||||||
|
if (err && level) {
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
this.setState({errorText: err, errorLevel: level});
|
this.setState({errorText: err, errorLevel: level});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4597,10 +4613,8 @@ class TinodeWeb extends React.Component {
|
|||||||
navigateTo("");
|
navigateTo("");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Sanitize and package credentail.
|
||||||
cred = cred ? this.state.tinode.addCredential(null, cred) : undefined;
|
cred = Tinode.credential(cred);
|
||||||
cred = cred ? cred.cred : undefined;
|
|
||||||
|
|
||||||
// Try to login with login/password. If they are not available, try token. If no token, ask for login/password.
|
// Try to login with login/password. If they are not available, try token. If no token, ask for login/password.
|
||||||
let promise = null;
|
let promise = null;
|
||||||
let token = this.state.tinode.getAuthToken();
|
let token = this.state.tinode.getAuthToken();
|
||||||
@@ -4619,7 +4633,7 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
this.handleCredentialsRequest(ctrl.params);
|
this.handleCredentialsRequest(ctrl.params);
|
||||||
} else {
|
} else {
|
||||||
this.handleLoginSuccessful(this);
|
this.handleLoginSuccessful();
|
||||||
}
|
}
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
// Login failed, report error.
|
// Login failed, report error.
|
||||||
@@ -4643,8 +4657,8 @@ class TinodeWeb extends React.Component {
|
|||||||
navigateTo(composeUrlHash(parsed.path, parsed.params));
|
navigateTo(composeUrlHash(parsed.path, parsed.params));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLoginSuccessful(instance) {
|
handleLoginSuccessful() {
|
||||||
instance.handleError("", null);
|
this.handleError("", null);
|
||||||
|
|
||||||
// Refresh authentication token.
|
// Refresh authentication token.
|
||||||
if (localStorage.getObject("keep-logged-in")) {
|
if (localStorage.getObject("keep-logged-in")) {
|
||||||
@@ -4652,8 +4666,8 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
// Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.
|
// Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.
|
||||||
var me = this.state.tinode.getMeTopic();
|
var me = this.state.tinode.getMeTopic();
|
||||||
me.onMetaDesc = instance.tnMeMetaDesc;
|
me.onMetaDesc = this.tnMeMetaDesc;
|
||||||
instance.setState({
|
this.setState({
|
||||||
connected: true,
|
connected: true,
|
||||||
credMethod: undefined,
|
credMethod: undefined,
|
||||||
credCode: undefined,
|
credCode: undefined,
|
||||||
@@ -4665,9 +4679,9 @@ class TinodeWeb extends React.Component {
|
|||||||
withLaterSub().
|
withLaterSub().
|
||||||
withDesc().
|
withDesc().
|
||||||
build()
|
build()
|
||||||
).catch(function(err){
|
).catch((err) => {
|
||||||
localStorage.removeItem("auth-token");
|
localStorage.removeItem("auth-token");
|
||||||
instance.handleError(err.message, "err");
|
this.handleError(err.message, "err");
|
||||||
navigateTo("");
|
navigateTo("");
|
||||||
});
|
});
|
||||||
navigateTo(setUrlSidePanel(window.location.hash, 'contacts'));
|
navigateTo(setUrlSidePanel(window.location.hash, 'contacts'));
|
||||||
@@ -4698,7 +4712,7 @@ class TinodeWeb extends React.Component {
|
|||||||
// Sending "received" notifications
|
// Sending "received" notifications
|
||||||
tnData(data) {
|
tnData(data) {
|
||||||
let topic = this.state.tinode.getTopic(data.topic);
|
let topic = this.state.tinode.getTopic(data.topic);
|
||||||
if (topic.msgStatus(data) > this.state.tinode.MESSAGE_STATUS_SENDING) {
|
if (topic.msgStatus(data) > Tinode.MESSAGE_STATUS_SENDING) {
|
||||||
clearTimeout(this.receivedTimer);
|
clearTimeout(this.receivedTimer);
|
||||||
this.receivedTimer = setTimeout(() => {
|
this.receivedTimer = setTimeout(() => {
|
||||||
this.receivedTimer = undefined;
|
this.receivedTimer = undefined;
|
||||||
@@ -4709,7 +4723,7 @@ class TinodeWeb extends React.Component {
|
|||||||
|
|
||||||
/* Fnd topic: find contacts by tokens */
|
/* Fnd topic: find contacts by tokens */
|
||||||
tnInitFind() {
|
tnInitFind() {
|
||||||
var fnd = Tinode.getFndTopic();
|
var fnd = this.state.tinode.getFndTopic();
|
||||||
if (fnd.isSubscribed()) {
|
if (fnd.isSubscribed()) {
|
||||||
this.setState({contactsSearchQuery: ''});
|
this.setState({contactsSearchQuery: ''});
|
||||||
this.tnFndSubsUpdated();
|
this.tnFndSubsUpdated();
|
||||||
@@ -4828,8 +4842,8 @@ class TinodeWeb extends React.Component {
|
|||||||
handleNewAccountRequest(login_, password_, public_, cred_, tags_) {
|
handleNewAccountRequest(login_, password_, public_, cred_, tags_) {
|
||||||
this.state.tinode.connect(this.state.serverAddress)
|
this.state.tinode.connect(this.state.serverAddress)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
var params = this.state.tinode.addCredential({public: public_, tags: tags_}, cred_);
|
return this.state.tinode.createAccountBasic(login_, password_,
|
||||||
return this.state.tinode.createAccountBasic(login_, password_, params);
|
{public: public_, tags: tags_, cred: Tinode.credential(cred_)});
|
||||||
}).then((ctrl) => {
|
}).then((ctrl) => {
|
||||||
if (ctrl.code >= 300 && ctrl.text === "validate credentials") {
|
if (ctrl.code >= 300 && ctrl.text === "validate credentials") {
|
||||||
this.handleCredentialsRequest(ctrl.params);
|
this.handleCredentialsRequest(ctrl.params);
|
||||||
@@ -4848,7 +4862,7 @@ class TinodeWeb extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (password) {
|
if (password) {
|
||||||
this.state.tinode.updateAccountBasic(null, Tinode.getCurrentLogin(), password).catch((err) => {
|
this.state.tinode.updateAccountBasic(null, this.state.tinode.getCurrentLogin(), password).catch((err) => {
|
||||||
this.handleError(err.message, "err");
|
this.handleError(err.message, "err");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -5100,6 +5114,7 @@ class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
<SidepanelView
|
<SidepanelView
|
||||||
|
tinode={this.state.tinode}
|
||||||
connected={this.state.connected}
|
connected={this.state.connected}
|
||||||
displayMobile={this.state.displayMobile}
|
displayMobile={this.state.displayMobile}
|
||||||
hideSelf={this.state.displayMobile && this.state.mobilePanel !== 'sidepanel'}
|
hideSelf={this.state.displayMobile && this.state.mobilePanel !== 'sidepanel'}
|
||||||
Reference in New Issue
Block a user