diff --git a/index.html b/index.html
index 3de21518..cd05b12d 100644
--- a/index.html
+++ b/index.html
@@ -258,6 +258,8 @@
return hash;
}
+ // Helper functions for hash navigation.
+
// Parse hash as in http://www.example.com/path#hash as if it were
// path and arguments.
function parseUrlHash(hash) {
@@ -293,22 +295,31 @@
return url;
}
- function addParamToHash(hash, key, value) {
- var hash = parseUrlHash(hash);
- if (!hash.params) {
- hash.params = {};
- }
- hash.params[key] = value;
- return composeUrlHash(hash.path, hash.params);
+ function addUrlParam(hash, key, value) {
+ var parsed = parseUrlHash(hash);
+ parsed.params[key] = value;
+ return composeUrlHash(parsed.path, parsed.params);
}
- function removeParamFromHash(hash, key) {
- var hash = parseUrlHash(hash);
- if (hash.params) {
- delete hash.params[key];
- }
- return composeUrlHash(hash.path, hash.params);
+ function removeUrlParam(hash, key) {
+ var parsed = parseUrlHash(hash);
+ delete parsed.params[key];
+ return composeUrlHash(parsed.path, parsed.params);
}
+ function setUrlSidePanel(hash, sidepanel) {
+ var parsed = parseUrlHash(hash);
+ parsed.path[0] = sidepanel;
+ return composeUrlHash(parsed.path, parsed.params);
+ }
+ function setUrlTopic(hash, topic) {
+ var parsed = parseUrlHash(hash);
+ parsed.path[1] = topic;
+ // Close InfoView on topic change.
+ delete parsed.params.info;
+ return composeUrlHash(parsed.path, parsed.params);
+ }
+ // END of hash navigation helper functions
+
// Detect server address from the URL
function detectServerAddress() {
@@ -2201,21 +2212,21 @@
},
handleTabClick: function(e) {
e.preventDefault();
- window.location.hash = addParamToHash(window.location.hash, 'tab', e.currentTarget.dataset.id);
+ window.location.hash = addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id);
this.setState({tabSelected: e.currentTarget.dataset.id, contactSelected: null});
},
handleContactSelected: function(sel) {
if (this.state.tabSelected === "p2p") {
- window.location.hash = removeParamFromHash(window.location.hash, 'tab');
+ window.location.hash = removeUrlParam(window.location.hash, 'tab');
this.props.onCreateTopic(sel, undefined);
}
},
handleNewGroupSubmit: function(name, dataUrl, priv, tags) {
- window.location.hash = removeParamFromHash(window.location.hash, 'tab');
+ window.location.hash = removeUrlParam(window.location.hash, 'tab');
this.props.onCreateTopic(undefined, vcard(name, dataUrl), priv, tags);
},
handleGroupByID: function(topicName) {
- window.location.hash = removeParamFromHash(window.location.hash, 'tab');
+ window.location.hash = removeUrlParam(window.location.hash, 'tab');
this.props.onCreateTopic(topicName);
},
render: function() {
@@ -2406,7 +2417,7 @@
var ValidationView = React.createClass({
getInitialState: function() {
return {
- code: '',
+ code: this.props.credCode || '',
};
},
handleChange: function(e) {
@@ -2420,12 +2431,12 @@
handleSubmit: function(e) {
e.preventDefault();
if (this.state.code && this.state.code.trim()) {
- this.props.onSubmit(this.props.credMethod[0], this.state.code.trim());
+ this.props.onSubmit(this.props.credMethod, this.state.code.trim());
}
},
render: function() {
var methods = {'email': 'email', 'tel': 'phone'};
- var method = methods[this.props.credMethod[0]] || this.props.credMethod[0];
+ var method = methods[this.props.credMethod] || this.props.credMethod;
return (
@@ -3767,7 +3778,7 @@
serverVersion: 'no connection',
contactsSearchQuery: '',
foundContacts: [],
- credMethod: []
+ credMethod: ''
};
},
componentDidMount: function() {
@@ -3807,11 +3818,11 @@
},
// Handle for hashchange event: display appropriate panels.
- handleHashRoute: function(e) {
+ handleHashRoute: function() {
var hash = parseUrlHash(window.location.hash);
// Left-side panel selector.
if (hash.path && hash.path.length >0) {
- if (['register','settings','edit','cred','newtpk',''].includes(hash.path[0])) {
+ if (['register','settings','edit','cred','newtpk','contacts',''].includes(hash.path[0])) {
this.setState({sidePanelSelected: hash.path[0]});
} else {
console.log("Unknown sidepanel view", hash.path[0]);
@@ -3829,7 +3840,7 @@
// Additional parameters of panels.
this.setState({
credCode: hash.params.code,
- credMethod: hash.params.cred,
+ credMethod: hash.params.method,
showInfoPanel: hash.params.info,
newTopicTabSelected: hash.params.tab
});
@@ -3875,8 +3886,14 @@
},
doLogin: function(login, password, cred) {
- var instance = this;
- cred = cred ? Tinode.addCredential(null, cred).cred : undefined;
+ if (Tinode.isAuthenticated()) {
+ // Already logged in. Go to default screen.
+ window.location.hash = "";
+ }
+
+ cred = cred ? Tinode.addCredential(null, cred) : undefined;
+ 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.
var promise = null;
var token = Tinode.getAuthToken();
@@ -3890,6 +3907,7 @@
this.setState({loginDisabled: false});
}
+ var instance = this;
if (promise) {
promise.then(function(ctrl) {
if (ctrl.code >= 300 && ctrl.text === "validate credentials") {
@@ -3902,6 +3920,7 @@
instance.setState({loginDisabled: false});
instance.handleError(err.message, "err");
localStorage.removeItem("auth-token");
+ window.location.hash = "";
});
}
},
@@ -3909,7 +3928,7 @@
handleCredentialsRequest: function(params) {
var parsed = parseUrlHash(window.location.hash);
parsed.path[0] = 'cred';
- parsed.params['cred'] = params.cred;
+ parsed.params['method'] = params.cred[0];
window.location.hash = composeUrlHash(parsed.path, parsed.params);
},
@@ -3922,10 +3941,13 @@
// Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.
var me = Tinode.getMeTopic();
me.onMetaDesc = instance.tnMeMetaDesc;
- window.location.hash = "";
+ if (!window.location.hash) {
+ window.location.hash = 'contacts';
+ } else {
+ instance.handleHashRoute();
+ }
instance.setState({
connected: true,
- sidePanelSelected: '',
myUserId: Tinode.getCurrentUserID()
});
// Subscribe, fetch topic desc, the list of subscriptions. Messages are not fetched.
@@ -4017,28 +4039,25 @@
if (topicName) {
// Contact selected
if (this.state.topicSelected != topicName) {
- var parsed = parseUrlHash(window.location.hash);
- parsed.path[1] = topicName;
- window.location.hash = composeUrlHash(parsed.path, parsed.params);
+ window.location.hash = setUrlTopic(window.location.hash, topicName);
}
this.setState({
+ errorText: '',
+ errorLevel: null,
mobilePanel: 'topic-view',
- showInfoPanel: false,
topicSelectedOnline: online,
topicSelectedAcs: acs,
- sidePanelSelected: '',
infoPanelShowMembers: Tinode.getTopicType(topicName) === "grp"
});
} else {
if (this.state.topicSelected) {
- var parsed = parseUrlHash(window.location.hash);
- parsed.path[1] = '';
- window.history.replaceState({}, "", composeUrlHash(parsed.path, parsed.params));
+ window.history.replaceState({}, "", setUrlTopic(window.location.hash, ''));
}
// Currently selected contact deleted
this.setState({
+ errorText: '',
+ errorLevel: null,
mobilePanel: 'sidepanel',
- showInfoPanel: false,
topicSelectedOnline: false,
topicSelectedAcs: null,
infoPanelShowMembers: false
@@ -4082,9 +4101,7 @@
},
// User chose a Sign Up menu item.
handleNewAccount: function() {
- var parsed = parseUrlHash(window.location.hash);
- parsed.path[0] = 'register';
- window.location.hash = composeUrlHash(parsed.path, parsed.params);
+ window.location.hash = setUrlSidePanel(window.location.hash, 'register');
},
// Actual registration of a new account.
handleNewAccountRequest: function(login_, password_, public_, cred_, tags_) {
@@ -4127,9 +4144,7 @@
// User chose Settings menu item.
handleSettings: function() {
- var parsed = parseUrlHash(window.location.hash);
- parsed.path[0] = this.state.myUserId ? 'edit' : 'settings';
- window.location.hash = composeUrlHash(parsed.path, parsed.params);
+ window.location.hash = setUrlSidePanel(window.location.hash, this.state.myUserId ? 'edit' : 'settings');
},
// User updated connection parameters - transport and server address
handleConnectionSettings: function(serverAddress, transport) {
@@ -4141,7 +4156,7 @@
// User clicked Cancel button in Setting or Sign Up panel.
handleSidepanelCancel: function() {
var parsed = parseUrlHash(window.location.hash);
- parsed.path[0] = '';
+ parsed.path[0] = this.state.myUserId ? 'contacts' : '';
if (parsed.params) {
delete parsed.params.tab;
}
@@ -4150,9 +4165,7 @@
},
// User clicked a (+) menu item.
handleNewTopic: function() {
- var parsed = parseUrlHash(window.location.hash);
- parsed.path[0] = 'newtpk';
- window.location.hash = composeUrlHash(parsed.path, parsed.params);
+ window.location.hash = setUrlSidePanel(window.location.hash, 'newtpk');
},
// Create of a new topic. New P2P topic requires peer's name.
handleNewTopicRequest: function(peerName, pub, priv, tags) {
@@ -4223,6 +4236,7 @@
localStorage.removeItem("auth-token");
this.setState(this.getInitialState());
this.tnSetup(this.state.serverAddress, this.state.transport);
+ window.location.hash = "";
},
handleLeaveUnsubRequest: function(topicName) {
@@ -4233,9 +4247,8 @@
var instance = this;
topic.leave(true).then(function(ctrl) {
// Hide MessagesView and InfoView panels.
+ window.location.hash = setUrlTopic(window.location.hash, '');
instance.setState({
- topicSelected: '',
- showInfoPanel: false,
infoPanelShowMembers: false
});
}).catch(function(err) {
@@ -4290,11 +4303,11 @@
},
handleShowInfoView: function() {
- window.location.hash = addParamToHash(window.location.hash, 'info', true);
+ window.location.hash = addUrlParam(window.location.hash, 'info', true);
this.setState({showInfoPanel: true, infoPanelShowMembers: false});
},
handleHideInfoView: function() {
- window.location.hash = removeParamFromHash(window.location.hash, 'info');
+ window.location.hash = removeUrlParam(window.location.hash, 'info');
this.setState({showInfoPanel: false, infoPanelShowMembers: false});
},
handleMemberUpdateRequest: function(topicName, added, removed) {