diff --git a/QvitterPlugin.php b/QvitterPlugin.php index 1b768d4..4b4986c 100644 --- a/QvitterPlugin.php +++ b/QvitterPlugin.php @@ -218,6 +218,9 @@ class QvitterPlugin extends Plugin { $m->connect(':nickname/notifications', array('action' => 'qvitter', 'nickname' => Nickname::INPUT_FMT)); + $m->connect(':nickname/blocks', + array('action' => 'qvitter', + 'nickname' => Nickname::INPUT_FMT)); $m->connect('settings/qvitter', array('action' => 'qvittersettings')); $m->connect('panel/qvitter', @@ -770,10 +773,14 @@ class QvitterPlugin extends Plugin { $twitter_user['profile_background_color'] = Profile_prefs::getConfigData($profile, 'theme', 'backgroundcolor'); $twitter_user['profile_banner_url'] = Profile_prefs::getConfigData($profile, 'qvitter', 'cover_photo'); - // follows me? + if ($scoped) { - $twitter_user['follows_you'] = $profile->isSubscribed($scoped); - } + // follows me? + $twitter_user['follows_you'] = $profile->isSubscribed($scoped); + + // blocks me? + $twitter_user['blocks_you'] = $profile->hasBlocked($scoped); + } // local user? $twitter_user['is_local'] = $profile->isLocal(); diff --git a/README.md b/README.md index 3c5d1ca..b863b71 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Qvitter ========================================== * Author: Hannes Mannerheim () -* Last mod.: Oct, 2015 +* Last mod.: Jan, 2016 * Version: 5-alpha * Homepage: @@ -87,7 +87,6 @@ Qvitter extends this API in a few undocumented ways. See onRouterInitialized() i for ideas about paths for the API extensions. - Notes ----- diff --git a/css/qvitter.css b/css/qvitter.css index f66d48b..3223dc1 100644 --- a/css/qvitter.css +++ b/css/qvitter.css @@ -4310,40 +4310,43 @@ button.shorten:not(.disabled):active { .edit-profile-button .edit-profile-text, .save-profile-button .edit-profile-text, .abort-edit-profile-button .edit-profile-text, -.crop-and-save-button .edit-profile-text { +.crop-and-save-button .edit-profile-text, +.member-button.member .ismember-text, +.external-follow-button.following .following-text, +.qvitter-follow-button.following .following-text, +.member-button.member:hover .leave-text, +.external-follow-button.following:hover .unfollow-text, +.qvitter-follow-button.following:hover .unfollow-text, +.qvitter-follow-button.blocking .blocking-text, +.qvitter-follow-button.blocking:hover .unblock-text { display:block; height: 28px; line-height: 28px; } .member-button.member .join-text, .external-follow-button.following .follow-text, -.qvitter-follow-button.following .follow-text { - display:none; - height: 28px; - line-height: 28px; - } -.member-button.member .ismember-text, -.external-follow-button.following .following-text, -.qvitter-follow-button.following .following-text { - display:block; - height: 28px; - line-height: 28px; - } +.qvitter-follow-button.following .follow-text, .member-button.member:hover .ismember-text, .external-follow-button.following:hover .following-text, -.qvitter-follow-button.following:hover .following-text { +.qvitter-follow-button.following:hover .following-text, +.qvitter-follow-button.blocking .follow-text, +.qvitter-follow-button.blocking .unfollow-text, +.qvitter-follow-button.blocking:hover .blocking-text { display:none; - height: 28px; - line-height: 28px; - } -.member-button.member:hover .leave-text, -.external-follow-button.following:hover .unfollow-text, -.qvitter-follow-button.following:hover .unfollow-text { - display:block; - height: 28px; - line-height: 28px; } +.user-actions .blocks-you::before { + content:"\f05e"; + color: #aaa; + cursor:default; + font-family: FontAwesome; + font-size: 20px; + line-height: 32px; + margin-right: 5px; +} + + + .queet-box-extras button { box-shadow: none; background:none !important; diff --git a/js/ajax-functions.js b/js/ajax-functions.js index fe58cfd..2cb4d3b 100644 --- a/js/ajax-functions.js +++ b/js/ajax-functions.js @@ -457,6 +457,44 @@ function APIFollowOrUnfollowUser(followOrUnfollow,user_id,this_element,actionOnS }); } +/* · + · + · Post follow or unfollow user request + · + · @param followOrUnfollow: either 'follow' or 'unfollow' + · @param user_id: the user id of the user we want to follow + · @param actionOnSuccess: callback function, false on error, data on success + · + · · · · · · · · · · · · · */ + +function APIBlockOrUnblockUser(blockOrUnblock,user_id,actionOnSuccess) { + + if(blockOrUnblock == 'block') { + var postRequest = 'blocks/create.json'; + } + else if (blockOrUnblock == 'unblock') { + var postRequest = 'blocks/destroy.json'; + } + + $.ajax({ url: window.apiRoot + postRequest, + cache: false, + type: "POST", + data: { + id: user_id + }, + dataType:"json", + error: function(data){ actionOnSuccess(false); console.log(data); }, + success: function(data) { + data = convertEmptyObjectToEmptyArray(data); + data = iterateRecursiveReplaceHtmlSpecialChars(data); + searchForUserDataToCache(data); + updateUserDataInStream(); + actionOnSuccess(data); + } + }); + } + + /* · · diff --git a/js/dom-functions.js b/js/dom-functions.js index 091ccb0..d7f2cbb 100644 --- a/js/dom-functions.js +++ b/js/dom-functions.js @@ -285,6 +285,54 @@ function showFavsAndRequeetsInQueet(q,data) { } +/* · + · + · Build a follow/block button + · + · @param obj: an object with a user array + · + · · · · · · · · · */ + +function buildFollowBlockbutton(obj) { + + // following? + var followingClass = ''; + if(obj.following) { + followingClass = ' following'; + } + + // blocking? + var blockingClass = ''; + if(obj.statusnet_blocking) { + blockingClass = ' blocking'; + } + + var followButton = ''; + if(typeof window.loggedIn.screen_name != 'undefined' // if logged in + && window.loggedIn.id != obj.id) { // not if this is me + if(!(obj.statusnet_profile_url.indexOf('/twitter.com/')>-1 && obj.following === false)) { // only unfollow twitter users + if(obj.blocks_you) { + var followButton = ''; + } + else { + var followButton = ''; + } + } + } + + return followButton; + } + /* · · @@ -310,28 +358,23 @@ function buildProfileCard(data) { var follows_you = '' + window.sL.followsYou + ''; } - // show user actions if logged in - var followingClass = ''; - if(data.following) { - followingClass = 'following'; - } var followButton = ''; // only add follow button if this is a local user if(data.is_local == true) { if(typeof window.loggedIn.screen_name != 'undefined' && window.loggedIn.id != data.id) { - var followButton = ''; + followButton = buildFollowBlockbutton(data); } // follow from external instance if logged out if(typeof window.loggedIn.screen_name == 'undefined') { - var followButton = ''; + followButton = ''; } // edit profile button if me if(typeof window.loggedIn.screen_name != 'undefined' && window.loggedIn.id == data.id) { - var followButton = ''; + followButton = ''; } } @@ -393,23 +436,18 @@ function buildProfileCard(data) { function buildExternalProfileCard(data) { - // local profile id and follow class - var followLocalIdHtml = ''; - var followingClass = ''; - if(typeof data.local != 'undefined' && data.local !== null) { - followLocalIdHtml = ' data-follow-user-id="' + data.local.id + '"'; - - if(data.local.following) { - followingClass = 'following'; - } - } - // follows me? var follows_you = ''; if(data.local !== null && data.local.follows_you === true && window.loggedIn.id != data.local.id) { var follows_you = '' + window.sL.followsYou + ''; } + // follow button + var followButton = ''; + if(window.loggedIn !== false && typeof data.local != 'undefined' && data.local !== null) { + var followButton = buildFollowBlockbutton(data.local); + } + // empty strings and zeros instead of null data = cleanUpUserObject(data.external); @@ -442,13 +480,6 @@ function buildExternalProfileCard(data) { var serverUrl = guessInstanceUrlWithoutProtocolFromProfileUrlAndNickname(data.statusnet_profile_url, data.screen_name); data.screenNameWithServer = '@' + data.screen_name + '@' + serverUrl; - var followButton = ''; - - // we can only follow remote users if we're logged in at the moment - if(window.loggedIn !== false) { - var followButton = ''; - } - data.profileCardHtml = '\
\
\ @@ -717,10 +748,11 @@ function setNewCurrentStream(streamObject,setLocation,fallbackId,actionOnSuccess }); } - // hide all notices from blocked users - if(typeof window.allBlocking != 'undefined') { + // hide all notices from blocked users (not for user lists) + if(window.currentStreamObject.type != 'users' && typeof window.allBlocking != 'undefined') { $.each(window.allBlocking,function(){ oldStreamState.find('strong.name[data-user-id="' + this + '"]').closest('.stream-item').addClass('profile-blocked-by-me'); + oldStreamState.find('strong.name[data-user-id="' + this + '"]').closest('.stream-item').children('.queet').attr('data-tooltip',window.sL.thisIsANoticeFromABlockedUser); }); } @@ -1870,26 +1902,27 @@ function buildUserStreamItemHtml(obj) { rtlOrNot = 'rtl'; } - // show user actions + // following? var followingClass = ''; if(obj.following) { - followingClass = 'following'; + followingClass = ' following'; } + + // blocking? + var blockingClass = ''; + if(obj.statusnet_blocking) { + blockingClass = ' blocking'; + } + var followButton = ''; if(typeof window.loggedIn.screen_name != 'undefined' // if logged in && window.loggedIn.id != obj.id) { // not if this is me if(!(obj.statusnet_profile_url.indexOf('/twitter.com/')>-1 && obj.following === false)) { // only unfollow twitter users - var followButton = ''; + var followButton = buildFollowBlockbutton(obj); } } - return '
\ + return '
\
\ ' + followButton + '\
\ @@ -2080,6 +2113,7 @@ function buildQueetHtml(obj, idInStream, extraClasses, requeeted_by, isConversat data-quitter-id-in-stream="' + idInStream + '" \ data-in-reply-to-screen-name="' + in_reply_to_screen_name + '" \ data-in-reply-to-status-id="' + obj.in_reply_to_status_id + '"\ + data-user-id="' + obj.user.id + '"\ ' + requeetedByMe + '>\
\ \ diff --git a/js/misc-functions.js b/js/misc-functions.js index 13a0f9f..b15a170 100644 --- a/js/misc-functions.js +++ b/js/misc-functions.js @@ -301,6 +301,137 @@ function localStorageIsEnabled() { } +/* · + · + · Block/unblock user and do necessary stuff + · + · · · · · · · · · */ + +function blockUser(arg, callback) { + + // arguments is sent as an object, for easier use with a menu's function-row + var userId = arg.userId; + var blockButton_jQueryElement = arg.blockButton_jQueryElement; + + display_spinner(); + APIBlockOrUnblockUser('block', userId, function(data) { + remove_spinner(); + + // activate the button, if we were passed one + if(typeof blockButton_jQueryElement != 'undefined') { + blockButton_jQueryElement.removeClass('disabled'); + } + + if(data && data.statusnet_blocking === true) { + // success + markUserAsBlockedInDOM(userId, data.following); + if(typeof callback == 'function') { + callback(blockButton_jQueryElement); + } + } + else { + // failed! + showErrorMessage(window.sL.failedBlockingUser); + } + }); + } +function unblockUser(arg, callback) { + + // arguments is sent as an object, for easier use with a menu's function-row + var userId = arg.userId; + var blockButton_jQueryElement = arg.blockButton_jQueryElement; + + display_spinner(); + APIBlockOrUnblockUser('unblock', userId, function(data) { + remove_spinner(); + + // activate the button, if we were passed one + if(typeof blockButton_jQueryElement != 'undefined') { + blockButton_jQueryElement.removeClass('disabled'); + } + + if(data && data.statusnet_blocking === false) { + // success + markUserAsUnblockedInDOM(userId, data.following); + if(typeof callback == 'function') { + callback(blockButton_jQueryElement); + } + } + else { + // failed! + showErrorMessage(window.sL.failedUnblockingUser); + } + }); + } +function markUserAsBlockedInDOM(userId, following) { + + // display buttons accordingly + $('.qvitter-follow-button[data-follow-user-id="' + userId + '"]').addClass('blocking'); + + if(following) { + $('.qvitter-follow-button[data-follow-user-id="' + userId + '"]').addClass('following'); + } + else { + $('.qvitter-follow-button[data-follow-user-id="' + userId + '"]').removeClass('following'); + } + + // hide notices from the blocked user + $.each($('.stream-item[data-quitter-id-in-stream][data-user-id="' + userId + '"]'),function(){ + $(this).addClass('profile-blocked-by-me'); + $(this).children('.queet').attr('data-tooltip',window.sL.thisIsANoticeFromABlockedUser); + }); + + // add to the window.allBlocking array + if (userIsBlocked(userId) === false) { + window.allBlocking.push(userId); + } + } +function markUserAsUnblockedInDOM(userId, following) { + + // display buttons accordingly + $('.qvitter-follow-button[data-follow-user-id="' + userId + '"]').removeClass('blocking'); + if(following) { + $('.qvitter-follow-button[data-follow-user-id="' + userId + '"]').addClass('following'); + } + else { + $('.qvitter-follow-button[data-follow-user-id="' + userId + '"]').removeClass('following'); + } + + // hide the user from lists of blocked users + $.each($('.stream-item.user[data-user-id="' + userId + '"]'),function(){ + slideUpAndRemoveStreamItem($(this)); + }); + + // unhide notices from the blocked user + $.each($('.stream-item[data-quitter-id-in-stream][data-user-id="' + userId + '"]'),function(){ + $(this).removeClass('profile-blocked-by-me'); + $(this).children('.queet').removeAttr('data-tooltip'); + }); + + // remove from the window.allBlocking array + var existingBlockIndex = window.allBlocking.indexOf(userId); + if (existingBlockIndex > -1) { + window.allBlocking.splice(existingBlockIndex, 1); + } + } + +/* · + · + · Is this user id blocked? + · + · · · · · · · · · */ + +function userIsBlocked(userId) { + var existingBlock = window.allBlocking.indexOf(userId); + if (existingBlock > -1) { + return true; + } + else { + return false; + } + } + + /* · · · Updates the times for all queets loaded to DOM @@ -1002,7 +1133,13 @@ function rememberStreamStateInLocalStorage() { return false; } }); + var feed = $('
').append(firstTwentyVisibleHTML); + + // we add these again (with updated blocking list) when the notices are fetched from the cache + feed.children('.stream-item').removeClass('profile-blocked-by-me'); + feed.children('.stream-item').children('.queet').removeAttr('data-tooltip'); // can contain tooltip about blocked user + feed.find('.temp-post').remove(); feed.children('.stream-item').removeClass('not-seen'); feed.children('.stream-item').removeClass('hidden-repeat'); // this means we need hide repeats when adding cached notices to feed later diff --git a/js/qvitter.js b/js/qvitter.js index 6368a33..4c633ef 100644 --- a/js/qvitter.js +++ b/js/qvitter.js @@ -1214,28 +1214,42 @@ $('body').on('click','.sm-ellipsis',function(e){ var streamItemUserID = $(this).closest('.queet').find('.stream-item-header').find('.name').attr('data-user-id'); var streamItemID = $(this).closest('.queet').parent('.stream-item').attr('data-quitter-id'); + // menu + var menuArray = []; + // my notice if(streamItemUserID == window.loggedIn.id) { - var menuArray = [ - { - type: 'function', - functionName: 'deleteQueet', - functionArguments: { - streamItemID: streamItemID - }, - label: window.sL.deleteVerb + menuArray.push({ + type: 'function', + functionName: 'deleteQueet', + functionArguments: { + streamItemID: streamItemID }, - ]; + label: window.sL.deleteVerb + }); } // other users' notices else { - var menuArray = [ - { - type: 'link', - href: window.siteInstanceURL + 'main/block?profileid=' + streamItemUserID, + if(userIsBlocked(streamItemUserID)) { + menuArray.push({ + type: 'function', + functionName: 'unblockUser', + functionArguments: { + userId: streamItemUserID + }, + label: window.sL.unblockUser.replace('{username}',streamItemUsername) + }); + } + else { + menuArray.push({ + type: 'function', + functionName: 'blockUser', + functionArguments: { + userId: streamItemUserID + }, label: window.sL.blockUser.replace('{username}',streamItemUsername) - }, - ]; + }); + } } // add menu to DOM and align it @@ -1453,67 +1467,73 @@ $('body').on('click','.external-member-button',function(event){ /* · · - · When clicking a follow button + · When clicking a follow/block button · · · · · · · · · · · · · · */ $('body').on('click','.qvitter-follow-button',function(event){ - if(!$(this).hasClass('disabled')) { - $(this).addClass('disabled'); - // get user id - var user_id = $(this).attr('data-follow-user-id'); - - // if there's no local user id, we have to take a detour - if(typeof user_id == 'undefined') { - $.ajax({ url: window.siteInstanceURL + 'main/ostatussub', - type: "POST", - data: { - token: window.commonSessionToken, - profile: $(this).attr('data-follow-user'), - submit: 'Confirm' - }, - error: function(data){ console.log('error'); console.log(data); }, - success: function(data) { - // reload page on success - // since ostatussub doesn't have an api, there's no good way to get the local user id here, - // and change the button to an unsubscribe button. - window.location.replace(window.siteInstanceURL + window.loggedIn.screen_name + '/subscriptions'); - } - }); - } - - // if we have a local id, it's straightforward, but we could be handling an unfollow - else { - - // follow or unfollow? - if($(this).hasClass('following')) { - var followOrUnfollow = 'unfollow'; - } - else { - var followOrUnfollow = 'follow'; - } - - // post to api - display_spinner(); - APIFollowOrUnfollowUser(followOrUnfollow,user_id, this, function(data,this_element) { - remove_spinner(); - $(this_element).removeClass('disabled'); - if(data) { - if(data.following) { - $(this_element).addClass('following'); - $('#user-following strong').html(parseInt($('#user-following strong').html(),10)+1); - appendUserToMentionsSuggestionsArray(data); - } - else { - $(this_element).removeClass('following'); - $('#user-following strong').html(parseInt($('#user-following strong').html(),10)-1); - } - } - }); - - } + if($(this).hasClass('disabled')) { + return true; } + + $(this).addClass('disabled'); + var user_id = $(this).attr('data-follow-user-id'); + + // if we have a local id, it's straightforward, but we could be handling an unfollow + if(typeof user_id != 'undefined') { + + // unblock? + if($(this).hasClass('blocking')) { + unblockUser({userId: user_id, blockButton_jQueryElement: $(this)}); + return true; + } + + // follow or unfollow? + if($(this).hasClass('following')) { + var followOrUnfollow = 'unfollow'; + } + else { + var followOrUnfollow = 'follow'; + } + + // post to api + display_spinner(); + APIFollowOrUnfollowUser(followOrUnfollow,user_id, this, function(data,this_element) { + remove_spinner(); + $(this_element).removeClass('disabled'); + if(data) { + if(data.following) { + $(this_element).addClass('following'); + $('#user-following strong').html(parseInt($('#user-following strong').html(),10)+1); + appendUserToMentionsSuggestionsArray(data); + } + else { + $(this_element).removeClass('following'); + $('#user-following strong').html(parseInt($('#user-following strong').html(),10)-1); + } + } + }); + + return true; + } + + // if there's no local user id, we have to take a detour + $.ajax({ url: window.siteInstanceURL + 'main/ostatussub', + type: "POST", + data: { + token: window.commonSessionToken, + profile: $(this).attr('data-follow-user'), + submit: 'Confirm' + }, + error: function(data){ console.log('error'); console.log(data); }, + success: function(data) { + // reload page on success + // since ostatussub doesn't have an api, there's no good way to get the local user id here, + // and change the button to an unsubscribe button. + window.location.replace(window.siteInstanceURL + window.loggedIn.screen_name + '/subscriptions'); + } + }); }); diff --git a/js/stream-router.js b/js/stream-router.js index 73b1ef8..f7ed994 100644 --- a/js/stream-router.js +++ b/js/stream-router.js @@ -614,6 +614,19 @@ function pathToStreamRouter(path) { return streamObject; } + // {screen_name}/blocks + if(pathSplit.length == 2 && /^[a-zA-Z0-9]+$/.test(pathSplit[0]) && pathSplit[1] == 'blocks') { + streamObject.name = 'user blocks'; + streamObject.nickname = pathSplit[0]; + streamObject.parentPath = streamObject.nickname; + streamObject.streamHeader = '@' + replaceHtmlSpecialChars(streamObject.nickname); + streamObject.streamSubHeader = window.sL.userBlocks; + streamObject.stream = 'qvitter/blocks.json?count=20&id=' + streamObject.nickname + '&withuserarray=1'; + streamObject.maxIdOrPage = 'page'; + streamObject.type = 'users'; + return streamObject; + } + // {screen_name}/groups if(pathSplit.length == 2 && /^[a-zA-Z0-9]+$/.test(pathSplit[0]) && pathSplit[1] == 'groups') { streamObject.name = 'user group list'; diff --git a/locale/ar.json b/locale/ar.json index 68a34ef..4d17ca9 100644 --- a/locale/ar.json +++ b/locale/ar.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/ast.json b/locale/ast.json index 90c11cb..453b49f 100644 --- a/locale/ast.json +++ b/locale/ast.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/ca.json b/locale/ca.json index 958cf36..f778b37 100644 --- a/locale/ca.json +++ b/locale/ca.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/de.json b/locale/de.json index 19a97a3..43a9769 100644 --- a/locale/de.json +++ b/locale/de.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Eingebettete Inhaltsvorschau nicht anzeigen in dieser Timeline", - "hideQuotesInTimeline":"Verberge Zitate in dieser Timeline" + "hideQuotesInTimeline":"Verberge Zitate in dieser Timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/en.json b/locale/en.json index 67f6dbf..9d546fe 100644 --- a/locale/en.json +++ b/locale/en.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/eo.json b/locale/eo.json index 9945110..7eb8c5b 100644 --- a/locale/eo.json +++ b/locale/eo.json @@ -163,5 +163,12 @@ "startRant":"Eki plendon", "continueRant":"Daŭrigi la plendon", "hideEmbeddedInTimeline":"Kaŝi enkorpigitajn enhavojn en ĉi tiu tempolinio", - "hideQuotesInTimeline":"Kaŝi citaĵojn en ĉi tiu tempolinio" + "hideQuotesInTimeline":"Kaŝi citaĵojn en ĉi tiu tempolinio", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/es.json b/locale/es.json index 259ac6e..df61d68 100644 --- a/locale/es.json +++ b/locale/es.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Ocultar contenido incrustado en esta línea temporal", - "hideQuotesInTimeline":"Ocultar citas en esta línea temporal" + "hideQuotesInTimeline":"Ocultar citas en esta línea temporal", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/es_ahorita.json b/locale/es_ahorita.json index 91b721d..c83203a 100644 --- a/locale/es_ahorita.json +++ b/locale/es_ahorita.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/eu.json b/locale/eu.json index dc71e3a..e269780 100644 --- a/locale/eu.json +++ b/locale/eu.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/fa.json b/locale/fa.json index 58bae9b..bbfcff3 100644 --- a/locale/fa.json +++ b/locale/fa.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/fi.json b/locale/fi.json index 794abe8..5f72f35 100644 --- a/locale/fi.json +++ b/locale/fi.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/fr.json b/locale/fr.json index 9264b37..f564a4e 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Cacher le contenu intégré dans ces avis", - "hideQuotesInTimeline":"Cacher les citations dans ces avis" + "hideQuotesInTimeline":"Cacher les citations dans ces avis", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/gl.json b/locale/gl.json index 488410c..d092e18 100644 --- a/locale/gl.json +++ b/locale/gl.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Ocultar contido incrustado nesta liña temporal", - "hideQuotesInTimeline":"Ocultar citas nesta liña temporal" + "hideQuotesInTimeline":"Ocultar citas nesta liña temporal", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/he.json b/locale/he.json index 9d0dd66..cffad42 100644 --- a/locale/he.json +++ b/locale/he.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/io.json b/locale/io.json index d6cd2f9..157989a 100644 --- a/locale/io.json +++ b/locale/io.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/it.json b/locale/it.json index e4985b3..39a0793 100644 --- a/locale/it.json +++ b/locale/it.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/ja.json b/locale/ja.json index 32272e8..27c3e72 100644 --- a/locale/ja.json +++ b/locale/ja.json @@ -163,5 +163,12 @@ "startRant":"連投する", "continueRant":"連投を続ける", "hideEmbeddedInTimeline":"タイムライン上の埋め込まれたコンテンツを隠す", - "hideQuotesInTimeline":"タイムライン上の引用を隠す" + "hideQuotesInTimeline":"タイムライン上の引用を隠す", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/nl.json b/locale/nl.json index a8e9742..17481ef 100644 --- a/locale/nl.json +++ b/locale/nl.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/no.json b/locale/no.json index a9066a3..de76dae 100644 --- a/locale/no.json +++ b/locale/no.json @@ -163,5 +163,12 @@ "startRant":"Start en utblåsning", "continueRant":"Fortsett utblåsningen", "hideEmbeddedInTimeline":"Skjul inkluderende innhold i denne tidslinjen", - "hideQuotesInTimeline":"Skjul sitater i denne tidslinjen" + "hideQuotesInTimeline":"Skjul sitater i denne tidslinjen", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/pt.json b/locale/pt.json index c4c95c2..b801895 100644 --- a/locale/pt.json +++ b/locale/pt.json @@ -163,5 +163,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/pt_br.json b/locale/pt_br.json index 0196fcb..58cff8b 100644 --- a/locale/pt_br.json +++ b/locale/pt_br.json @@ -163,5 +163,12 @@ "startRant":"Iniciar um debate", "continueRant":"Continuar o debate", "hideEmbeddedInTimeline":"Ocultar conteúdo incorporado nessa linha do tempo", - "hideQuotesInTimeline":"Ocultar citações nesta linha do tempo" + "hideQuotesInTimeline":"Ocultar citações nesta linha do tempo", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/ru.json b/locale/ru.json index f842932..703c866 100644 --- a/locale/ru.json +++ b/locale/ru.json @@ -161,5 +161,12 @@ "addEditLanguageLink":"Помогите перевести {site-title} на другой язык", "onlyPartlyTranslated":"{site-title} только частично переведён на {language-name} ({percent}%). Вы можете помочь завершить перевод на на домашней странице репозитория Qvitter", "startRant":"Начать декламацию", - "continueRant":"Продолжить декламацию" + "continueRant":"Продолжить декламацию", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/sq.json b/locale/sq.json index d9b06c6..a8ccbe1 100644 --- a/locale/sq.json +++ b/locale/sq.json @@ -163,5 +163,12 @@ "startRant":"Filloni një dërdëllitje", "continueRant":"Vazhdojeni dërdëllitjen", "hideEmbeddedInTimeline":"Fshih lëndë të trupëzuar në këtë rrjedhë kohore", - "hideQuotesInTimeline":"Fshih citime në këtë rrjedhë kohore" + "hideQuotesInTimeline":"Fshih citime në këtë rrjedhë kohore", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." } diff --git a/locale/sv.json b/locale/sv.json index e7291bd..7496751 100644 --- a/locale/sv.json +++ b/locale/sv.json @@ -163,5 +163,12 @@ "startRant":"Påbörja en harang", "continueRant":"Fortsätt harangen", "hideEmbeddedInTimeline":"Dölj inbäddat innehåll i detta flöde", - "hideQuotesInTimeline":"Dölj citat i detta flöde" + "hideQuotesInTimeline":"Dölj citat i detta flöde", + "userBlocks":"Konton du blockerar", + "buttonBlocked":"Blockerad", + "buttonUnblock":"Avblockera", + "failedBlockingUser":"Misslyckades med att blockera användaren.", + "failedUnblockingUser":"Misslyckades med att avblockera användaren.", + "unblockUser": "Avblockera {username}", + "tooltipBlocksYou":"Du är blockerad från att följa {username}." } diff --git a/locale/zh_cn.json b/locale/zh_cn.json index 6b82016..3cc8d2a 100644 --- a/locale/zh_cn.json +++ b/locale/zh_cn.json @@ -162,5 +162,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" -} \ No newline at end of file + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." +} diff --git a/locale/zh_tw.json b/locale/zh_tw.json index 54da409..ee9cde6 100644 --- a/locale/zh_tw.json +++ b/locale/zh_tw.json @@ -162,5 +162,12 @@ "startRant":"Start a rant", "continueRant":"Continue the rant", "hideEmbeddedInTimeline":"Hide embedded content in this timeline", - "hideQuotesInTimeline":"Hide quotes in this timeline" + "hideQuotesInTimeline":"Hide quotes in this timeline", + "userBlocks":"Accounts you're blocking", + "buttonBlocked":"Blocked", + "buttonUnblock":"Unblock", + "failedBlockingUser":"Failed to block the user.", + "failedUnblockingUser":"Failed to unblock the user.", + "unblockUser": "Unblock {username}", + "tooltipBlocksYou":"You are blocked from following {username}." }