better support for links to profiles that has changed nickname after the link was created

This commit is contained in:
Hannes Mannerheim 2015-09-18 13:42:19 +02:00
parent 2e4a8923ef
commit ae5ccea547
4 changed files with 106 additions and 63 deletions

View File

@ -135,12 +135,6 @@ function getFromAPI(stream, actionOnSuccess) {
statusCode: {
401:function() {
location.reload(); // we may have been logged out in another tab, reload page
},
404:function() {
// redirect to frontpage when trying to access non-existing users
if(stream.indexOf('statuses/user_timeline.json?screen_name=') > -1) {
window.location.replace(window.siteInstanceURL);
}
}
},
success: function(data, textStatus, request) {
@ -178,15 +172,17 @@ function getFromAPI(stream, actionOnSuccess) {
/* ·
·
· Get user nickname from user id
· Get user nickname by user id
·
· @param id: local user id
· @param callback: function to invoke when done
·
· · · · · · · · · · · · · */
function getUserIdFromNicknameFromAPI(id, callback) {
function getNicknameByUserIdFromAPI(id, callback) {
display_spinner();
getFromAPI('users/show.json?id=' + id, function(data){
remove_spinner();
if(data && typeof data.screen_name != 'undefined') {
callback(data.screen_name);
}

View File

@ -483,11 +483,14 @@ function groupProfileCard(groupAlias) {
· Change stream
·
· @param streamObject: object returned by pathToStreamRouter()
· @param setLocation: whether we should update the browsers location bar when we set the new stream
· @param fallbackId: if we fail to get the stream, it can be due to a bad/changed user/group nickname,
· in that case this parameter can contain a user/group id that we can use to retrieve the correct nickname
· @param actionOnSuccess: callback function on success
·
· · · · · · · · · */
function setNewCurrentStream(streamObject,setLocation,actionOnSuccess) {
function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess) {
if(!streamObject && !streamObject.stream) {
console.log('invalid streamObject, no stream to set!');
@ -497,11 +500,6 @@ function setNewCurrentStream(streamObject,setLocation,actionOnSuccess) {
// remember state of old stream (including profile card)
window.oldStreams[window.currentStream] = $('#feed').siblings('.profile-card').outerHTML() + $('#feed').outerHTML();
// set location bar from stream
if(setLocation) {
setUrlFromStream(streamObject);
}
// halt interval that checks for new queets
window.clearInterval(checkForNewQueetsInterval);
@ -540,6 +538,11 @@ function setNewCurrentStream(streamObject,setLocation,actionOnSuccess) {
$('#feed-header-inner h2').css('opacity','0.2');
$('#feed-header-inner h2').animate({opacity:'1'},1000);
// set location bar from stream
if(setLocation) {
setUrlFromStream(streamObject);
}
// also mark this stream as the current stream immediately, if a saved copy exists
addStreamToHistoryMenuAndMarkAsCurrent(streamObject);
}
@ -563,41 +566,74 @@ function setNewCurrentStream(streamObject,setLocation,actionOnSuccess) {
// get stream
getFromAPI(streamObject.stream, function(queet_data, userArray){
if(queet_data) {
// while waiting for this data user might have changed stream, so only proceed if current stream still is this one
if(window.currentStream == streamObject.stream) {
// profile card from user array
if(userArray) {
addProfileCardToDOM(buildProfileCard(userArray));
// while waiting for this data user might have changed stream, so only proceed if current stream still is this one
if(window.currentStream != streamObject.stream) {
console.log('stream has changed, aborting');
return;
}
// if we have a fallbackId and a userArray, and the userArray's is is not equal to
// the fallackId, this is the wrong stream! we need to re-invoke setNewCurrentStream()
// with the correct and up-to-date nickname (maybe best not to send a fallbackId here not
// to risk getting into an infinite loop caused by bad data)
// also, we do the same thing if getting the stream fails, but we have a fallback id
if((userArray && fallbackId && userArray.id != fallbackId)
|| (queet_data === false && fallbackId)) {
getNicknameByUserIdFromAPI(fallbackId,function(nickname) {
if(nickname) {
setNewCurrentStream(pathToStreamRouter(nickname),true,false,actionOnSuccess);
}
// show group profile card if this is a group stream
if(streamObject.name == 'group notice stream'
|| streamObject.name == 'group member list'
|| streamObject.name == 'group admin list') {
groupProfileCard(streamObject.nickname);
else {
// redirect to front page if everything fails
setNewCurrentStream(pathToStreamRouter('/'),true,false,actionOnSuccess);
}
});
}
// start checking for new queets again
window.clearInterval(checkForNewQueetsInterval);
checkForNewQueetsInterval=window.setInterval(function(){checkForNewQueets()},window.timeBetweenPolling);
// getting stream failed, and we don't have a fallback id, redirect to front page
else if(queet_data === false) {
setNewCurrentStream(pathToStreamRouter('/'),true,false,actionOnSuccess);
}
// add this stream to the history menu
addStreamToHistoryMenuAndMarkAsCurrent(streamObject);
// everything seems fine, show the new stream
else if(queet_data) {
remove_spinner();
$('#feed-body').html(''); // empty feed only now so the scrollers don't flicker on and off
$('#new-queets-bar').parent().addClass('hidden'); document.title = window.siteTitle; // hide new queets bar if it's visible there
addToFeed(queet_data, false,'visible'); // add stream items to feed element
$('#feed').animate({opacity:'1'},150); // fade in
$('body').removeClass('loading-older');$('body').removeClass('loading-newer');
$('html,body').scrollTop(0); // scroll to top
// set location bar from stream
if(setLocation) {
setUrlFromStream(streamObject);
}
// maybe do something
if(typeof actionOnSuccess == 'function') {
actionOnSuccess();
}
// profile card from user array
if(userArray) {
addProfileCardToDOM(buildProfileCard(userArray));
}
// show group profile card if this is a group stream
if(streamObject.name == 'group notice stream'
|| streamObject.name == 'group member list'
|| streamObject.name == 'group admin list') {
groupProfileCard(streamObject.nickname);
}
// start checking for new queets again
window.clearInterval(checkForNewQueetsInterval);
checkForNewQueetsInterval=window.setInterval(function(){checkForNewQueets()},window.timeBetweenPolling);
// add this stream to the history menu
addStreamToHistoryMenuAndMarkAsCurrent(streamObject);
remove_spinner();
$('#feed-body').html(''); // empty feed only now so the scrollers don't flicker on and off
$('#new-queets-bar').parent().addClass('hidden'); document.title = window.siteTitle; // hide new queets bar if it's visible there
addToFeed(queet_data, false,'visible'); // add stream items to feed element
$('#feed').animate({opacity:'1'},150); // fade in
$('body').removeClass('loading-older');$('body').removeClass('loading-newer');
$('html,body').scrollTop(0); // scroll to top
// maybe do something
if(typeof actionOnSuccess == 'function') {
actionOnSuccess();
}
}
});

View File

@ -56,7 +56,7 @@ window.loggedIn = iterateRecursiveReplaceHtmlSpecialChars(window.loggedIn);
window.onpopstate = function(event) {
if(event && event.state) {
display_spinner();
setNewCurrentStream(pathToStreamRouter(event.state.strm),false,function(){
setNewCurrentStream(pathToStreamRouter(event.state.strm),false,false,function(){
remove_spinner();
});
}
@ -764,7 +764,7 @@ function proceedToSetLanguageAndLogin(data){
else {
display_spinner();
window.currentStream = ''; // force reload stream
setNewCurrentStream(getStreamFromUrl(),true,function(){
setNewCurrentStream(getStreamFromUrl(),true,false,function(){
logoutWithoutReload(false);
remove_spinner();
});
@ -878,7 +878,7 @@ function doLogin(streamObjectToSet) {
// set stream
window.currentStream = ''; // always reload stream on login
setNewCurrentStream(streamObjectToSet,true,function(){
setNewCurrentStream(streamObjectToSet,true,false,function(){
$('.language-dropdown').css('display','none');
$('#user-header').animate({opacity:'1'},800);
$('#user-body').animate({opacity:'1'},800);
@ -1200,7 +1200,7 @@ $('#user-header').on('click',function(e){
if($(e.target).is('#mini-edit-profile-button')) {
return;
}
setNewCurrentStream(pathToStreamRouter(window.loggedIn.screen_name),true);
setNewCurrentStream(pathToStreamRouter(window.loggedIn.screen_name),true,false);
});
@ -1215,7 +1215,7 @@ $('#search-query').on('keyup',function(e) { if(e.keyCode==13) { showSearchStream
$('button.icon.nav-search').on('click',function(e) { showSearchStream();}); // on click on magnifying glass
function showSearchStream() {
var path = 'search/notice?q=' + encodeURIComponent(replaceHtmlSpecialChars($('#search-query').val()));
setNewCurrentStream(pathToStreamRouter(path),true);
setNewCurrentStream(pathToStreamRouter(path),true,false);
}
@ -1272,31 +1272,42 @@ $('body').on('click','a', function(e) {
if(streamObject && streamObject.stream) {
e.preventDefault();
// if this is a user/{id} type link
// if this is a user/{id} type link we want to find the nickname before setting a new stream
// the main reason is that we want to update the browsers location bar and the .stream-selecton
// links as fast as we can. we rather not wait for the server response
if(streamObject.name == 'profile by id') {
// see if we have the nickname in cache
var nickname = userArrayCacheGetUserNicknameById(streamObject.id);
if(nickname) {
setNewCurrentStream(pathToStreamRouter(nickname),true);
// pathToStreamRouter() might have found a cached nickname
if(streamObject.nickname) {
setNewCurrentStream(pathToStreamRouter(streamObject.nickname),true,streamObject.id);
}
// if we don't have it in cache we query the server for it
// (we _could_ just try the nickname in the link html, but the user can have changed nickname)
// otherwise we might follow the user and thereby already know its nickname
else if (typeof window.following != 'undefined' && typeof window.following[streamObject.id] != 'undefined') {
setNewCurrentStream(pathToStreamRouter(window.following[streamObject.id].username),true,streamObject.id);
}
// if the text() of the clicked element looks like a user nickname, use that (but send id to setNewCurrentStream() in case this is bad data)
else if(/^@[a-zA-Z0-9]+$/.test($(e.target).text()) || /^[a-zA-Z0-9]+$/.test($(e.target).text())) {
var nickname = $(e.target).text();
if(nickname.indexOf('@') == 0) {
nickname = nickname.substring(1); // remove any starting @
}
setNewCurrentStream(pathToStreamRouter(nickname),true,streamObject.id);
}
// if we can't figure out or guess a nickname, query the server for it
else {
display_spinner();
getUserIdFromNicknameFromAPI(streamObject.id,function(nickname) {
getNicknameByUserIdFromAPI(streamObject.id,function(nickname) {
if(nickname) {
setNewCurrentStream(pathToStreamRouter(nickname),true);
setNewCurrentStream(pathToStreamRouter(nickname),true,false);
}
else {
remove_spinner();
alert('could not find local user with id ' + streamObject.id);
alert('user not found');
}
});
}
}
// all other links that qvitter can handle
else {
setNewCurrentStream(streamObject,true);
setNewCurrentStream(streamObject,true,false);
}
}
}
@ -2300,7 +2311,7 @@ $('body').on('click','button.shorten',function () {
· · · · · · · · · · · · · */
$('body').on('click','.reload-stream',function () {
$('.reload-stream').hide();
setNewCurrentStream(URLtoStreamRouter(window.location.href),false,function(){
setNewCurrentStream(URLtoStreamRouter(window.location.href),false,false,function(){
$('.reload-stream').show();
});
});
@ -3501,7 +3512,7 @@ $('body').on('click','#mini-edit-profile-button, #edit-profile-header-link, .hov
$('#page-container > .profile-card .edit-profile-button').trigger('click');
}
else {
setNewCurrentStream(pathToStreamRouter(window.loggedIn.screen_name), true, function(){
setNewCurrentStream(pathToStreamRouter(window.loggedIn.screen_name), true, false, function(){
$('#page-container > .profile-card .edit-profile-button').trigger('click');
});
}

View File

@ -217,7 +217,7 @@ function pathToStreamRouter(path) {
return streamObject;
}
// group/{id }/id
// group/{id}/id
if(pathSplit.length == 3 && pathSplit[0] == 'group' && /^[0-9]+$/.test(pathSplit[1]) && pathSplit[2] == 'id') {
streamObject.name = 'group notice stream by id';
streamObject.id = pathSplit[1];