From 2a0a9267b8d16939e0b951fbc8f0ea44fa28ae3d Mon Sep 17 00:00:00 2001 From: erqan Date: Mon, 5 May 2014 22:28:15 +0300 Subject: [PATCH 1/4] discovering some followers and bringing to life some death functions around of 'who to follow' --- css/style.css | 73 ++++++++++++++++++++++++ following.html | 20 ++++--- home.html | 22 +++++--- js/interface_common.js | 73 +++++++++++++++++++++++- js/interface_home.js | 22 +++++++- js/interface_localization.js | 12 +++- js/options.js | 13 +++++ js/twister_actions.js | 1 + js/twister_following.js | 105 +++++++++++++++++++++++++++-------- js/twister_io.js | 35 ++++++++++-- options.html | 14 ++++- 11 files changed, 339 insertions(+), 51 deletions(-) diff --git a/css/style.css b/css/style.css index 9644069..f2a031f 100644 --- a/css/style.css +++ b/css/style.css @@ -81,6 +81,14 @@ h3 content: ""; clear: both; } +.isFollowing:after { + color: #1a1; + content: '\2714'; +} +.notFollowing:after { + color: #a11; + content: '\2718'; +} /************************************* **************************** BUTTONS ** **************************************/ @@ -275,6 +283,11 @@ button.disabled:hover border: solid 1px rgba( 69, 71, 77, .1 ); background: #fff; } +.options .module +{ + margin: 5px; + padding: 5px; +} .messages-qtd { position: absolute; @@ -513,6 +526,21 @@ button.disabled:hover { text-decoration: none; } +.who-follow +{ + height: auto; + background-color: rgba(69, 71, 77, 0.1); + overflow: hidden; +} +.mini-follower-link +{ + display: inline-block; + margin-right: 10px; +} +.mini-follower-link:before +{ + content: " \2027"; +} /*********************************** ********************* POST AREA **** ***********************************/ @@ -1457,6 +1485,51 @@ ol.toptrends-list { text-decoration: underline; } /************************************* +******************* WHO TO FOLLOW MODAL +**************************************/ +.who-to-follow-modal .modal-wrapper +{ + width: 560px; + height: 470px; + margin: -200px 0 0 -280px; + overflow-x: hidden; +} +.who-to-follow-modal .modal-content +{ + padding: 15px; + height: 400px; + overflow-y: auto; +} +.who-to-follow-modal .modal-buttons +{ + display: none; +} +.who-to-follow-modal ol +{ + margin: 5px; +} +.who-to-follow-modal .open-profile-modal:hover +{ + text-decoration: none; +} +.who-to-follow-modal .open-profile-modal span +{ + vertical-align: middle; +} +.who-to-follow-modal .open-profile-modal span:hover +{ + text-decoration: underline; +} +.who-to-follow-modal .follow +{ + float: right; + margin: -30px 10px 0 10px; +} +.who-to-follow-modal .twister-user-info span +{ + vertical-align: bottom; +} +/************************************* ****************** LOADER ************ **************************************/ .postboard-loading diff --git a/following.html b/following.html index 8dad248..cc69c26 100644 --- a/following.html +++ b/following.html @@ -364,16 +364,18 @@ -
- + - - - +
diff --git a/home.html b/home.html index 8cc370a..050aaf6 100644 --- a/home.html +++ b/home.html @@ -193,8 +193,10 @@
+ +
-
- + - - - +
diff --git a/js/interface_common.js b/js/interface_common.js index 54a2bd8..b7561a3 100644 --- a/js/interface_common.js +++ b/js/interface_common.js @@ -86,7 +86,7 @@ function timeSincePost(t) { } // -// Profile, mentions, hashtag, and following modal +// Profile, mentions, hashtag, and following modal, who to follow // ----------------------------------- function newProfileModal(username) { @@ -242,6 +242,75 @@ function openFollowingModal(e) $( "."+followingModalClass + " h3" ).text( polyglot.t("followed_by", { username: username }) ); } +function refreshWhoToFollow(e) { + e.stopPropagation(); + e.preventDefault(); + + $('.follow-suggestions').html(''); + + getRandomFollowSuggestion(processSuggestion); + getRandomFollowSuggestion(processSuggestion); + getRandomFollowSuggestion(processSuggestion); +} + +function fillWhoToFollowModal(list, hlist, start) { + for (var i = 0; i < followingUsers.length && list.length < start + 25; i++) { + if (typeof(followingsFollowings[followingUsers[i]]) !== 'undefined') { + for (var j = 0; j < followingsFollowings[followingUsers[i]].length && list.length < start + 25; j++) { + + if (followingUsers.indexOf(followingsFollowings[followingUsers[i]][j]) < 0 && + list.indexOf(followingsFollowings[followingUsers[i]][j]) < 0) { + list.push(followingsFollowings[followingUsers[i]][j]); + + var item = $("#follow-suggestion-template").clone(true); + item.removeAttr("id"); + + item.find(".twister-user-info").attr("data-screen-name", followingsFollowings[followingUsers[i]][j]); + + item.find(".twister-user-name").attr("href", $.MAL.userUrl(followingsFollowings[followingUsers[i]][j])); + item.find(".twister-by-user-name").attr("href", $.MAL.userUrl(followingUsers[i])); + item.find(".twister-user-tag").text("@" + followingsFollowings[followingUsers[i]][j]); + + getAvatar(followingsFollowings[followingUsers[i]][j], item.find(".twister-user-photo")); + getFullname(followingsFollowings[followingUsers[i]][j], item.find(".twister-user-full")); + getBio(followingsFollowings[followingUsers[i]][j], item.find(".bio")); + + var $spanFollowedBy = item.find(".followed-by"); + $spanFollowedBy.text(followingUsers[i]); + getFullname(followingUsers[i], $spanFollowedBy); + + item.find('.twister-user-remove').remove(); + + hlist.append(item); + } + } + } + } +} + +function openWhoToFollowModal(e) { + e.stopPropagation(); + e.preventDefault(); + + var whoToFollowModalClass = "who-to-follow-modal"; + openModal( whoToFollowModalClass ); + + var content = $("." + whoToFollowModalClass + " .modal-content"); + var hlist = $('
    '); + var tmplist = []; + + content.scroll(function(){ + if (content.scrollTop() >= hlist.height() - content.height() - 20){ + fillWhoToFollowModal(tmplist, hlist, tmplist.length); + } + }); + + fillWhoToFollowModal(tmplist, hlist, 0); + + hlist.appendTo( "." + whoToFollowModalClass + " .modal-content" ); + $( "." + whoToFollowModalClass + " h3" ).text( polyglot.t("Who to Follow") ); +} + // // Post actions, submit, count characters // -------------------------------------- @@ -1183,4 +1252,6 @@ function initInterfaceCommon() { $( ".open-following-modal").bind( "click", openFollowingModal ); $( ".userMenu-connections a").bind( "click", openMentionsModal ); + $( ".who-to-follow .refresh-users" ).bind( "click", refreshWhoToFollow ); + $( ".who-to-follow .view-all-users" ).bind( "click", openWhoToFollowModal ); } diff --git a/js/interface_home.js b/js/interface_home.js index 3832f90..2a250f3 100644 --- a/js/interface_home.js +++ b/js/interface_home.js @@ -97,6 +97,26 @@ var InterfaceFunctions = function() } }); + loadSessionData(); + //geting followings of following... + for(var i = 0; i < followingUsers.length; i++) { + if (typeof(followingsFollowings[followingUsers[i]]) === 'undefined') { + loadFollowingFromDht(followingUsers[i], 1, [], 0, function (args, following, seqNum) { + if (following.indexOf(defaultScreenName) > -1) { + if (knownFollowers.indexOf(args) < 0) + knownFollowers.push(args); + } else { + if (notFollowers.indexOf(args) < 0) + notFollowers.push(args); + } + $(".open-followers").attr("title", knownFollowers.length.toString()); + + followingsFollowings[args] = following; + }, followingUsers[i]); + } + } + storeSessionData(); + setTimeout("getRandomFollowSuggestion(processSuggestion)", 1000); setTimeout("getRandomFollowSuggestion(processSuggestion)", 1000); setTimeout("getRandomFollowSuggestion(processSuggestion)", 1000); @@ -117,7 +137,7 @@ var InterfaceFunctions = function() function(args, ret) { console.log("Error with gettrendinghashtags. Older twister daemon?"); }, {}); - + if( args.cbFunc ) args.cbFunc(args.cbArg); }, {cbFunc:cbFunc, cbArg:cbArg}); diff --git a/js/interface_localization.js b/js/interface_localization.js index 3c9ee55..8f8da87 100644 --- a/js/interface_localization.js +++ b/js/interface_localization.js @@ -220,7 +220,11 @@ if(preferredLanguage == "en"){ "RTs those are close to original twist": "RTs those are close to original twist", "Show if the original is older than": "Show if the original is older than", "hour(s)": "hour(s)", - "only numbers are allowed!": "only numbers are allowed!" + "only numbers are allowed!": "only numbers are allowed!", + "Show with every user name": "Show with every user name", + "Show at profile modal only": "Show at profile modal only", + "Show if a user follows me": "Show if a user follows me", + "follows you": "follows you" }; } if(preferredLanguage == "es"){ @@ -1840,7 +1844,11 @@ if(preferredLanguage == "tr"){ "RTs those are close to original twist": "Orjinal twist'e yakın olan RTler", "Show if the original is older than": "Orjinali yandaki süreden daha eskiyse göster", "hour(s)": "saat", - "only numbers are allowed!": "sadece rakam girilebilir!" + "only numbers are allowed!": "sadece rakam girilebilir!", + "Show with every user name": "Tüm kullanıcı adlarının yanında göster", + "Show at profile modal only": "Sadece profilinde göster", + "Show if a user follows me": "Bir kullanıcının beni takip edip etmediğini göster", + "follows you": "seni takip ediyor" }; } diff --git a/js/options.js b/js/options.js index 72aa037..f912f12 100644 --- a/js/options.js +++ b/js/options.js @@ -320,6 +320,18 @@ var TwisterOptions = function() }); }; + this.getIsFollowingMeOpt = function () { + return $.Options.getOption('isFollowingMe'); + }; + + this.setIsFollowingMeOpt = function () { + $('#isFollowingMe')[0].value = this.getIsFollowingMeOpt(); + + $('#isFollowingMe').on('change', function () { + $.Options.setOption(this.id, this.value); + }); + }; + this.InitOptions = function() { this.soundNotifOptions(); this.volumeControl(); @@ -339,6 +351,7 @@ var TwisterOptions = function() this.setHideRepliesOpt(); this.setHideCloseRTsHourOpt(); this.setHideCloseRTsOpt(); + this.setIsFollowingMeOpt(); } } diff --git a/js/twister_actions.js b/js/twister_actions.js index 2a38fc0..6947e85 100644 --- a/js/twister_actions.js +++ b/js/twister_actions.js @@ -191,6 +191,7 @@ function updateProfileData(profileModalContent, username) { getPostsCount( username, profileModalContent.find(".posts-count") ); getFollowers( username, profileModalContent.find(".followers-count") ); getNumFollowing( username, profileModalContent.find(".following-count") ); + getWhoFollows ( username, profileModalContent.find(".who-follow") ); profileModalContent.find(".following-count").parent().attr("href", $.MAL.followingUrl(username)); diff --git a/js/twister_following.js b/js/twister_following.js index 78facd9..15bf88c 100644 --- a/js/twister_following.js +++ b/js/twister_following.js @@ -5,6 +5,9 @@ // Provides random user suggestions to follow. var followingUsers = []; +var knownFollowers = []; +var notFollowers = []; +var followingsFollowings = {}; var _isFollowPublic = {}; var _followsPerPage = 200; var _maxFollowingPages = 50; @@ -41,6 +44,28 @@ function saveFollowingToStorage() { ns.localStorage.set("lastLoadFromDhtTime", _lastLoadFromDhtTime); } +// load followers & following's followings from sessionStorage +function loadSessionData() { + var ns = $.initNamespaceStorage(defaultScreenName); + + if (ns.sessionStorage.isSet("followingsFollowings")) + followingsFollowings = ns.sessionStorage.get("followingsFollowings"); + + if (ns.sessionStorage.isSet("followers")) + knownFollowers = ns.sessionStorage.get("followers"); + + if (ns.sessionStorage.isSet("notFollowers")) + notFollowers = ns.sessionStorage.get("notFollowers"); +} + +// save list of followers & following's followings to sessionStorage +function storeSessionData() { + var ns = $.initNamespaceStorage(defaultScreenName); + ns.sessionStorage.set("followingsFollowings", followingsFollowings); + ns.sessionStorage.set("followers", knownFollowers); + ns.sessionStorage.set("notFollowers", notFollowers); +} + // load public list of following users from dht resources // "following1", "following2" etc. // it will stop loading when resource is empty @@ -256,36 +281,63 @@ function getRandomFollowSuggestion(cbFunc, cbArg) { return; } - var i; - do{ - var i = parseInt( Math.random() * followingUsers.length ); - } while( i < followingUsers.length && followingUsers[i] == defaultScreenName); + var i = parseInt( Math.random() * followingUsers.length ); + + if ( (i < followingUsers.length && followingUsers[i] == defaultScreenName) || + typeof(followingsFollowings[followingUsers[i]]) === 'undefined') { + + setTimeout(getRandomFollowSuggestion, 500, cbFunc, cbArg); + return; + } if( i < followingUsers.length ) { - loadFollowingFromDht( followingUsers[i], 1, [], 0, - function(args, following, seqNum) { - if( following ) { - var suggested = false; - var j = parseInt( Math.random() * following.length ); - for( ; j < following.length; j++ ) { - if( followingUsers.indexOf(following[j]) < 0 && - _followSuggestions.indexOf(following[j]) < 0 ) { - args.cbFunc(args.cbArg, following[j], args.followedBy); - _followSuggestions.push(following[j]); - suggested = true; - break; - } - } - if( !suggested ) { - args.cbFunc(args.cbArg, null, null); - } + var suggested = false; + var j = parseInt( Math.random() * followingsFollowings[followingUsers[i]].length ); + for( ; j < followingsFollowings[followingUsers[i]].length; j++ ) { + if( followingUsers.indexOf(followingsFollowings[followingUsers[i]][j]) < 0 && + _followSuggestions.indexOf(followingsFollowings[followingUsers[i]][j]) < 0 ) { + cbFunc(cbArg, followingsFollowings[followingUsers[i]][j], followingUsers[i]); + _followSuggestions.push(followingsFollowings[followingUsers[i]][j]); + suggested = true; + break; } - }, {cbFunc:cbFunc, cbArg:cbArg, followedBy:followingUsers[i]}); + } + if( !suggested ) { + cbFunc(cbArg, null, null); + } } else { cbFunc(cbArg, null, null); } } +function whoFollows(username) { + var list = []; + + for (var following in followingsFollowings) { + if (followingsFollowings[following].indexOf(username) > -1) { + list.push(following); + } + } + return list; +} + +function getWhoFollows(username, item) { + var list = whoFollows(username); + + for (var i = 0; i < list.length; i++) { + var follower_link = $( '' ); + + // link follower to profile page + follower_link.attr("data-screen-name", list[i]); + follower_link.attr("href", $.MAL.userUrl(list[i])); + follower_link.text(list[i]); + follower_link.on("click", openProfileModal); + getFullname( list[i], follower_link ); + + item.append( follower_link ); + } +} + // adds following users to the interface (following.html) function showFollowingUsers(){ var $notFollowing = $(".not-following-any"); @@ -337,11 +389,16 @@ function processSuggestion(arg, suggestion, followedBy) { getAvatar(suggestion,item.find(".twister-user-photo")); - getFullname(suggestion,item.find(".twister-user")); - $spanFollowedBy = item.find(".followed-by"); + //getFullname(suggestion,item.find(".twister-user")); + var $spanFollowedBy = item.find(".followed-by"); $spanFollowedBy.text(followedBy); getFullname(followedBy,$spanFollowedBy); + item.find('.twister-user-remove').bind("click", function() { + item.remove(); + getRandomFollowSuggestion(processSuggestion); + }); + dashboard.append(item); } } diff --git a/js/twister_io.js b/js/twister_io.js index 34e6fee..2b383d9 100644 --- a/js/twister_io.js +++ b/js/twister_io.js @@ -212,6 +212,31 @@ function getFullname( username, item ){ args.item.text(value); } }, {item: item} ); + if ($.Options.getIsFollowingMeOpt() === 'everywhere' || item.hasClass('profile-name')) { + if (knownFollowers.indexOf(username) > -1) { + item.addClass('isFollowing'); + item.attr("title", polyglot.t("follows you")); + } else if (notFollowers.indexOf(username) > -1) + item.addClass("notFollowing"); + else { + loadFollowingFromDht(username, 1, [], 0, function (args, following, seqNum) { + if (following.indexOf(args.user) > -1) { + item.addClass('isFollowing'); + item.attr("title", polyglot.t("follows you")); + if (knownFollowers.indexOf(args.username) < 0) + knownFollowers.push(args.username); + } else { + item.addClass('notFollowing'); + if (notFollowers.indexOf(args.username) < 0) + notFollowers.push(args.username); + } + + storeSessionData(); + }, {"user": defaultScreenName, "item": item, "username": username}); + } + + $(".open-followers").attr("title", knownFollowers.length.toString()); + } } // get bio and store it in item.text @@ -252,10 +277,12 @@ function getLocation( username, item ){ function getWebpage( username, item ){ getProfileResource( username, "url", item, function(args, val) { - if( val.indexOf("://") < 0 ) { - val = "http://" + val; - } - args.item.attr("href", val); + if(typeof(val) !== 'undefined') { + if (val.indexOf("://") < 0) { + val = "http://" + val; + } + args.item.attr("href", val); + } }, {item:item} ); } diff --git a/options.html b/options.html index c354289..d6e5000 100644 --- a/options.html +++ b/options.html @@ -46,7 +46,7 @@ -
    +
    @@ -258,6 +258,18 @@
    +
    +
    +
    +

    Show if a user follows me

    + +
    +
    +
    +
    From 459a83da6d1fb7ba2663a446d696171ec1d7476d Mon Sep 17 00:00:00 2001 From: erqan Date: Tue, 6 May 2014 02:13:23 +0300 Subject: [PATCH 2/4] .who-to-follow-modal .bio font size and color --- css/style.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/css/style.css b/css/style.css index f2a031f..94be7eb 100644 --- a/css/style.css +++ b/css/style.css @@ -1529,6 +1529,11 @@ ol.toptrends-list { { vertical-align: bottom; } +.who-to-follow-modal .bio +{ + font-size: 12px; + color: rgba( 0, 0, 0, .6 ); +} /************************************* ****************** LOADER ************ **************************************/ From 8e456179c6b6eaea79a9ccdf2354717b6916fc9e Mon Sep 17 00:00:00 2001 From: erqan Date: Tue, 6 May 2014 12:06:45 +0300 Subject: [PATCH 3/4] font-size for who-follow in profile modal --- css/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/css/style.css b/css/style.css index 94be7eb..f479e0e 100644 --- a/css/style.css +++ b/css/style.css @@ -531,6 +531,7 @@ button.disabled:hover height: auto; background-color: rgba(69, 71, 77, 0.1); overflow: hidden; + font-size: 12px; } .mini-follower-link { From 97449fbe466248b92ec186eecb2d3ad59b497700 Mon Sep 17 00:00:00 2001 From: erqan Date: Tue, 6 May 2014 14:43:39 +0300 Subject: [PATCH 4/4] fixing lazy load for full who to follow list --- js/interface_common.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/js/interface_common.js b/js/interface_common.js index b7561a3..b73ca50 100644 --- a/js/interface_common.js +++ b/js/interface_common.js @@ -254,7 +254,8 @@ function refreshWhoToFollow(e) { } function fillWhoToFollowModal(list, hlist, start) { - for (var i = 0; i < followingUsers.length && list.length < start + 25; i++) { + var i; + for (i = 0; i < followingUsers.length && list.length < start + 20; i++) { if (typeof(followingsFollowings[followingUsers[i]]) !== 'undefined') { for (var j = 0; j < followingsFollowings[followingUsers[i]].length && list.length < start + 25; j++) { @@ -286,6 +287,12 @@ function fillWhoToFollowModal(list, hlist, start) { } } } + + if (i >= followingUsers.length - 1) { + return false; + } + // returns true, if there are more... + return true; } function openWhoToFollowModal(e) { @@ -301,7 +308,8 @@ function openWhoToFollowModal(e) { content.scroll(function(){ if (content.scrollTop() >= hlist.height() - content.height() - 20){ - fillWhoToFollowModal(tmplist, hlist, tmplist.length); + if (!fillWhoToFollowModal(tmplist, hlist, tmplist.length)) + content.unbind("scroll"); } });