You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
630 lines
23 KiB
630 lines
23 KiB
// tmobile.js |
|
// 2013 Miguel Freitas |
|
// |
|
// mobile interface for twister using jquery mobile + router |
|
|
|
var twisterInitialized = false; |
|
var handlersInstalled = false; |
|
|
|
function initializeTwister( redirectNetwork, redirectLogin, cbFunc, cbArg ) { |
|
if( !handlersInstalled ) { |
|
interfaceNetworkHandlers(); |
|
installUserSearchHandler(); |
|
installProfileEditHandlers(); |
|
// install scrollbottom handler to load more posts as needed |
|
$(window).on('scroll', function () { |
|
if ($(window).scrollTop() >= $(document).height() - $(window).height() - 20){ |
|
reachedScrollBottom(); |
|
} |
|
}); |
|
// home screen timeline refresh button |
|
$('.timeline-refresh').on('click', function (e) { |
|
requestTimelineUpdate("latest",postsPerRefresh,followingUsers); |
|
$.mobile.silentScroll(0); |
|
}); |
|
// reply text counter both newmsg and dmchat |
|
$('.post-area-new textarea') |
|
.off('input keyup') |
|
.on('focus', poseTextareaPostTools) |
|
.on('keyup', replyTextInput) |
|
.on('keyup', function() { replyTextUpdateRemaining(this); }) |
|
; |
|
|
|
handlersInstalled = true; |
|
|
|
twister.tmpl.post = extractTemplate('#template-post'); |
|
twister.tmpl.postFull = extractTemplate('#template-post-full'); |
|
twister.tmpl.postFull.find('.post-stats').hide(); |
|
} |
|
|
|
if( twisterInitialized ) { |
|
if( cbFunc ) |
|
cbFunc(cbArg); |
|
} else { |
|
networkUpdate( function() { |
|
if( redirectNetwork && !twisterdConnectedAndUptodate ) { |
|
$.MAL.goNetwork(); |
|
return; |
|
} |
|
|
|
initUser(function() { |
|
if( redirectLogin && !defaultScreenName ) { |
|
$.MAL.goLogin(); |
|
return; |
|
} |
|
|
|
if( defaultScreenName ) { |
|
loadFollowing( function(args) { |
|
requestLastHave(); |
|
initMentionsCount(); |
|
initDMsCount(); |
|
twisterFollowingO = TwisterFollowing(defaultScreenName); |
|
|
|
twisterInitialized = true; |
|
if( cbFunc ) |
|
cbFunc(cbArg); |
|
setInterval("tmobileTick()", 2000); |
|
}); |
|
} else { |
|
if( cbFunc ) |
|
cbFunc(cbArg); |
|
} |
|
}); |
|
}); |
|
} |
|
} |
|
|
|
var router=new $.mobile.Router( |
|
[ |
|
{ "#index" : {handler: "index", events: "bc"} }, |
|
{ "#home": {handler: "home", events: "bs" } }, |
|
{ "#profile": {handler: "profile", events: "bs" } }, |
|
{ "#profile-edit": {handler: "profileedit", events: "bs" } }, |
|
{ "#following": {handler: "following", events: "bs" } }, |
|
{ "#post": {handler: "post", events: "bs" } }, |
|
{ "#newmsg": {handler: "newmsg", events: "bs" } }, |
|
{ "#rt": {handler: "rt", events: "bs" } }, |
|
{ "#mentions": {handler: "mentions", events: "bs" } }, |
|
{ "#hashtag": {handler: "hashtag", events: "bs" } }, |
|
{ "#login": {handler: "login", events: "bs" } }, |
|
{ "#network": {handler: "network", events: "bs" } }, |
|
{ "#directmsg": {handler: "directmsg", events: "bs" } }, |
|
{ "#dmchat": {handler: "dmchat", events: "bs" } }, |
|
{ "#search": {handler: "search", events: "bs" } }, |
|
{ "#new-user-modal": {handler: "newusermodal", events: "bs" } }, |
|
],{ |
|
index: function(type,match,ui) { |
|
$.mobile.loading('show'); |
|
initializeTwister( true, true, function() { |
|
//$.MAL.goHome(); |
|
}); |
|
}, |
|
home: function(type,match,ui) { |
|
$.mobile.loading('show'); |
|
initializeTwister( true, true, function() { |
|
if( !$("#home .posts").children().length ) { |
|
$.mobile.loading('show'); |
|
cleanupStorage(); |
|
getFullname( defaultScreenName, $("#home .rtitle")); |
|
$(".mentions-count").attr("href","#mentions?user="+defaultScreenName ); |
|
requestTimelineUpdate("latestFirstTime",postsPerRefresh,followingUsers); |
|
} |
|
}); |
|
}, |
|
profile: function(type,match,ui) { |
|
var params=router.getParams(match[1]); |
|
clearProfilePage(); |
|
$.mobile.loading('show'); |
|
initializeTwister( true, true, function() { |
|
var user; |
|
if( params && params.hasOwnProperty("user") ) { |
|
user = params.user; |
|
} else { |
|
user = defaultScreenName; |
|
} |
|
var $newmsgLink = $("a.profile-newmsg"); |
|
if( user != defaultScreenName ) { |
|
$newmsgLink.attr("href",$.MAL.newPostToUrl(user)).show(); |
|
} else { |
|
$newmsgLink.hide(); |
|
} |
|
|
|
$.mobile.loading('show'); |
|
updateProfileData( $("#profile"), user); |
|
}); |
|
}, |
|
profileedit: function(type,match,ui) { |
|
$.mobile.loading('show'); |
|
initializeTwister( true, true, function() { |
|
var containerElem = $('.profile-card.forEdition'); |
|
loadProfileForEdit(defaultScreenName, { |
|
fullname: containerElem.find('.input-name').attr('placeholder', polyglot.t('Full name here')), |
|
bio: containerElem.find('.input-bio').attr('placeholder', polyglot.t('Describe yourself')), |
|
location: containerElem.find('.input-location').attr('placeholder', polyglot.t('Location')), |
|
url: containerElem.find('.input-url').attr('placeholder', polyglot.t('website')) |
|
}); |
|
loadAvatarForEdit(defaultScreenName, $('.profile-card-photo.forEdition')); |
|
dumpPrivkey(defaultScreenName, function(args, key) { |
|
$(".secret-key").text(key); |
|
}, {}); |
|
}); |
|
}, |
|
following: function(type,match,ui) { |
|
var params=router.getParams(match[1]); |
|
clearProfilePage(); |
|
$.mobile.loading('show'); |
|
initializeTwister( true, true, function() { |
|
var user; |
|
if( params && params.hasOwnProperty("user") ) { |
|
user = params.user; |
|
} else { |
|
user = defaultScreenName; |
|
} |
|
if( params && params.hasOwnProperty("follow") ) { |
|
follow(params.follow); |
|
} |
|
if( params && params.hasOwnProperty("unfollow") ) { |
|
unfollow(params.unfollow); |
|
} |
|
$.mobile.loading('show'); |
|
$("#following a.ui-btn").removeClass("ui-btn-active"); |
|
var followingList = twister.tmpl.followingList.clone(true).appendTo($("#following .content")) |
|
.closest('.following-list').listview(); |
|
appendFollowingToElem(followingList); |
|
followingList.find('[data-role="button"]').button(); |
|
}); |
|
}, |
|
post: function(type,match,ui) { |
|
initializeTwister( true, true, function (req) { |
|
if (!req || !req.userpost) return; |
|
|
|
var originalLi = postToElem(JSON.parse(req.userpost), 'original', false, twister.tmpl.postFull) |
|
.addClass('expanded-post') |
|
; |
|
var $ulPost = $("#post ul.posts"); |
|
$ulPost.text(""); |
|
$ulPost.append(originalLi); |
|
$ulPost.find(".post-interactions").trigger('create'); |
|
$ulPost.listview('refresh'); |
|
installReplyClick(); |
|
installRetransmitClick(); |
|
|
|
// insert replies to this post after |
|
requestRepliesAfter(originalLi); |
|
// RTs faces and counter |
|
var postDataElem = originalLi.find('.post-data'); |
|
requestRTs(postDataElem.attr('data-screen-name'), postDataElem.attr('data-id')); |
|
}, router.getParams(match[1])); |
|
}, |
|
newmsg: function(type,match,ui) { |
|
var params=router.getParams(match[1]); |
|
initializeTwister( true, true, function() { |
|
var $replyTextarea = $("#newmsg .post-area-new textarea"); |
|
$replyTextarea.attr("placeholder", polyglot.t("New Post...")); |
|
if( params && params.hasOwnProperty("replyto") ) { |
|
$replyTextarea.val(params.replyto); |
|
} else { |
|
$replyTextarea.val(""); |
|
} |
|
$.MAL.disableButton($("#newmsg .post-submit")); |
|
|
|
var $replyOriginal = $(".reply-original-post") |
|
$replyOriginal.html(""); |
|
if( params && params.hasOwnProperty("userpost") ) { |
|
var originalLi = postToElem(JSON.parse(params.userpost), 'original'); |
|
$replyOriginal.append(originalLi); |
|
$replyOriginal.listview('refresh'); |
|
} |
|
|
|
installSubmitClick(); |
|
}); |
|
}, |
|
rt: function(type,match,ui) { |
|
var params=router.getParams(match[1]); |
|
initializeTwister( true, true, function() { |
|
var $rtOriginal = $(".rt-original-post") |
|
$rtOriginal.html(""); |
|
var originalLi = postToElem(JSON.parse(params.userpost), 'original'); |
|
$rtOriginal.append(originalLi); |
|
$rtOriginal.listview('refresh'); |
|
|
|
installRetransmitConfirmClick(); |
|
}); |
|
}, |
|
mentions: function(type,match,ui) { |
|
var params=router.getParams(match[1]); |
|
$.mobile.loading('show'); |
|
initializeTwister( true, true, function() { |
|
var user; |
|
var $newmsgLink = $("a.mention-newmsg"); |
|
if( params && params.hasOwnProperty("user") ) { |
|
user = params.user; |
|
$newmsgLink.attr("href",$.MAL.newPostToUrl(user)); |
|
} else { |
|
user = defaultScreenName; |
|
$newmsgLink.attr("href","#newmsg"); |
|
resetMentionsCount(); |
|
} |
|
$("#mentions .rtitle").text(polyglot.t("mentions_at", { user: user })); |
|
var $ulMentions = $("#mentions ul.posts"); |
|
setupHashtagOrMention( $ulMentions, user, "mention"); |
|
}); |
|
}, |
|
hashtag: function(type,match,ui) { |
|
var params=router.getParams(match[1]); |
|
$.mobile.loading('show'); |
|
initializeTwister( true, true, function() { |
|
$("#hashtag .rtitle").text("#" + params.hashtag); |
|
$("a.hashtag-newmsg").attr("href",$.MAL.newPostHashtagToUrl(params.hashtag)); |
|
var $ulHashtag = $("#hashtag ul.posts"); |
|
setupHashtagOrMention($ulHashtag,params.hashtag,"hashtag"); |
|
}); |
|
}, |
|
login: function(type,match,ui) { |
|
if (!$('#login .content').children().length) |
|
$('#login .content').append(twister.tmpl.loginMC.clone(true)).trigger('create'); |
|
$.mobile.loading('show'); |
|
initializeTwister( true, false, function() { |
|
$.mobile.loading('hide'); |
|
$("select.local-usernames").selectmenu("refresh", true); |
|
}); |
|
}, |
|
network: function(type,match,ui) { |
|
$.mobile.loading('show'); |
|
initializeTwister( false, false, function() { |
|
$.mobile.loading('hide'); |
|
$("select.local-usernames.spam-user").selectmenu("refresh", true); |
|
getSpamMsg(); |
|
getGenerate(); |
|
}); |
|
}, |
|
directmsg: function(type,match,ui) { |
|
$.mobile.loading('show'); |
|
initializeTwister( true, true, function() { |
|
$.mobile.loading('show'); |
|
modalDMsSummaryDraw($('#directmsg .direct-messages-list')); |
|
}); |
|
}, |
|
dmchat: function(type,match,ui) { |
|
var params=router.getParams(match[1]); |
|
$.mobile.loading('show'); |
|
initializeTwister( true, true, function() { |
|
var peerAlias = params.user; |
|
var board = $('#dmchat .direct-messages-thread').empty(); |
|
|
|
$('#dmchat .rtitle').text('Chat @' + peerAlias); |
|
$("#dmchat textarea").val(""); |
|
installDMSendClick(peerAlias); |
|
|
|
$.mobile.loading('show'); |
|
|
|
tmobileQueryReq = queryStart(board, peerAlias, 'direct', undefined, 2000, { |
|
boardAutoAppend: true, |
|
lastId: 0, |
|
lengthNew: 0, |
|
ready: function (req, peerAlias) { |
|
twister.DMs[peerAlias] = twister.res[req]; |
|
}, |
|
readyReq: peerAlias, |
|
drawFinish: function (req) { |
|
setTimeout($.MAL.dmConversationLoaded, 200, twister.res[req].board); |
|
}, |
|
skidoo: function (req) { |
|
return $.mobile.activePage.attr('id') !== 'dmchat' || req !== tmobileQueryReq; |
|
} |
|
}); |
|
}); |
|
}, |
|
search: function(type,match,ui) { |
|
initializeTwister( true, true, function() { |
|
/**/ |
|
}); |
|
}, |
|
newusermodal: function(type,match,ui) { |
|
initializeTwister( false, false, function() { |
|
/* dumpPrivkey(defaultScreenName, function(args, key) { |
|
$(".secret-key").text(key); |
|
}, {}); */ |
|
}); |
|
}, |
|
}, { |
|
defaultHandler: function(type, ui, page) { |
|
console.log("Default handler called due to unknown route (" |
|
+ type + ", " + ui + ", " + page + ")" ); |
|
console.log(ui); |
|
console.log(page); |
|
}, |
|
defaultHandlerEvents: "s", |
|
defaultArgsRe: true |
|
} |
|
); |
|
|
|
function installPostboardClick() { |
|
var $postDatas = $(".post-data"); |
|
$postDatas.off('click').on('click', function (e) { |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
var userpost = $(this).attr("data-userpost"); |
|
var url = "#post?userpost=" + encodeURIComponent(userpost); |
|
$.mobile.loading('show'); |
|
$.mobile.navigate( url ); |
|
}); |
|
|
|
$(".post a").off('click').on('click', function (e) { |
|
e.stopPropagation(); |
|
|
|
// stopPropagation is supposed to be enough, but in Android the |
|
// default action is not called so we reimplement it here as a hack. |
|
e.preventDefault(); |
|
$.mobile.loading('show'); |
|
$.mobile.navigate( $(this).attr("href") ); |
|
}); |
|
} |
|
|
|
function installReplyClick() { |
|
var $postReply = $("#post .post-reply"); |
|
$postReply.off('click').on('click', function (e) { |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
|
|
var $postData = $(this).closest(".post-data"); |
|
var userpost = $postData.attr("data-userpost"); |
|
var replyTo = $postData.attr("data-reply-to"); |
|
var url = "#newmsg?replyto=" + encodeURIComponent(replyTo) + |
|
"&userpost=" + encodeURIComponent(userpost); |
|
$.mobile.loading('show'); |
|
$.mobile.navigate( url ); |
|
}); |
|
} |
|
|
|
function installRetransmitClick() { |
|
var $postRt = $("#post .post-propagate"); |
|
$postRt.off('click').on('click', function (e) { |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
|
|
var $postData = $(this).closest(".post-data"); |
|
var userpost = $postData.attr("data-userpost"); |
|
var url = "#rt?userpost=" + encodeURIComponent(userpost); |
|
$.mobile.loading('show'); |
|
$.mobile.navigate( url ); |
|
}); |
|
} |
|
|
|
|
|
function installSubmitClick() { |
|
var $postSubmit = $(".post-submit"); |
|
$postSubmit.off('click').on('click', function (e) { |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
|
|
var $this = $( this ); |
|
var $replyText = $this.closest(".post-area-new").find("textarea"); |
|
|
|
var $postOrig = $("#newmsg .reply-original-post .post-data"); |
|
|
|
var s = encode_utf8($replyText.val()); |
|
newPostMsg(s, $postOrig.attr('data-screen-name'), parseInt($postOrig.attr('data-id'))); |
|
|
|
$replyText.val(""); |
|
$replyText.attr("placeholder", polyglot.t("Your message was sent!")); |
|
|
|
setTimeout( function() {$.MAL.goHome();}, 1000); |
|
}); |
|
} |
|
|
|
function installDMSendClick(peerAlias) { |
|
$('.dm-submit').off('click').on('click', {peerAlias: peerAlias}, |
|
function (event) { |
|
muteEvent(event, true); |
|
|
|
var elemTextArea = $(event.target).closest('.post-area-new').find('textarea'); |
|
if (!elemTextArea.val()) |
|
return; |
|
|
|
newDirectMsg(encode_utf8(elemTextArea.val()), event.data.peerAlias); |
|
elemTextArea.val(''); |
|
} |
|
); |
|
} |
|
|
|
function installRetransmitConfirmClick() { |
|
var $postConfirmRt = $(".retransmit-confirm"); |
|
$postConfirmRt.off('click').on('click', function (e) { |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
|
|
var $postOrig = $("#rt .rt-original-post .post-data"); |
|
|
|
$.mobile.loading('show'); |
|
newRtMsg($postOrig); |
|
$.MAL.goHome(); |
|
}); |
|
} |
|
|
|
function installUserSearchHandler() { |
|
$('.userMenu-search-field') |
|
.off('click input') |
|
.on('keyup', userSearchEnter) |
|
.on('click keyup', |
|
{hashtags: true, handleRet: processDropdownUserResults, |
|
handleRetZero: closeSearchDialog}, userSearchKeypress) |
|
; |
|
} |
|
|
|
function installProfileEditHandlers() { |
|
$('.profile-card-photo.forEdition').on('click', function () {$('#avatar-file').trigger('click');}); |
|
$('#avatar-file').on('change', handleAvatarFileSelectMobile); |
|
$('.submit-changes').on('click', function (event) { |
|
var saveElem = $(event.target); |
|
var containerElem = saveElem.closest('.content'); |
|
|
|
$.MAL.disableButton(saveElem); |
|
|
|
saveProfile(defaultScreenName, |
|
{ |
|
fullname: containerElem.find('.input-name').val(), |
|
bio: containerElem.find('.input-bio').val(), |
|
location: containerElem.find('.input-location').val(), |
|
url: containerElem.find('.input-url').val(), |
|
tox: containerElem.find('.input-tox').val(), |
|
bitmessage: containerElem.find('.input-bitmessage').val() |
|
}, |
|
function (req) { |
|
saveAvatar(req.peerAlias, req.avatarData, |
|
function () { |
|
alert(polyglot.t('profile_saved')); |
|
$.MAL.goHome(); |
|
}, |
|
null, |
|
function (req) { |
|
alert(polyglot.t('profile_not_saved') + '\n\nCan\'t save avatar data.'); |
|
$.MAL.enableButton(req); |
|
}, |
|
req.saveElem |
|
); |
|
}, |
|
{ |
|
peerAlias: defaultScreenName, |
|
avatarData: containerElem.find('.profile-card-photo.forEdition').attr('src'), |
|
saveElem: saveElem |
|
}, |
|
function (req) { |
|
alert(polyglot.t('profile_not_saved') + '\n\nCan\'t save profile data.'); |
|
$.MAL.enableButton(req); |
|
}, |
|
saveElem |
|
); |
|
}); |
|
$('.cancel-changes').on('click', $.mobile.back); |
|
} |
|
|
|
function handleAvatarFileSelectMobile(evt) { |
|
var files = evt.target.files; // FileList object |
|
var f = files[0]; |
|
|
|
// Only process image files. |
|
if (f.type === undefined || f.type.match('image.*')) { |
|
var reader; |
|
try { |
|
reader = new FileReader(); |
|
} catch(e) { |
|
alert(polyglot.t('File APIs not supported in this browser.')); |
|
return; |
|
} |
|
|
|
reader.onload=function(e){ |
|
var img=new Image(); |
|
img.onload=function(){ |
|
var MAXWidthHeight=64; |
|
var r=MAXWidthHeight/Math.max(this.width,this.height), |
|
w=Math.round(this.width*r), |
|
h=Math.round(this.height*r), |
|
c=document.createElement("canvas"); |
|
c.width=w;c.height=h; |
|
c.getContext("2d").drawImage(this,0,0,w,h); |
|
|
|
var imgURL = undefined; |
|
var encoder = new JPEGEncoder(); |
|
for(var q = 90; (!imgURL || imgURL.length > 4096) && q > 10; q -= 1) { |
|
imgURL = encoder.encode(c.getContext("2d").getImageData(0,0,w,h), q); |
|
console.log( "q: " + q + " url size: " + imgURL.length ); |
|
} |
|
$(".profile-card-photo.forEdition").attr("src", imgURL ); |
|
} |
|
img.src=e.target.result; |
|
} |
|
|
|
// Read in the image file as a data URL. |
|
reader.readAsDataURL(f); |
|
} |
|
} |
|
|
|
function handleClickOpenConversation(event) { |
|
event.stopPropagation(); |
|
event.preventDefault(); |
|
|
|
var userpost = $(event.target).closest(event.data.feeder).attr('data-userpost'); |
|
|
|
$.mobile.loading('show'); |
|
$.mobile.navigate('#post?userpost=' + encodeURIComponent(userpost)); |
|
} |
|
|
|
|
|
function clearProfilePage() { |
|
$("#profile .profile-card-photo").attr("src","img/grayed_avatar_placeholder_24.png"); |
|
$("#profile .profile-name").text(""); |
|
$("#profile .profile-location").text(""); |
|
$("#profile .profile-url").text(""); |
|
$("#profile .profile-url").attr("href",""); |
|
$("#profile .profile-location").text(""); |
|
$("#profile .posts").text(""); |
|
} |
|
|
|
// handler of scroll bottom to request older posts |
|
function reachedScrollBottom() { |
|
var curPage = $.mobile.activePage.attr("id"); |
|
if( curPage == "home" ) { |
|
if( timelineLoaded ) { |
|
requestTimelineUpdate("older", postsPerRefresh, followingUsers); |
|
} |
|
} |
|
} |
|
|
|
function encode_utf8(s) { |
|
// only needed in android 2.3 - why? |
|
var ua = navigator.userAgent; |
|
if( ua.indexOf("Android") >= 0 ) |
|
{ |
|
var androidversion = parseFloat(ua.slice(ua.indexOf("Android")+8)); |
|
if (androidversion < 3.0) |
|
{ |
|
return unescape(encodeURIComponent(s)); |
|
} |
|
} |
|
return s; |
|
} |
|
|
|
var tmobileQueryReq; |
|
|
|
function setupHashtagOrMention(board, query, resource) { |
|
$.mobile.loading('show'); |
|
board.empty(); |
|
|
|
tmobileQueryReq = queryStart(board, query, resource, undefined, undefined, { |
|
boardAutoAppend: true, |
|
skidoo: function (req) { |
|
var curPage = $.mobile.activePage.attr('id'); |
|
return (curPage !== 'mentions' && curPage !== 'hashtag') || req !== tmobileQueryReq; |
|
} |
|
}); |
|
} |
|
|
|
// every 2 seconds do something page specific. |
|
function tmobileTick() { |
|
var curPage = $.mobile.activePage.attr("id"); |
|
if( curPage == "network" ) { |
|
networkUpdate(); |
|
} |
|
if( curPage == "home" ) { |
|
requestLastHave(); |
|
} |
|
if( curPage == "new-user-modal" ) { |
|
dumpPubkey(defaultScreenName, function(args, pubkey) { |
|
//pubkey = ""; |
|
if( pubkey.length > 0 ) { |
|
follow('twister', true, function() { |
|
$.MAL.goProfileEdit(); |
|
}); |
|
} |
|
}, {} ); |
|
} |
|
} |
|
|
|
$(document).on('mobileinit', function () { |
|
$.mobile.allowCrossDomainPages = true; |
|
$.mobile.zoom.enabled = false; |
|
$.mobile.buttonMarkup.hoverDelay = 0; //defaults 200 |
|
$.mobile.defaultDialogTransition = 'none'; |
|
$.mobile.defaultPageTransition = 'none'; |
|
});
|
|
|