diff --git a/css/style.css b/css/style.css index ef791bd..e04d0e2 100644 --- a/css/style.css +++ b/css/style.css @@ -843,13 +843,13 @@ textarea.splited-post { /*********************************** ********************* WHO TO FOLLOW ***********************************/ -.who-to-follow -{ +.who-to-follow, +.new-users { padding: 10px; margin-bottom: 10px; } -.who-to-follow h3 -{ +.who-to-follow h3, +.new-users h3 { display: inline; } .twister-user @@ -1943,32 +1943,39 @@ ol.toptrends-list { ********* WHO TO FOLLOW MODAL ******** **************************************/ -.who-to-follow-modal ol { +.who-to-follow-modal ol, +.new-users-modal ol { margin: 5px; } -.who-to-follow-modal .open-profile-modal:hover { +.who-to-follow-modal .open-profile-modal:hover, +.new-users-modal .open-profile-modal:hover { text-decoration: none; } -.who-to-follow-modal .open-profile-modal span { +.who-to-follow-modal .open-profile-modal span, +.new-users-modal .open-profile-modal span { vertical-align: middle; } -.who-to-follow-modal .open-profile-modal span:hover { +.who-to-follow-modal .open-profile-modal span:hover, +.new-users-modal .open-profile-modal span:hover { text-decoration: underline; } -.who-to-follow-modal .follow { +.who-to-follow-modal .follow, +.new-users-modal .follow { float: right; margin: -30px 10px 0 10px; } -.who-to-follow-modal .twister-user-info span { +.who-to-follow-modal .twister-user-info span, +.new-users-modal .twister-user-info span { vertical-align: bottom; } -.who-to-follow-modal .bio { +.who-to-follow-modal .bio, +.new-users-modal .bio { font-size: 12px; color: rgba( 0, 0, 0, .6 ); } diff --git a/home.html b/home.html index 2ff27ec..66c96bd 100644 --- a/home.html +++ b/home.html @@ -146,6 +146,8 @@ + + @@ -227,6 +229,23 @@ + +
+
+

New Users

+ . + Refresh + . + View All + +
+
+
+
+
+
diff --git a/js/interface_common.js b/js/interface_common.js index ec2acdd..ff248b9 100644 --- a/js/interface_common.js +++ b/js/interface_common.js @@ -741,22 +741,7 @@ function fillWhoToFollowModal(list, hlist, start) { if (followingUsers.indexOf(utf) < 0 && list.indexOf(utf) < 0) { list.push(utf); - var item = itemTmp.clone(true); - - item.find('.twister-user-info').attr('data-screen-name', utf); - item.find('.twister-user-name').attr('href', $.MAL.userUrl(utf)); - item.find('.twister-by-user-name').attr('href', $.MAL.userUrl(followingUsers[i])); - item.find('.twister-user-tag').text('@' + utf); - - getAvatar(utf, item.find('.twister-user-photo')); - getFullname(utf, item.find('.twister-user-full')); - getBioToElem(utf, item.find('.bio')); - getFullname(followingUsers[i], item.find('.followed-by').text(followingUsers[i])); - getStatusTime(utf, item.find('.latest-activity .time')); - - item.find('.twister-user-remove').remove(); - - hlist.append(item); + processWhoToFollowSuggestion(hlist, utf, followingUsers[i]); } } } @@ -782,12 +767,32 @@ function openWhoToFollowModal() { modal.content.on('scroll', function() { if (modal.content.scrollTop() >= hlist.height() - modal.content.height() - 20) { - if (!fillWhoToFollowModal(tmplist, hlist, tmplist.length)) + if (!fillWhoToFollowModal(tmplist, modal.self, tmplist.length)) modal.content.off('scroll'); } }); - fillWhoToFollowModal(tmplist, hlist, 0); + fillWhoToFollowModal(tmplist, modal.self, 0); +} + +function openNewUsersModal() { + var modal = openModal({ + classAdd: 'new-users-modal', + title: polyglot.t('New Users') + }); + + var hlist = $('') + .appendTo(modal.content); + var count = 10; + + modal.content.on('scroll', function() { + if (modal.content.scrollTop() >= hlist.height() - modal.content.height() - 20) { + !getLastNUsers(5, count, modal.self); + count += 10; + } + }); + + getLastNUsers(10, 0, modal.self); } function openModalUriShortener() @@ -1237,6 +1242,8 @@ function loadModalFromHash() { openWhoToFollowModal(); else if (hashstring === '#/uri-shortener') openModalUriShortener(); + else if (hashstring === '#newusers') + openNewUsersModal(); } function initHashWatching() { diff --git a/js/interface_home.js b/js/interface_home.js index 5b1984f..8d7f0a0 100644 --- a/js/interface_home.js +++ b/js/interface_home.js @@ -100,6 +100,11 @@ var InterfaceFunctions = function() { else killInterfaceModule('who-to-follow'); + if ($.Options.NewUsers.val === 'enable') + initNewUsers(); + else + killInterfaceModule('new-users'); + if ($.Options.TwistdayReminder.val === 'enable') initTwistdayReminder(); else @@ -200,6 +205,29 @@ function refreshWhoToFollow() { } } +function initNewUsers() { + var nus = initInterfaceModule('new-users'); + + if (nus.length) { + var nusRefresh = nus.find('.refresh-users'); + nusRefresh.on('click', refreshNewUsers); + setTimeout(function() {nusRefresh.click();}, 100); + } +} + +function refreshNewUsers() { + var module = $('.module.new-users'); + var list = module.find('.follow-suggestions'); + + if (list.length) { + list.empty().hide(); + module.find('.refresh-users').hide(); + module.find('.loading-roller').show(); + + getLastNUsers(3, 0, module); + } +} + function initTwistdayReminder() { var $module = initInterfaceModule('twistday-reminder'); diff --git a/js/interface_localization.js b/js/interface_localization.js index bef7976..78cf4b3 100644 --- a/js/interface_localization.js +++ b/js/interface_localization.js @@ -372,7 +372,8 @@ if(preferredLanguage == "en"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } if(preferredLanguage == "es"){ @@ -717,7 +718,8 @@ if(preferredLanguage == "es"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -1061,7 +1063,8 @@ if(preferredLanguage == "uk"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -1410,7 +1413,8 @@ if(preferredLanguage == "zh-CN"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -1756,7 +1760,8 @@ if(preferredLanguage == "nl"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -2100,7 +2105,8 @@ if(preferredLanguage == "it"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -2445,7 +2451,8 @@ if(preferredLanguage == "fr"){ "users_favs": "Favorites of @%{username}", "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -2797,7 +2804,8 @@ if(preferredLanguage == "ru"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -3145,7 +3153,8 @@ if(preferredLanguage == "de"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -3488,7 +3497,8 @@ if(preferredLanguage == "ja"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -3837,7 +3847,8 @@ if(preferredLanguage == "pt-BR"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } @@ -4182,7 +4193,8 @@ if(preferredLanguage == "tr"){ "Favorites": "Favoriler", "You have to log in to favorite messages.": "İletileri favorine eklemek için giriş yapmalısın.", "fav_this": "Sana özel mi?", - "Last activity": "Son etkinlik" + "Last activity": "Son etkinlik", + "New Users": "Yeni Kullanıcılar" }; } @@ -4530,7 +4542,8 @@ if(preferredLanguage == "cs"){ "Favorites": "Favorites", "You have to log in to favorite messages.": "You have to log in to favorite messages.", "fav_this": "Is it for you only?", - "Last activity": "Last activity" + "Last activity": "Last activity", + "New Users": "New Users" }; } diff --git a/js/options.js b/js/options.js index 2acd553..8eb5612 100644 --- a/js/options.js +++ b/js/options.js @@ -41,6 +41,10 @@ function twisterOptions() { name: 'WhoToFollow', valDefault: 'enable' }); + this.add({ + name: 'NewUsers', + valDefault: 'enable' + }); this.add({ name: 'TwistdayReminder', valDefault: 'enable', diff --git a/js/twister_following.js b/js/twister_following.js index c736b05..98de68e 100644 --- a/js/twister_following.js +++ b/js/twister_following.js @@ -15,6 +15,8 @@ var _searchKeypressTimer = undefined; var _lastSearchUsersResults = []; var _lastSearchUsersResultsRemovedFromDHTgetQueue = true; var _lastLoadFromDhtTime = 0; +var _lastProcessedBlock = -1; +var knownNewUsers = []; var twisterFollowingO = undefined; @@ -427,6 +429,36 @@ function followingEmptyOrMyself() { return (!followingUsers.length || (followingUsers.length === 1 && followingUsers[0] === defaultScreenName)) } +function getLastNUsers(n,offset,module) { + + for (var i = offset; i < knownNewUsers.length && i < offset + n; i++) + processWhoToFollowSuggestion(module, knownNewUsers[i]); + + if (knownNewUsers.length >= n + offset) + return; + + if (_lastProcessedBlock == -1) + requestBestBlock(processBlockUsers, {n: n, offset: offset, module: module}); + else + requestNthBlock(_lastProcessedBlock - 1, processBlockUsers, {n: n, offset: offset, module: module}); +} + +function processBlockUsers(block, users){ + _lastProcessedBlock = block.height; + + if (knownNewUsers.length + block.usernames.length < users.n + users.offset) + setTimeout(function(){requestBlock(block.previousblockhash, processBlockUsers, users);}, 100); + + for (var i = 0; i < block.usernames.length; i++) { + if (knownNewUsers.indexOf(block.usernames[i]) == -1) { + processWhoToFollowSuggestion(users.module, block.usernames[i]); + knownNewUsers.push(block.usernames[i]); + if (knownNewUsers.length >= users.n + users.offset) + break; + } + } +} + // randomly choose a user we follow, get "following1" from him and them // choose a suggestion from their list. this function could be way better, but // that's about the simplest we may get to start with. @@ -446,10 +478,11 @@ function getRandomFollowSuggestion() { var suggested = false; var j = Math.floor(Math.random() * twisterFollowingO.followingsFollowings[followingUsers[i]].following.length); + var module = $('.module.who-to-follow'); for( ; j < twisterFollowingO.followingsFollowings[followingUsers[i]].following.length; j++ ) { if( followingUsers.indexOf(twisterFollowingO.followingsFollowings[followingUsers[i]].following[j]) < 0 && _followSuggestions.indexOf(twisterFollowingO.followingsFollowings[followingUsers[i]].following[j]) < 0) { - processWhoToFollowSuggestion(twisterFollowingO.followingsFollowings[followingUsers[i]].following[j], followingUsers[i]); + processWhoToFollowSuggestion(module, twisterFollowingO.followingsFollowings[followingUsers[i]].following[j], followingUsers[i]); _followSuggestions.push(twisterFollowingO.followingsFollowings[followingUsers[i]].following[j]); suggested = true; break; @@ -501,26 +534,37 @@ function getWhoFollows(peerAlias, elem) { ; } -function processWhoToFollowSuggestion(suggestion, followedBy) { +function processWhoToFollowSuggestion(module, suggestion, followedBy) { if (suggestion) { - var module = $('.module.who-to-follow'); var list = module.find('.follow-suggestions'); var item = $('#follow-suggestion-template').clone(true) .removeAttr('id'); item.find('.twister-user-info').attr('data-screen-name', suggestion); item.find('.twister-user-name').attr('href', $.MAL.userUrl(suggestion)); - item.find('.twister-by-user-name').attr('href', $.MAL.userUrl(followedBy)); item.find('.twister-user-tag').text('@' + suggestion); getAvatar(suggestion, item.find('.twister-user-photo')); - getFullname(followedBy, item.find('.followed-by').text(followedBy)); getStatusTime(suggestion, item.find('.latest-activity .time')); - item.find('.twister-user-remove').on('click', function() { - item.remove(); - getRandomFollowSuggestion(); - }); + if (module.hasClass('who-to-follow') || module.hasClass('who-to-follow-modal')) { + item.find('.twister-by-user-name').attr('href', $.MAL.userUrl(followedBy)); + getFullname(followedBy, item.find('.followed-by').text(followedBy)); + item.find('.twister-user-remove').on('click', function () { + item.remove(); + getRandomFollowSuggestion(); + }); + } + else if (module.hasClass('new-users') || module.hasClass('new-users-modal')){ + item.find('.followers').remove(); + item.find('.twister-user-remove').remove(); + } + + if (module.hasClass('modal-wrapper')) { + getFullname(suggestion, item.find('.twister-user-full')); + getBioToElem(suggestion, item.find('.bio')); + item.find('.twister-user-remove').remove(); + } list.append(item).show(); module.find('.refresh-users').show(); diff --git a/js/twister_network.js b/js/twister_network.js index 38694f7..4497937 100644 --- a/js/twister_network.js +++ b/js/twister_network.js @@ -146,46 +146,59 @@ function requestBestBlock(cbFunc, cbArg) { }, {}); } +function requestNthBlock(n, cbFunc, cbArg) { + twisterRpc("getblockhash", [n], + function(args, hash) { + requestBlock(hash, args.cbFunc, args.cbArg); + }, {cbFunc:cbFunc, cbArg:cbArg}, + function(args, ret) { + console.log("getblockhash error"); + }, {}); +} + function requestBlock(hash, cbFunc, cbArg) { twisterRpc("getblock", [hash], function(args, block) { - twisterdLastBlockTime = block.time; - $(".last-block-time").text( timeGmtToText(twisterdLastBlockTime) ); + //twisterdLastBlockTime = block.time; + //$(".last-block-time").text( timeGmtToText(twisterdLastBlockTime) ); if( args.cbFunc ) - args.cbFunc(args.cbArg); + args.cbFunc(block, args.cbArg); }, {cbFunc:cbFunc, cbArg:cbArg}, function(args, ret) { console.log("requestBlock error"); }, {}); } - function networkUpdate(cbFunc, cbArg) { requestNetInfo(function () { - requestBestBlock(function(args) { - var curTime = new Date().getTime() / 1000; - if( twisterdConnections ) { - if( twisterdLastBlockTime > curTime + 3600 ) { - $.MAL.setNetworkStatusMsg(polyglot.t("Last block is ahead of your computer time, check your clock."), false); - twisterdConnectedAndUptodate = false; - } else if( twisterdLastBlockTime > curTime - (2 * 3600) ) { - if( twisterDhtNodes ) { - $.MAL.setNetworkStatusMsg(polyglot.t("Block chain is up-to-date, twister is ready to use!"), true); - twisterdConnectedAndUptodate = true; - } else { - $.MAL.setNetworkStatusMsg(polyglot.t("DHT network down."), false); - twisterdConnectedAndUptodate = true; - } - } else { - var daysOld = (curTime - twisterdLastBlockTime) / (3600*24); - $.MAL.setNetworkStatusMsg(polyglot.t("downloading_block_chain", { days: daysOld.toFixed(2) }), false); - // don't alarm user if blockchain is just a little bit behind - twisterdConnectedAndUptodate = (daysOld < 2); + requestBestBlock(function(block, args) { + + twisterdLastBlockTime = block.time; + $(".last-block-time").text( timeGmtToText(twisterdLastBlockTime) ); + + var curTime = new Date().getTime() / 1000; + if (twisterdConnections) { + if (twisterdLastBlockTime > curTime + 3600) { + $.MAL.setNetworkStatusMsg(polyglot.t("Last block is ahead of your computer time, check your clock."), false); + twisterdConnectedAndUptodate = false; + } else if (twisterdLastBlockTime > curTime - (2 * 3600)) { + if (twisterDhtNodes) { + $.MAL.setNetworkStatusMsg(polyglot.t("Block chain is up-to-date, twister is ready to use!"), true); + twisterdConnectedAndUptodate = true; + } else { + $.MAL.setNetworkStatusMsg(polyglot.t("DHT network down."), false); + twisterdConnectedAndUptodate = true; + } + } else { + var daysOld = (curTime - twisterdLastBlockTime) / (3600 * 24); + $.MAL.setNetworkStatusMsg(polyglot.t("downloading_block_chain", {days: daysOld.toFixed(2)}), false); + // don't alarm user if blockchain is just a little bit behind + twisterdConnectedAndUptodate = (daysOld < 2); + } } - } - if( args.cbFunc ) - args.cbFunc(args.cbArg) + if (args.cbFunc) + args.cbFunc(args.cbArg); }, {cbFunc:cbFunc, cbArg:cbArg} ); }); } diff --git a/options.html b/options.html index 8338e62..ea4645e 100644 --- a/options.html +++ b/options.html @@ -353,6 +353,17 @@
+
+

New Users

+
+
+ +
+
+

Twistday Reminder

diff --git a/theme_calm/css/style.css b/theme_calm/css/style.css index 21f5be0..835dfbb 100644 --- a/theme_calm/css/style.css +++ b/theme_calm/css/style.css @@ -1024,12 +1024,12 @@ textarea.splited-post { /*********************************** ********************* WHO TO FOLLOW ***********************************/ -.who-to-follow -{ +.who-to-follow, +.new-users { padding: 10px; } -.who-to-follow h3 -{ +.who-to-follow h3, +.new-users h3 { display: inline; } .twister-user @@ -2345,19 +2345,23 @@ textarea.splited-post { ********* WHO TO FOLLOW MODAL ******** **************************************/ -.who-to-follow-modal .modal-content { +.who-to-follow-modal .modal-content, +.new-users-modal .modal-content { padding: 15px; } -.who-to-follow-modal ol { +.who-to-follow-modal ol, +.new-users-modal ol { margin: 5px; } -.who-to-follow-modal .open-profile-modal:hover { +.who-to-follow-modal .open-profile-modal:hover, +.new-users-modal .open-profile-modal span:hover { text-decoration: none; } -.who-to-follow-modal .open-profile-modal span { +.who-to-follow-modal .open-profile-modal span, +.new-users-modal .open-profile-modal span { vertical-align: middle; } @@ -2365,16 +2369,19 @@ textarea.splited-post { text-decoration: underline; } -.who-to-follow-modal .follow { +.who-to-follow-modal .follow, +.new-users-modal .follow { float: right; margin: -30px 10px 0 10px; } -.who-to-follow-modal .twister-user-info span { +.who-to-follow-modal .twister-user-info span, +.new-users-modal .twister-user-info span { vertical-align: bottom; } -.who-to-follow-modal .bio { +.who-to-follow-modal .bio, +.new-users-modal .bio { font-size: 12px; color: rgba( 0, 0, 0, .6 ); } diff --git a/theme_nin/css/style.css b/theme_nin/css/style.css index 1f5ba6b..14e9279 100644 --- a/theme_nin/css/style.css +++ b/theme_nin/css/style.css @@ -2159,27 +2159,32 @@ textarea.splited-post { /******** WHO TO FOLLOW ********/ /* line 411, ../sass/style.sass */ -.who-to-follow.module { +.who-to-follow.module, +.new-users.module { width: inherit; margin-bottom: 20px; } /* line 414, ../sass/style.sass */ -.who-to-follow small { +.who-to-follow small, +.new-users small { display: none; } /* line 416, ../sass/style.sass */ -.who-to-follow h3 { +.who-to-follow h3, +.new-users h3 { float: left; } /* line 418, ../sass/style.sass */ -.who-to-follow ol { +.who-to-follow ol, +.new-users ol { clear: both; } -.who-to-follow .twister-user-info { +.who-to-follow .twister-user-info, +.new-users .twister-user-info { margin-top: 8px; } @@ -3130,45 +3135,53 @@ ol.toptrends-list a:hover { /******* WHO TO FOLLOW MODAL****** */ /* line 943, ../sass/style.sass */ -.modal-wrapper.who-to-follow-modal { +.modal-wrapper.who-to-follow-modal, +.modal-wrapper.new-users-modal { width: 520px; height: 580px; margin: -290px 0 0 -260px; } /* line 949, ../sass/style.sass */ -.who-to-follow-modal .modal-content { +.who-to-follow-modal .modal-content, +.new-users-modal .modal-content { padding: 15px; } /* line 955, ../sass/style.sass */ -.who-to-follow-modal ol { +.who-to-follow-modal ol, +.new-users-modal ol { margin: 5px; } /* line 958, ../sass/style.sass */ -.who-to-follow-modal .open-profile-modal:hover { +.who-to-follow-modal .open-profile-modal:hover, +.new-users-modal .open-profile-modal:hover { text-decoration: none; } /* line 960, ../sass/style.sass */ -.who-to-follow-modal .twister-user { - position: relative; +.who-to-follow-modal .twister-user, +.new-users-modal .twister-user { +position: relative; padding: 5px; } /* line 963, ../sass/style.sass */ -.who-to-follow-modal .twister-user-photo { +.who-to-follow-modal .twister-user-photo, +.new-users-modal .twister-user-photo { position: relative; left: 0; float: left; display: block; } /* line 968, ../sass/style.sass */ -.who-to-follow-modal .twister-user-info { +.who-to-follow-modal .twister-user-info, +.new-users-modal .twister-user-info { position: relative; margin-top: 4px; padding-left: 70px; width: auto; } /* line 972, ../sass/style.sass */ -.who-to-follow-modal .bio { +.who-to-follow-modal .bio, +.new-users-modal .bio { color: rgba(0, 0, 0, 0.6); font-style: italic; }