diff --git a/css/style.css b/css/style.css index 283d0dc..4655c31 100644 --- a/css/style.css +++ b/css/style.css @@ -300,6 +300,16 @@ button.follow:hover, button.unfollow:hover, .following-own-modal .following-list opacity: 0.9; } +.userMenu li.userMenu-favs > a { + padding: 0 14px; + opacity: 1; +} + +.userMenu li.userMenu-favs > a:before { + content: '★'; + font-size: 24px; +} + .userMenu li.userMenu-profile > a { background: url(../img/profile.png) no-repeat 5px center; } @@ -1280,6 +1290,7 @@ ol.toptrends-list { .post-favorite:before { content: "★"; + font-size: 18px; } .post-reply:hover, .post-propagate:hover, diff --git a/home.html b/home.html index 89e5136..61b8af6 100644 --- a/home.html +++ b/home.html @@ -76,6 +76,7 @@ +
  • @@ -343,7 +344,7 @@
    Reply Retransmit - + Favorite
    +
    +
    + +
    +
    @@ -662,6 +671,7 @@ +
    diff --git a/js/interface_common.js b/js/interface_common.js index 90d9c8e..9cf222b 100644 --- a/js/interface_common.js +++ b/js/interface_common.js @@ -510,6 +510,39 @@ function updateQueryModal(req) { requestQuery(req); } +function openFavsModal(event) { + if (event && typeof event.stopPropagation === 'function') { + event.preventDefault(); + event.stopPropagation(); + } + + var userInfo = $(this).closest('[data-screen-name]'); + var peerAlias = ''; + if (userInfo.length) + peerAlias = userInfo.attr('data-screen-name'); + else if (defaultScreenName) + peerAlias = defaultScreenName; + else { + alertPopup({ + //txtTitle: polyglot.t(''), add some title (not 'error', please) or just KISS + txtMessage: polyglot.t('No favs here because you are not logged in.') + }); + return; + } + + window.location.hash = '#favs?user=' + peerAlias; +} + +function openFavsModalHandler(peerAlias) { + var modal = openModal({ + classAdd: 'hashtag-modal', + content: $('#hashtag-modal-template').children().clone(true), + title: polyglot.t('users_favs', {username: peerAlias}) + }); + + setupQueryModalUpdating(modal.content.find('.postboard-posts'), peerAlias, 'fav'); +} + function openMentionsModal(event) { if (event && typeof event.stopPropagation === 'function') { event.preventDefault(); @@ -1131,7 +1164,7 @@ function loadModalFromHash() { // FIXME rework hash scheme from '#following?user=twister' to something like '#/@twister/following' if (hashdata[0] !== '#web+twister') - hashdata = hashstring.match(/(hashtag|profile|mentions|directmessages|followers|following|conversation)\?(?:group|user|hashtag|post)=(.+)/); + hashdata = hashstring.match(/(hashtag|profile|mentions|directmessages|followers|following|conversation|favs)\?(?:group|user|hashtag|post)=(.+)/); if (hashdata && hashdata[1] !== undefined && hashdata[2] !== undefined) { if (hashdata[1] === 'profile') @@ -1158,6 +1191,8 @@ function loadModalFromHash() { splithashdata2 = hashdata[2].split(':'); openConversationModal(splithashdata2[0], splithashdata2[1]); } + else if (hashdata[1] === 'favs') + openFavsModalHandler(hashdata[2]); } else if (hashstring === '#directmessages') openCommonDMsModal(); else if (hashstring === '#followers') @@ -1246,6 +1281,49 @@ function reTwistPopup(event, post, textArea) { replyArea.find('.post-submit').addClass('with-reference'); } +function favPopup(event, post, textArea) { + event.stopPropagation(); + + if (!defaultScreenName) { + alertPopup({ + txtMessage: polyglot.t('You have to log in to favorite messages.') + }); + return; + } + + if (typeof post === 'undefined') + post = $.evalJSON($(event.target).closest('.post-data').attr('data-userpost')); + + var modal = openModal({ + classBase: '.prompt-wrapper', + classAdd: 'fav-this', + title: polyglot.t('fav_this') + }); + + modal.content + .append(postToElem(post, '')) + .append($('#fav-modal-template').children().clone(true)) + ; + /* + //TODO: favs can be also commented + var replyArea = modal.content.find('.post-area .post-area-new'); + if (typeof textArea === 'undefined') { + textArea = replyArea.find('textarea'); + var textAreaPostInline = modal.content.find('.post .post-area-new textarea'); + $.each(['placeholder', 'data-reply-to'], function(i, attribute) { + textArea.attr(attribute, textAreaPostInline.attr(attribute)); + }); + } else { + replyArea.find('textarea').replaceWith(textArea); + if (textArea.val()) { + textArea.focus(); + replyArea.addClass('open'); + } + } + replyArea.find('.post-submit').addClass('with-reference'); + */ +} + // Expande Área do Novo post function replyInitPopup(e, post, textArea) { var modal = openModal({ @@ -2298,6 +2376,17 @@ function retweetSubmit(event) { closePrompt(prompt); } +function favSubmit(event) { + event.preventDefault(); + event.stopPropagation(); + + var prompt = $(event.target).closest('.prompt-wrapper'); + var priv = (event.target.className.indexOf('private') > -1); + + newFavMsg(prompt.find('.post-data'), priv); + closePrompt(prompt); +} + function changeStyle() { var style, profile, menu; var theme = $.Options.theme.val; @@ -2442,6 +2531,7 @@ function initInterfaceCommon() { $('.post-text').on('click', 'a', muteEvent); $('.post-reply').on('click', postReplyClick); $('.post-propagate').on('click', reTwistPopup); + $('.post-favorite').on('click', favPopup); $('.userMenu-config').clickoutside(closeThis.bind($('.config-menu'))); $('.userMenu-config-dropdown').on('click', dropDownMenu); $('#post-template.module.post').on('click', function(event) { @@ -2461,6 +2551,8 @@ function initInterfaceCommon() { ; $('.post-submit').on('click', postSubmit); $('.modal-propagate').on('click', retweetSubmit); + $('.modal-fav-public').on('click', favSubmit); + $('.modal-fav-private').on('click', favSubmit); $('.expanded-content .show-more').on('mouseup', {feeder: '.module.post.original.open .module.post.original .post-data'}, handleClickOpenConversation) .on('click', muteEvent) // to prevent post collapsing @@ -2476,6 +2568,8 @@ function initInterfaceCommon() { //$('.open-following-modal').on('click', openFollowingModal); $('.userMenu-connections a').on('click', openMentionsModal); $('.mentions-from-user').on('click', openMentionsModal); + $('.userMenu-favs a').on('click', openFavsModal); + $('.favs-from-user').on('click', openFavsModal); $('#hashtag-modal-template .postboard-news').on('click', function () { $(this).hide(); diff --git a/js/interface_localization.js b/js/interface_localization.js index a90e3ed..9f48289 100644 --- a/js/interface_localization.js +++ b/js/interface_localization.js @@ -361,6 +361,11 @@ if(preferredLanguage == "en"){ "IP Overhead Upload:": "IP Overhead Upload:", "Payload Download:": "Payload Download:", "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } if(preferredLanguage == "es"){ @@ -681,6 +686,24 @@ if(preferredLanguage == "es"){ "Sound": "Sonido", "Users": "Usuarios", "Direct Message's copy to self": "Direct Message's copy to self", + "Traffic information": "Traffic information", + "DHT Torrents:": "DHT Torrents:", + "Peers:": "Peers:", + "Peer List Size:": "Peer List Size:", + "Active Requests:": "Active Requests:", + "Download:": "Download:", + "Upload:": "Upload:", + "DHT Download:": "DHT Download:", + "DHT Upload:": "DHT Upload:", + "IP Overhead Download:": "IP Overhead Download:", + "IP Overhead Upload:": "IP Overhead Upload:", + "Payload Download:": "Payload Download:", + "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } @@ -1001,6 +1024,23 @@ if(preferredLanguage == "uk"){ "Direct Message's copy to self": "Повідомлення скопійовано самому собі", "Traffic information": "Статистика трафіку", "Direct messages with": "Співбесіда з", + "DHT Torrents:": "DHT Torrents:", + "Peers:": "Peers:", + "Peer List Size:": "Peer List Size:", + "Active Requests:": "Active Requests:", + "Download:": "Download:", + "Upload:": "Upload:", + "DHT Download:": "DHT Download:", + "DHT Upload:": "DHT Upload:", + "IP Overhead Download:": "IP Overhead Download:", + "IP Overhead Upload:": "IP Overhead Upload:", + "Payload Download:": "Payload Download:", + "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } @@ -1338,6 +1378,11 @@ if(preferredLanguage == "zh-CN"){ "IP Overhead Upload:": "IP层开销上传:", "Payload Download:": "有效载荷下载:", "Payload Upload:": "有效载荷上传:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } @@ -1659,6 +1704,24 @@ if(preferredLanguage == "nl"){ "Sound": "Sound", "Users": "Users", "Direct Message's copy to self": "Direct Message's copy to self", + "Traffic information": "Traffic information", + "DHT Torrents:": "DHT Torrents:", + "Peers:": "Peers:", + "Peer List Size:": "Peer List Size:", + "Active Requests:": "Active Requests:", + "Download:": "Download:", + "Upload:": "Upload:", + "DHT Download:": "DHT Download:", + "DHT Upload:": "DHT Upload:", + "IP Overhead Download:": "IP Overhead Download:", + "IP Overhead Upload:": "IP Overhead Upload:", + "Payload Download:": "Payload Download:", + "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } @@ -1978,6 +2041,24 @@ if(preferredLanguage == "it"){ "Sound": "Sound", "Users": "Users", "Direct Message's copy to self": "Direct Message's copy to self", + "Traffic information": "Traffic information", + "DHT Torrents:": "DHT Torrents:", + "Peers:": "Peers:", + "Peer List Size:": "Peer List Size:", + "Active Requests:": "Active Requests:", + "Download:": "Download:", + "Upload:": "Upload:", + "DHT Download:": "DHT Download:", + "DHT Upload:": "DHT Upload:", + "IP Overhead Download:": "IP Overhead Download:", + "IP Overhead Upload:": "IP Overhead Upload:", + "Payload Download:": "Payload Download:", + "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } @@ -2299,6 +2380,24 @@ if(preferredLanguage == "fr"){ "Sound": "Sound", "Users": "Users", "Direct Message's copy to self": "Direct Message's copy to self", + "Traffic information": "Traffic information", + "DHT Torrents:": "DHT Torrents:", + "Peers:": "Peers:", + "Peer List Size:": "Peer List Size:", + "Active Requests:": "Active Requests:", + "Download:": "Download:", + "Upload:": "Upload:", + "DHT Download:": "DHT Download:", + "DHT Upload:": "DHT Upload:", + "IP Overhead Download:": "IP Overhead Download:", + "IP Overhead Upload:": "IP Overhead Upload:", + "Payload Download:": "Payload Download:", + "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "Favorites": "Favorites", + "You have to log in to favorite messages.": "You have to log in to favorite messages." + }; } @@ -2626,6 +2725,24 @@ if(preferredLanguage == "ru"){ "New post": "Новый пост", "Search": "Поиск", "Direct Msg": "ЛС", + "Traffic information": "Traffic information", + "DHT Torrents:": "DHT Torrents:", + "Peers:": "Peers:", + "Peer List Size:": "Peer List Size:", + "Active Requests:": "Active Requests:", + "Download:": "Download:", + "Upload:": "Upload:", + "DHT Download:": "DHT Download:", + "DHT Upload:": "DHT Upload:", + "IP Overhead Download:": "IP Overhead Download:", + "IP Overhead Upload:": "IP Overhead Upload:", + "Payload Download:": "Payload Download:", + "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } @@ -2728,7 +2845,7 @@ if(preferredLanguage == "de"){ "in postboard": "in der Timeline", "in search result": "in den Suchergebnissen", "in top trends": "in den Top Trends", - "new_posts": "%{smart_count} neuer Post |||| %{smart_count} neue Posts", + "new_posts": "%{smart_count} neuer Post |||| %{smart_count} neue Posts", /* FIXME: duplicate */ "new_mentions": "%{smart_count} neue Erwähnung |||| %{smart_count} neue Erwähnungen", "new_direct_messages": "%{smart_count} neue Direktnachricht |||| %{smart_count} neue Direktnachrichten", "new_group_messages": "%{smart_count} neue Gruppen-Nachricht |||| %{smart_count} neue Gruppen-Nachrichten", @@ -2840,7 +2957,7 @@ if(preferredLanguage == "de"){ "Options": "Einstellungen", "Switch to Promoted posts": "Wechsle zu Promoted Nachrichten", "Switch to Normal posts": "Switch to Normal posts", - "new_posts": "%{smart_count} neue Nachricht |||| %{smart_count} neue Nachrichten", + "new_posts": "%{smart_count} neue Nachricht |||| %{smart_count} neue Nachrichten", /* FIXME: duplicate */ "Use language": "Sprache einstellen", "Ignore": "Ignorieren", "Ignore and clear out": "Ignore and clear out", @@ -2949,6 +3066,24 @@ if(preferredLanguage == "de"){ "Sound": "Sound", "Users": "Users", "Direct Message's copy to self": "Kopie der Direktnachricht an mich selbst", + "Traffic information": "Traffic information", + "DHT Torrents:": "DHT Torrents:", + "Peers:": "Peers:", + "Peer List Size:": "Peer List Size:", + "Active Requests:": "Active Requests:", + "Download:": "Download:", + "Upload:": "Upload:", + "DHT Download:": "DHT Download:", + "DHT Upload:": "DHT Upload:", + "IP Overhead Download:": "IP Overhead Download:", + "IP Overhead Upload:": "IP Overhead Upload:", + "Payload Download:": "Payload Download:", + "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } @@ -3267,6 +3402,24 @@ if(preferredLanguage == "ja"){ "Sound": "Sound", "Users": "Users", "Direct Message's copy to self": "Direct Message's copy to self", + "Traffic information": "Traffic information", + "DHT Torrents:": "DHT Torrents:", + "Peers:": "Peers:", + "Peer List Size:": "Peer List Size:", + "Active Requests:": "Active Requests:", + "Download:": "Download:", + "Upload:": "Upload:", + "DHT Download:": "DHT Download:", + "DHT Upload:": "DHT Upload:", + "IP Overhead Download:": "IP Overhead Download:", + "IP Overhead Upload:": "IP Overhead Upload:", + "Payload Download:": "Payload Download:", + "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } @@ -3580,7 +3733,6 @@ if(preferredLanguage == "pt-BR"){ "post_rt_time_prep": "at", "undo": "undo", "Daemon exited...": "Daemon exited...", - "Secret Key": "Secret Key", "Copy to clipboard": "Copy to clipboard", "Full name here": "Full name here", "Describe yourself": "Describe yourself", @@ -3592,6 +3744,24 @@ if(preferredLanguage == "pt-BR"){ "Sound": "Sound", "Users": "Users", "Direct Message's copy to self": "Direct Message's copy to self", + "Traffic information": "Traffic information", + "DHT Torrents:": "DHT Torrents:", + "Peers:": "Peers:", + "Peer List Size:": "Peer List Size:", + "Active Requests:": "Active Requests:", + "Download:": "Download:", + "Upload:": "Upload:", + "DHT Download:": "DHT Download:", + "DHT Upload:": "DHT Upload:", + "IP Overhead Download:": "IP Overhead Download:", + "IP Overhead Upload:": "IP Overhead Upload:", + "Payload Download:": "Payload Download:", + "Payload Upload:": "Payload Upload:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } @@ -3912,6 +4082,24 @@ if(preferredLanguage == "tr"){ "Sound": "Ses", "Users": "Kullanıcılar", "Direct Message's copy to self": "Özel iletinin kopyasını sakla", + "Traffic information": "Trafik bilgileri", + "DHT Torrents:": "DHT Torrentleri:", + "Peers:": "Eşler:", + "Peer List Size:": "Eş listesi uzunluğu:", + "Active Requests:": "Aktif istekler:", + "Download:": "İndirme:", + "Upload:": "Yükleme:", + "DHT Download:": "DHT İndirme:", + "DHT Upload:": "DHT Yükleme:", + "IP Overhead Download:": "IP Başlık İndirme:", + "IP Overhead Upload:": "IP Başlık Yükleme:", + "Payload Download:": "İçerik İndirme:", + "Payload Upload:": "İçerik Yükleme:", + "No favs here because you are not logged in." : "Giriş yapmadan favorileri göremezsin.", + "users_favs": "@%{username} kullanıcısının favorileri", + "Favorites": "Favoriler", + "You have to log in to favorite messages.": "İletileri favorine eklemek için giriş yapmalısın.", + "fav_this": "Sana özel mi?" }; } @@ -4248,6 +4436,11 @@ if(preferredLanguage == "cs"){ "IP Overhead Upload:": "IP Overhead - odesílání:", "Payload Download:": "Data aplikace - stahování:", "Payload Upload:": "Data aplikace - odesílání:", + "No favs here because you are not logged in." : "No favs here because you are not logged in.", + "users_favs": "Favorites of @%{username}", + "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?" }; } diff --git a/js/twister_actions.js b/js/twister_actions.js index 9bf55d1..df56d09 100644 --- a/js/twister_actions.js +++ b/js/twister_actions.js @@ -319,6 +319,39 @@ function newRtMsg(postData, msg) { } } +function newFavMsg(postData, priv, msg) { + var userpost = $.evalJSON(postData.attr('data-content_to_rt')); + var sig_userpost = postData.attr('data-content_to_sigrt'); + + if (typeof sig_userpost === 'undefined') { + alert(polyglot.t('error', + {error: 'can\'t sig_userpost is not deifned'} + )); + + return; + } + var rtObj = {sig_userpost: sig_userpost, userpost: userpost}; + + if (typeof lastPostId !== 'undefined') { + if (typeof _sendedPostIDs !== 'undefined') + _sendedPostIDs.push(lastPostId + 1); + + var params = [defaultScreenName, lastPostId + 1, rtObj, priv]; + + if (typeof msg !== 'undefined') + params.push(msg); + + twisterRpc('newfavmsg', params, + function(arg, ret) {incLastPostId();}, null, + function(arg, ret) {var msg = ('message' in ret) ? ret.message : ret; + alert(polyglot.t('ajax_error', {error: msg})); + }, null + ); + } else { + alert(polyglot.t('Internal error: lastPostId unknown (following yourself may fix!)')); + } +} + function newShortURI(uri, cbFunc, cbReq) { if (!uri || !defaultScreenName) return; if (parseInt(twisterVersion) < 93500) { @@ -413,14 +446,22 @@ function clearQueryProcessed(id) { function requestQuery(req) { req.postboard.closest('div').find('.postboard-loading').show(); - dhtget(req.query, req.resource, 'm', - function(req, posts) { - req.posts = posts; - processQuery(req); - }, - req, - req.timeoutArgs - ); + if (req.resource === 'fav'){ + twisterRpc("getfavs", [req.query, 1000], function(req, posts){ + req.posts = posts; + processQuery(req) + }, req); + } + else { + dhtget(req.query, req.resource, 'm', + function (req, posts) { + req.posts = posts; + processQuery(req); + }, + req, + req.timeoutArgs + ); + } } function processQuery(req) { @@ -436,6 +477,10 @@ function processQuery(req) { for (var i = req.posts.length - 1; i >= 0; i--) { var userpost = req.posts[i].userpost; + + if (userpost.fav) + userpost = userpost.fav; + var key = userpost.n + ';' + userpost.time; if (!_queryProcessedMap[req.id][key]) { diff --git a/js/twister_formatpost.js b/js/twister_formatpost.js index 79fd1e5..9e734cc 100644 --- a/js/twister_formatpost.js +++ b/js/twister_formatpost.js @@ -43,6 +43,8 @@ function postToElem(post, kind, promoted) { "dm" : encrypted message (dm) -opt "rt" : original userpost - opt "sig_rt" : sig of rt - opt + "fav" : original userpost - opt + "sif_fav" : sig of fav - opt "reply" : - opt { "n" : reference username @@ -57,6 +59,10 @@ function postToElem(post, kind, promoted) { // Obtain data from userpost var userpost = post.userpost; + //TODO: favorites may have comment also... + if (userpost.fav) + userpost = userpost.fav; + if (post.sig_wort) userpost.sig_wort = post.sig_wort;