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 @@
-