navigation mostly works but still buggy

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