') // to open stuff in new tab, see routeOnClick()
+ },
+ tmpl: {}, // templates should be detached and stored here
+ modal: {}
+};
var window_scrollY = 0;
var _watchHashChangeRelaxDontDoIt = window.location.hash === '' ? true : false;
-var _minimizedModals = {};
+
+// FIXME so looks like it's wrapper over $; it's here to select and manipulate detached elements too
+// and actually I'm talking about 'so called \'detached\'' elements which appended to twister.html.detached
+// we may just append twister.html.detached to document instead and remove this weird shit (or I need to
+// improve my google skills to find native jQuery way to dig through all detached elemets with one query)
+function getElem(req) {
+ var elem = $(req);
+ var h = twister.html.detached.find(req);
+
+ for (var i = 0; i < h.length; i++)
+ elem[elem.length++] = h[i];
+
+ return elem;
+}
function openModal(modal) {
if (!modal.classBase) {
@@ -17,7 +38,8 @@ function openModal(modal) {
$('body').css('overflow', 'hidden');
}
- $(modal.classBase + ':not(#templates *)').remove();
+ if (modal.classBase !== '.prompt-wrapper')
+ closeModal($(modal.classBase + ':not(#templates *)'), true);
modal.self = $('#templates ' + modal.classBase).clone(true)
.addClass(modal.classAdd);
@@ -30,9 +52,14 @@ function openModal(modal) {
else
modal.content = modal.self.find('.modal-content');
- modal.self.prependTo('body').fadeIn('fast');
+ modal.self.appendTo('body').fadeIn('fast'); // FIXME maybe it's better to append it to some container inside body
if (modal.classBase === '.modal-wrapper') {
+ twister.modal[window.location.hash] = modal;
+ modal.self.attr('data-modal-id', window.location.hash);
+
+ modal.drapper = $('').appendTo(twister.html.detached); // here modal goes instead detaching
+
modal.content.outerHeight(modal.self.height() - modal.self.find('.modal-header').outerHeight());
var windowHeight = $(window).height();
@@ -46,49 +73,95 @@ function openModal(modal) {
return modal;
}
-function closeModal() {
- closeModalHandler('.modal-wrapper');
+function closeModal(req, switchMode) {
+ if (typeof req === 'undefined')
+ var elem = $('.modal-wrapper:not(#templates *)'); // select active modal(s)
+ else if (req.jquery)
+ var elem = req;
+ else if (req.target)
+ var elem = getElem(req.target); // getElem() to search in minimized too
+ else if (typeof req === 'string' || req.outerHTML)
+ var elem = getElem(req);
+
+ if (!elem || !elem.length)
+ return;
+
+ // we close all modals which are containing element(s)
+ elem.closest('.modal-wrapper:not(.closed)').addClass('closed')
+ .fadeOut(switchMode ? 10 : 'fast', function () {
+ var i = this.getAttribute('data-modal-id');
+
+ if (twister.modal[i].minimized)
+ twister.modal[i].btnResume.fadeOut('fast', function () {this.remove();});
+ else
+ this.remove(); // if it's minimized it will be removed with twister.modal[i].drapper
- if (window.location.hash !== '') {
- _watchHashChangeRelaxDontDoIt = true;
- window.location.hash = '#';
+ twister.modal[i].drapper.remove();
+ twister.modal[i] = undefined;
+ }
+ );
+
+ if (!switchMode) {
+ if (window.location.hash !== '') {
+ _watchHashChangeRelaxDontDoIt = true;
+ window.location.hash = '#';
+ }
+ window.scroll(window.pageXOffset, window_scrollY);
+ $('body').css({
+ 'overflow': 'auto',
+ 'margin-right': '0'
+ });
}
- window.scroll(window.pageXOffset, window_scrollY);
- $('body').css({
- 'overflow': 'auto',
- 'margin-right': '0'
- });
}
-function closePrompt() {
- closeModalHandler('.prompt-wrapper');
-}
+function closePrompt(req) {
+ if (typeof req === 'undefined')
+ var elem = $('.prompt-wrapper:not(#templates *)');
+ else if (req.jquery)
+ var elem = req;
+ else if (req.target)
+ var elem = $(req.target);
+ else if (typeof req === 'string' || req.outerHTML)
+ var elem = $(req);
+
+ if (!elem || !elem.length)
+ return;
-function closeModalHandler(classBase) {
- var modalWindows = $(classBase+':not(#templates *)');
+ if (typeof req.stopPropagation === 'function') {
+ req.preventDefault();
+ req.stopPropagation();
+ req = req.data;
+ }
- modalWindows.fadeOut('fast', function() {modalWindows.remove();});
+ // we close all prompts which are containing element(s)
+ elem.closest('.prompt-wrapper:not(.closed)').addClass('closed')
+ .fadeOut('fast', function() {this.remove();});
+
+ if (req && typeof req.cbFunc === 'function') // FIXME maybe bind to ^ prompt fadeout function
+ req.cbFunc(req.cbReq);
}
function minimizeModal(modal, switchMode) {
+
function minimize(modal, scroll) {
- modal.detach();
+ var i = modal.attr('data-modal-id');
- btnResume = $('
' + modal.find('.modal-header h3').text() + '')
+ modal.appendTo(twister.modal[i].drapper);
+
+ twister.modal[i].minimized = true;
+ twister.modal[i].scroll = scroll;
+ twister.modal[i].btnResume = $('' + modal.find('.modal-header h3').text() + '')
.on('click', {hashString: window.location.hash}, resumeModal)
+ .on('mouseup', {route: window.location.hash, blankOnly: true}, routeOnClick)
.appendTo($('#modals-minimized'))
;
-
- _minimizedModals[window.location.hash] = {
- self: modal,
- scroll: scroll,
- btnResume: btnResume
- };
}
+ if (modal.is('.closed')) return;
+
var scroll; // MUST be setted before modal.detach(), modal.fadeOut() and so on
if (modal.is('.directMessages') || modal.is('.group-messages-new-group')
- || modal.is('.group-messages-join-group')) {
+ || modal.is('.group-messages-join-group') || modal.is('.following-own-modal')) {
scroll = {
targetSelector: '.modal-content',
top: modal.find('.modal-content').scrollTop()
@@ -123,10 +196,9 @@ function minimizeModal(modal, switchMode) {
}
function resumeModal(event) {
- var elemEvent = $(event.target);
- elemEvent.fadeOut('fast', function () {elemEvent.remove();});
+ $(event.target).fadeOut('fast', function () {this.remove();});
- var modalActive = $('.modal-wrapper:not(#templates *)');
+ var modalActive = $('.modal-wrapper:not(#templates *)').not('.closed');
if (modalActive.length)
minimizeModal(modalActive, true);
else {
@@ -134,9 +206,10 @@ function resumeModal(event) {
$('body').css('overflow', 'hidden');
}
- var modal = _minimizedModals[event.data.hashString];
- if (modal) {
- _minimizedModals[event.data.hashString] = undefined;
+ var modal = twister.modal[event.data.hashString];
+ if (modal.self.not('.closed') && modal.minimized) {
+ modal.minimized = false;
+ modal.btnResume = undefined;
if (window.location.hash !== event.data.hashString) {
_watchHashChangeRelaxDontDoIt = true;
window.location.hash = event.data.hashString;
@@ -146,35 +219,39 @@ function resumeModal(event) {
if (modal.scroll)
modal.self.find($(modal.scroll.targetSelector).scrollTop(modal.scroll.top));
- if (modal.resume && typeof modal.resume.cbFunc === 'function')
- modal.resume.cbFunc(modal.resume.cbArg);
+ if (typeof modal.onResume === 'function')
+ modal.onResume(modal.onResumeReq);
});
}
}
-function focusModalWithElement(elem, cbFunc, cbArg) {
+function focusModalWithElement(elem, cbFunc, cbReq) {
if (elem.jquery ? elem.is('html *') : $(elem).is('html *')) {
if (typeof cbFunc === 'function')
- cbFunc(cbArg);
+ cbFunc(cbReq);
return true;
}
- var hash = getHashOfMinimizedModalWithElem(elem);
- if (hash) {
- _minimizedModals[hash].resume = {cbFunc: cbFunc, cbArg: cbArg};
- _minimizedModals[hash].btnResume.click();
+ var i = getHashOfMinimizedModalWithElem(elem);
+ if (i) {
+ if (typeof i === 'object') i = i[0]; // several modals, but only one may be active currently
+ twister.modal[i].onResume = cbFunc;
+ twister.modal[i].onResumeReq = cbReq;
+ twister.modal[i].btnResume.click();
return true;
}
return false;
}
-function getHashOfMinimizedModalWithElem(elem) {
- for (var i in _minimizedModals)
- if (_minimizedModals[i] && _minimizedModals[i].self.find(elem).length)
- return i;
+function getHashOfMinimizedModalWithElem(req) {
+ var hashes = [];
+
+ for (var i in twister.modal)
+ if (twister.modal[i] && twister.modal[i].minimized && twister.modal[i].drapper.find(req).length)
+ hashes[hashes.length++] = i;
- return '';
+ return hashes.length > 1 ? hashes : hashes[0];
}
function isModalWithElemExists(elem) {
@@ -184,90 +261,97 @@ function isModalWithElemExists(elem) {
return getHashOfMinimizedModalWithElem(elem) ? true : false;
}
-function confirmPopup(event, req) {
- if (event && event.stopPropagation) {
- event.stopPropagation();
+function confirmPopup(req) {
+ if (!req) return;
- if (!req && event.data)
- req = event.data;
+ if (typeof req.stopPropagation === 'function') {
+ req.preventDefault();
+ req.stopPropagation();
+ if (req.data)
+ req = req.data;
+ else
+ return;
}
var modal = openModal({
classBase: '.prompt-wrapper',
classAdd: 'confirm-popup',
content: $('#confirm-popup-template').children().clone(true),
- title: req.titleTxt
+ title: req.txtTitle
});
- if (req.messageTxt)
- modal.content.find('.message').html(htmlFormatMsg(req.messageTxt, {markout: 'apply'}).html);
+ if (req.txtMessage)
+ modal.content.find('.message').html(htmlFormatMsg(req.txtMessage, {markout: 'apply'}).html);
var btn = modal.content.find('.confirm');
if (req.removeConfirm)
btn.remove();
else {
- if (req.confirmTxt)
- btn.text(req.confirmTxt);
+ if (req.txtConfirm)
+ btn.text(req.txtConfirm);
else
btn.text(polyglot.t('Confirm'));
- if (req.confirmFunc) {
- btn.on('click', function () {
- closePrompt();
- req.confirmFunc(req.confirmFuncArgs);
- });
- } else
+
+ if (req.cbConfirm)
+ btn.on('click', {cbFunc: req.cbConfirm, cbReq: req.cbConfirmReq}, closePrompt);
+ else
btn.on('click', closePrompt);
}
var btn = modal.content.find('.cancel');
if (req.removeCancel)
btn.remove();
else {
- if (req.cancelTxt)
- btn.text(req.cancelTxt);
+ if (req.txtCancel)
+ btn.text(req.txtCancel);
else
btn.text(polyglot.t('Cancel'));
- if (req.cancelFunc) {
- btn.on('click', function () {
- closePrompt();
- req.cancelFunc(req.cancelFuncArgs);
- });
- } else
+
+ if (req.cbCancel)
+ btn.on('click', {cbFunc: req.cbCancel, cbReq: req.cbCancelReq}, closePrompt);
+ else
btn.on('click', closePrompt);
}
var btn = modal.self.find('.prompt-close');
if (req.removeClose)
btn.remove();
else {
- if (req.closeFunc) {
- if (typeof req.closeFunc === 'string') {
- if (req.closeFunc === 'confirmFunc') {
- req.closeFunc = req.confirmFunc;
- req.closeFuncArgs = req.confirmFuncArgs;
- } else if (req.closeFunc === 'cancelFunc') {
- req.closeFunc = req.cancelFunc;
- req.closeFuncArgs = req.cancelFuncArgs;
+ if (req.cbClose) {
+ if (typeof req.cbClose === 'string')
+ if (req.cbClose === 'cbConfirm') {
+ req.cbClose = req.cbConfirm;
+ req.cbCloseReq = req.cbConfirmReq;
+ } else if (req.cbClose === 'cbCancel') {
+ req.cbClose = req.cbCancel;
+ req.cbCloseReq = req.cbCancelReq;
}
- }
- btn.on('click', function () {
- closePrompt();
- req.closeFunc(req.closeFuncArgs);
- });
+
+ btn.on('click', {cbFunc: req.cbClose, cbReq: req.cbCloseReq}, closePrompt);
}
}
}
-function checkNetworkStatusAndAskRedirect(cbFunc, cbArg) {
- networkUpdate(function(args) {
+function alertPopup(req) {
+ if (!req) return;
+
+ if (!req.txtConfirm)
+ req.txtConfirm = polyglot.t('btn_ok');
+ req.removeCancel = true;
+
+ confirmPopup(req);
+}
+
+function checkNetworkStatusAndAskRedirect(cbFunc, cbReq) {
+ networkUpdate(function(req) {
if (!twisterdConnectedAndUptodate) {
- confirmPopup(null, {
- messageTxt: polyglot.t('confirm_switch_to_network', {page: '/network.html'}),
- confirmFunc: $.MAL.goNetwork
+ confirmPopup({
+ txtMessage: polyglot.t('confirm_switch_to_network', {page: '/network.html'}),
+ cbConfirm: $.MAL.goNetwork
});
} else {
- if (args.cbFunc)
- args.cbFunc(args.cbArg);
+ if (req.cbFunc)
+ req.cbFunc(req.cbReq);
}
- }, {cbFunc:cbFunc,cbArg:cbArg});
+ }, {cbFunc: cbFunc, cbReq: cbReq});
}
function timeGmtToText(t) {
@@ -335,10 +419,10 @@ function openGroupProfileModalWithNameHandler(groupAlias) {
elemFitNextIntoParentHeight(modal.content.find('.profile-card'));
}
-function openUserProfileModalWithNameHandler(username) {
+function openUserProfileModalWithNameHandler(peerAlias) {
var content = $('#profile-modal-template').children().clone(true);
- updateProfileData(content, username);
+ updateProfileData(content, peerAlias);
// FIXME following ctc could be part of updateProfileData() when mobile will be ready for this
content.find('.tox-ctc').attr('title', polyglot.t('Copy to clipboard'));
content.find('.bitmessage-ctc').attr('title', polyglot.t('Copy to clipboard'));
@@ -346,17 +430,14 @@ function openUserProfileModalWithNameHandler(username) {
var modal = openModal({
classAdd: 'profile-modal',
content: content,
- title: polyglot.t('users_profile', {username: username})
+ title: polyglot.t('users_profile', {username: peerAlias})
});
- // setup follow button in profile modal window
- var button = modal.content.find('.profile-card-buttons .follow');
- if (button) {
- if (followingUsers.indexOf(username) !== -1)
- toggleFollowButton(username, true, function() {setTimeout(loadModalFromHash, 500);});
- else
- button.on('click', userClickFollow);
- }
+ toggleFollowButton({
+ button: modal.content.find('.profile-card-buttons .follow'),
+ peerAlias: peerAlias,
+ toggleUnfollow: followingUsers.indexOf(peerAlias) !== -1 ? true : false
+ });
elemFitNextIntoParentHeight(modal.content.find('.profile-card'));
@@ -405,35 +486,38 @@ function updateQueryModal(req) {
requestQuery(req);
}
-function openMentionsModal(e) {
- if (e && e.stopPropagation) {
- e.stopPropagation();
- e.preventDefault();
+function openMentionsModal(event) {
+ if (event && typeof event.stopPropagation === 'function') {
+ event.preventDefault();
+ event.stopPropagation();
}
var userInfo = $(this).closest('[data-screen-name]');
if (userInfo.length)
- var username = userInfo.attr('data-screen-name');
+ var peerAlias = userInfo.attr('data-screen-name');
else if (defaultScreenName)
- var username = defaultScreenName;
+ var peerAlias = defaultScreenName;
else {
- alert(polyglot.t('No one can mention you because you are not logged in.'));
+ alertPopup({
+ //txtTitle: polyglot.t(''), add some title (not 'error', please) or just KISS
+ txtMessage: polyglot.t('No one can mention you because you are not logged in.')
+ });
return;
}
- window.location.hash = '#mentions?user=' + username;
+ window.location.hash = '#mentions?user=' + peerAlias;
}
-function openMentionsModalHandler(username) {
+function openMentionsModalHandler(peerAlias) {
var modal = openModal({
classAdd: 'hashtag-modal',
content: $('#hashtag-modal-template').children().clone(true),
- title: polyglot.t('users_mentions', {username: username})
+ title: polyglot.t('users_mentions', {username: peerAlias})
});
- setupQueryModalUpdating(modal.content.find('.postboard-posts'), username, 'mention');
+ setupQueryModalUpdating(modal.content.find('.postboard-posts'), peerAlias, 'mention');
- if (username === defaultScreenName) {
+ if (peerAlias === defaultScreenName) {
// obtain already cached mention posts from twister_newmsgs.js
processQuery({
postboard: modal.content.find('.postboard-posts'),
@@ -445,17 +529,73 @@ function openMentionsModalHandler(username) {
}
}
-function openFollowingModal(username) {
- var content = $('#following-modal-template').children().clone(true);
+function openFollowingModal(peerAlias) {
+ if (!peerAlias || peerAlias === defaultScreenName) {
+ if (!defaultScreenName) {
+ alertPopup({
+ //txtTitle: polyglot.t(''), add some title (not 'error', please) or just KISS
+ txtMessage: polyglot.t('You are not following anyone because you are not logged in.')
+ });
+ history.back();
+ return;
+ }
- content.find('.following-screen-name b').text(username);
- loadFollowingIntoList(username, content.closest('ol'));
+ var modal = openModal({
+ classAdd: 'following-own-modal',
+ content: twister.tmpl.followingList.clone(true),
+ title: polyglot.t('Following')
+ });
+ showFollowingUsers(modal.content.find('.following-list'));
+ requestSwarmProgress();
+ } else {
+ var modal = openModal({
+ classAdd: 'following-modal',
+ content: $('#following-modal-template').children().clone(true),
+ title: polyglot.t('followed_by', {username: peerAlias})
+ });
+ modal.content.find('.following-screen-name b').text(peerAlias);
+ loadFollowingIntoList(peerAlias, modal.content.find('ol'));
+ }
+}
- openModal({
- classAdd: 'following-modal',
- content: content,
- title: polyglot.t('followed_by', {username: username})
+function showFollowingUsers(followingList) {
+ if (followingEmptyOrMyself())
+ $.MAL.warnFollowingNotAny(closeModal, followingList);
+ else
+ for (var i = 0; i < followingUsers.length; i++)
+ addToFollowingList(followingList, followingUsers[i]);
+
+ $.MAL.followingListLoaded(followingList);
+}
+
+function addToFollowingList(followingList, peerAlias) {
+ var item = twister.tmpl.followingUser.clone(true).attr('data-peer-alias', peerAlias);
+
+ item.find('.mini-profile-info').attr('data-screen-name', peerAlias)
+ item.find('.following-screen-name').text(peerAlias);
+ item.find('a.open-profile-modal').attr('href', $.MAL.userUrl(peerAlias));
+ item.find('.direct-messages-with-user').text(polyglot.t('send_DM'))
+ .on('mouseup', {route: $.MAL.dmchatUrl(peerAlias)}, routeOnClick);
+ item.find('.mentions-from-user').text(polyglot.t('display_mentions'))
+ .on('mouseup', {route: $.MAL.mentionsUrl(peerAlias)}, routeOnClick);
+ getAvatar(peerAlias, item.find('.mini-profile-photo'));
+ getFullname(peerAlias, item.find('.mini-profile-name'));
+
+ if (peerAlias === defaultScreenName)
+ item.find('following-config').hide();
+
+ toggleFollowButton({
+ button: item.find('.follow'),
+ peerAlias: peerAlias,
+ toggleUnfollow: true
});
+ var elem = item.find('.public-following').on('click', followingListPublicCheckbox);
+ if (isPublicFollowing(peerAlias))
+ elem.text(polyglot.t('Public'));
+ else
+ elem.text(polyglot.t('Private')).addClass('private');
+
+ item.prependTo(followingList);
}
function fillWhoToFollowModal(list, hlist, start) {
@@ -517,10 +657,10 @@ function openWhoToFollowModal() {
fillWhoToFollowModal(tmplist, hlist, 0);
}
-function newConversationModal(username, resource) {
+function newConversationModal(peerAlias, resource) {
var content = $('#hashtag-modal-template').children().clone(true);
- requestPost(content.find('.postboard-posts'), username, resource,
+ requestPost(content.find('.postboard-posts'), peerAlias, resource,
function(args) {
var postboard = args.content.find('.postboard-posts');
var postLi = postboard.children().first()
@@ -532,27 +672,42 @@ function newConversationModal(username, resource) {
return content;
}
-function openConversationClick(e) {
- e.stopPropagation();
- e.preventDefault();
+function openConversationClick(event) {
+ event.preventDefault();
+ event.stopPropagation();
- var postData = $(this).closest(e.data.feeder);
+ var elem = $(event.target);
+ var postData = elem.closest(event.data.feeder);
- window.location.hash = '#conversation?post=' + postData.attr('data-screen-name') +
- ':post' + postData.attr('data-id');
+ event.data.route = '#conversation?post=' + postData.attr('data-screen-name')
+ + ':post' + postData.attr('data-id');
+ routeOnClick(event);
}
-function openConversationModal(username, resource) {
+function openConversationModal(peerAlias, resource) {
openModal({
classAdd: 'conversation-modal',
- content: newConversationModal(username, resource),
- title: polyglot.t('conversation_title', {username: username})
+ content: newConversationModal(peerAlias, resource),
+ title: polyglot.t('conversation_title', {username: peerAlias})
});
}
-function watchHashChange(e) {
- if (e != null) {
- var prevurlsplit = e.oldURL.split('#');
+function routeOnClick(event) {
+ if (!event || !event.data || !event.data.route)
+ return;
+
+ event.stopPropagation();
+ event.preventDefault();
+
+ if (event.button === 0 && !event.data.blankOnly) // left mouse button
+ window.location = event.data.route;
+ else if (event.button === 1) // middle mouse button
+ twister.html.blanka.attr('href', event.data.route)[0].click();
+}
+
+function watchHashChange(event) {
+ if (typeof event !== 'undefined') {
+ var prevurlsplit = event.oldURL.split('#');
var prevhashstring = prevurlsplit[1];
// FIXME need to move back button handling to special function and call it in openModal() and resumeModal()
@@ -575,17 +730,18 @@ function watchHashChange(e) {
}
function loadModalFromHash() {
- if (_minimizedModals[window.location.hash]) {
+ var i = window.location.hash;
+ if (twister.modal[i] && twister.modal[i].minimized) {
// need to remove active modal before btnResume.click() or it will be minimized in resumeModal()
// e.g. for case when you click on profile link in some modal having this profile's modal minimized already
$('.modal-wrapper:not(#templates *)').remove();
- _minimizedModals[window.location.hash].btnResume.click();
+ twister.modal[i].btnResume.click();
return;
}
var hashstring = decodeURIComponent(window.location.hash);
if (hashstring === '') {
- closeModal();
+ closeModal(); // close active modal(s)
return;
}
var hashdata = hashstring.split(':');
@@ -618,6 +774,8 @@ function loadModalFromHash() {
}
} else if (hashstring === '#directmessages')
directMessagesPopup();
+ else if (hashstring === '#following')
+ openFollowingModal();
else if (hashstring === '#groupmessages')
openGroupMessagesModal();
else if (hashstring === '#groupmessages+newgroup')
@@ -649,7 +807,10 @@ function reTwistPopup(event, post, textArea) {
event.stopPropagation();
if (!defaultScreenName) {
- alert(polyglot.t('You have to log in to retransmit messages.'));
+ alertPopup({
+ //txtTitle: polyglot.t(''), add some title (not 'error', please) or just KISS
+ txtMessage: polyglot.t('You have to log in to retransmit messages.')
+ });
return;
}
@@ -669,8 +830,13 @@ function reTwistPopup(event, post, textArea) {
modal.content.find('.switch-mode')
.text(polyglot.t('Switch to Reply'))
- .on('click', (function(event) {replyInitPopup(event, post,
- $(event.target).closest('form').find('textarea').detach());}).bind(post))
+ .on('click', {post: post},
+ function(event) {
+ var textArea = $(event.target).closest('form').find('textarea').detach();
+ closePrompt(event.target);
+ replyInitPopup(event, event.data.post, textArea);
+ }
+ )
;
var replyArea = modal.content.find('.post-area .post-area-new');
@@ -707,8 +873,13 @@ function replyInitPopup(e, post, textArea) {
modal.content.find('.switch-mode')
.text(polyglot.t('Switch to Retransmit'))
- .on('click', (function(event) {reTwistPopup(event, post,
- $(event.target).closest('form').find('textarea').detach())}).bind(post))
+ .on('click', {post: post},
+ function(event) {
+ var textArea = $(event.target).closest('form').find('textarea').detach();
+ closePrompt(event.target);
+ reTwistPopup(event, event.data.post, textArea);
+ }
+ )
;
var replyArea = modal.content.find('.post-area .post-area-new').addClass('open');
@@ -734,48 +905,144 @@ function closeThis() {
$(this).slideUp('fast');
}
-function toggleFollowButton(username, toggleUnfollow, bindFunc) {
- if (!username)
+function toggleFollowButton(req) {
+ if (!req || !req.peerAlias)
return;
- if (toggleUnfollow) {
- $('[data-screen-name="'+username+'"]').find('.follow')
+ if (req.toggleUnfollow) {
+ if (!req.button || !req.button.jquery)
+ req.button = getElem('[data-screen-name="' + req.peerAlias + '"]').find('.follow');
+ req.button
+ .text(polyglot.t('Unfollow'))
.removeClass('follow')
.addClass('unfollow')
.off('click')
- .on('click',
- (function(e) {
- e.stopPropagation();
-
- unfollow(this.username.toString(),
- (function() {
- toggleFollowButton(this.username);
- if (this.bindFunc)
- this.bindFunc;
- }).bind({username: this.username, bindFunc: this.bindFunc})
- );
- }).bind({username: username, bindFunc: bindFunc})
- )
- .text(polyglot.t('Unfollow'))
- .trigger('eventToggleUnfollow')
+ .on('click', {peerAlias: req.peerAlias}, clickUnfollow)
;
} else {
- $('[data-screen-name="'+username+'"]').find('.unfollow')
+ if (!req.button || !req.button.jquery)
+ req.button = getElem('[data-screen-name="' + req.peerAlias + '"]').find('.unfollow');
+ req.button
+ .text(polyglot.t('Follow'))
.removeClass('unfollow')
.addClass('follow')
.off('click')
- .on('click',
- (function(e) {
- userClickFollow(e);
- if (this.bindFunc)
- this.bindFunc;
- }).bind({bindFunc: bindFunc})
- )
- .text(polyglot.t('Follow'))
- .trigger('eventToggleFollow');
+ .on('click', {peerAlias: req.peerAlias}, clickFollow)
+ ;
}
}
+function clickFollow(event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (!defaultScreenName) {
+ alertPopup({
+ //txtTitle: polyglot.t(''), add some title (not 'error', please) or just KISS
+ txtMessage: polyglot.t('You have to log in to follow users.')
+ });
+ return;
+ }
+
+ var peerAlias = (event.data && event.data.peerAlias) ? event.data.peerAlias
+ : $(event.target).closest('[data-screen-name]').attr('data-screen-name');
+ var content = $('#following-config-modal-template').children().clone(true);
+
+ content.closest('.following-config-modal-content').attr('data-screen-name', peerAlias);
+ content.find('.following-config-method-message')
+ .html(htmlFormatMsg(polyglot.t('select_way_to_follow_@', {alias: peerAlias}), {markout: 'apply'}).html);
+ content.find('.following-screen-name b').text(peerAlias);
+
+ openModal({
+ classBase: '.prompt-wrapper', // FIXME it will be modal with advanced following set up in future
+ classAdd: 'following-config-modal',
+ content: content,
+ title: polyglot.t('Following config')
+ });
+}
+
+function clickUnfollow(event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ var peerAlias = (event.data && event.data.peerAlias) ? event.data.peerAlias
+ : $(event.target).closest('[data-screen-name]').attr('data-screen-name');
+
+ confirmPopup({
+ txtMessage: polyglot.t('confirm_unfollow_@', {alias: peerAlias}),
+ cbConfirm: function (peerAlias) {
+ unfollow(peerAlias,
+ function(req) {
+ $('.mini-profile .following-count').text(followingUsers.length - 1);
+ $('.wrapper .postboard .post').each(function() {
+ var elem = $(this);
+ if ((elem.find('[data-screen-name="' + req.peerAlias + '"]').length
+ && !elem.find(".post-rt-by .open-profile-modal").text())
+ || elem.find(".post-rt-by .open-profile-modal").text() === '@' + req.peerAlias)
+ elem.remove();
+ }); // FIXME also need to check list of pending posts to remove from there
+ toggleFollowButton({peerAlias: req.peerAlias});
+ var followingList = getElem('.following-own-modal .following-list');
+ if (followingList.length)
+ followingList.find('li[data-peer-alias="' + req.peerAlias + '"]').remove();
+ }, {peerAlias: peerAlias}
+ );
+ },
+ cbConfirmReq: peerAlias
+ });
+}
+
+function setFollowingMethod(event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ var button = $(event.target);
+ var peerAlias = button.closest('.following-config-modal-content').attr('data-screen-name');
+
+ follow(peerAlias, button.hasClass('private') ? false : true,
+ function(req) {
+ $('.mini-profile .following-count').text(followingUsers.length - 1);
+ setTimeout(requestTimelineUpdate, 1000, 'latest', postsPerRefresh, [req.peerAlias], promotedPostsOnly);
+ toggleFollowButton({peerAlias: req.peerAlias, toggleUnfollow: req.toggleUnfollow});
+ var followingList = getElem('.following-own-modal .following-list');
+ if (followingList.length)
+ addToFollowingList(followingList, req.peerAlias);
+ }, {peerAlias: peerAlias, toggleUnfollow: true}
+ );
+}
+
+function followingListPublicCheckbox(event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ var tickSelection = function (req) {
+ if (req.isPublic === req.wasPublic) return;
+
+ var elem = $('.mini-profile-info[data-screen-name="' + req.peerAlias + '"] .public-following');
+ elem.toggleClass('private');
+ if (!req.isPublic)
+ elem.text(polyglot.t('Private'));
+ else
+ elem.text(polyglot.t('Public'));
+
+ //console.log('set following method of @' + peerAlias + ' for ' + isPublic);
+ follow(req.peerAlias, req.isPublic);
+ };
+ var elem = $(event.target);
+ var peerAlias = elem.closest('.mini-profile-info').attr('data-screen-name');
+ var wasPublic = !elem.hasClass('private');
+
+ confirmPopup({
+ txtMessage: polyglot.t('select_way_to_follow_@', {alias: peerAlias}),
+ txtConfirm: polyglot.t('Public'),
+ cbConfirm: tickSelection,
+ cbConfirmReq: {isPublic: true, wasPublic: wasPublic, peerAlias: peerAlias},
+ txtCancel: polyglot.t('Private'),
+ cbCancel: tickSelection,
+ cbCancelReq: {isPublic: false, wasPublic: wasPublic, peerAlias: peerAlias}
+ });
+}
+
function postExpandFunction(e, postLi) {
if (!postLi.hasClass('original'))
return;
@@ -825,23 +1092,26 @@ function postExpandFunction(e, postLi) {
e.stopPropagation();
}
-function postReplyClick(e) {
+function postReplyClick(event) {
if (!defaultScreenName) {
- e.stopPropagation();
- alert(polyglot.t('You have to log in to post replies.'));
+ event.stopPropagation();
+ alertPopup({
+ //txtTitle: polyglot.t(''), add some title (not 'error', please) or just KISS
+ txtMessage: polyglot.t('You have to log in to post replies.')
+ });
return;
}
var post = $(this).closest('.post');
if (!post.hasClass('original'))
- replyInitPopup(e, $.evalJSON(post.find('.post-data').attr('data-userpost')));
+ replyInitPopup(event, $.evalJSON(post.find('.post-data').attr('data-userpost')));
else {
if (!post.closest('.post.open').length)
- postExpandFunction(e, post);
- composeNewPost(e, post.find('.post-area-new'));
+ postExpandFunction(event, post);
+ composeNewPost(event, post.find('.post-area-new'));
}
- e.stopPropagation();
+ event.stopPropagation();
}
// Expande Área do Novo post
@@ -1588,7 +1858,7 @@ function postSubmit(e, oldLastPostId) {
}
if (btnPostSubmit.closest('.prompt-wrapper').length)
- closePrompt();
+ closePrompt(btnPostSubmit);
else {
textArea.val('').attr('placeholder', polyglot.t('Your message was sent!'));
btnPostSubmit.closest('form').find('.post-area-remaining').text('140');
@@ -1601,13 +1871,14 @@ function postSubmit(e, oldLastPostId) {
}
}
-function retweetSubmit(e) {
- e.stopPropagation();
- e.preventDefault();
+function retweetSubmit(event) {
+ event.preventDefault();
+ event.stopPropagation();
- newRtMsg($(this).closest('.prompt-wrapper').find('.post-data'));
+ var prompt = $(event.target).closest('.prompt-wrapper');
- closePrompt();
+ newRtMsg(prompt.find('.post-data'));
+ closePrompt(prompt);
}
function changeStyle() {
@@ -1680,13 +1951,7 @@ function replaceDashboards() {
}
function initInterfaceCommon() {
- $('.modal-close, .modal-blackout').not('.prompt-close').on('click', function() {
- if ($('.modal-content').attr('style') != undefined)
- $('.modal-content').removeAttr('style');
- $('.modal-back').css('display', 'none');
- $('.mark-all-as-read').css('display', 'none');
- closeModal();
- });
+ $('.modal-close, .modal-blackout').not('.prompt-close').on('click', closeModal);
$('.minimize-modal').on('click', function (event) {
minimizeModal($(event.target).closest('.modal-wrapper'));
@@ -1696,13 +1961,12 @@ function initInterfaceCommon() {
$('.prompt-close').on('click', closePrompt);
- /*
- $('.modal-back').on('click', function() {
- if ($('.modal-content .direct-messages-list')[0]) return;
- directMessagesPopup();
- $('.modal-content').removeAttr('style');
+ $('button.follow').on('click', clickFollow);
+
+ $('.following-config-method-buttons .public-following').on('click', function(event) {
+ setFollowingMethod(event);
+ closePrompt(event);
});
- */
$('.post-text').on('click', 'a', function(e) {e.stopPropagation();});
$('.post-reply').on('click', postReplyClick);
@@ -1726,7 +1990,7 @@ function initInterfaceCommon() {
;
$('.post-submit').on('click', postSubmit);
$('.modal-propagate').on('click', retweetSubmit);
- $('.expanded-content .show-more').on('click',
+ $('.expanded-content .show-more').on('mouseup',
{feeder: '.module.post.original.open .module.post.original .post-data'}, openConversationClick);
if ($.Options.unicodeConversion.val === 'disable')
@@ -1792,6 +2056,10 @@ function initInterfaceCommon() {
}
}
+function extractTemplate(selector) {
+ return $(selector).appendTo(twister.html.detached).children();
+}
+
function promptCopyAttrData(event) {
window.prompt(polyglot.t('copy_to_clipboard'), $(event.target).attr('data'));
}
@@ -1855,14 +2123,17 @@ function setTextcompleteDropdownListPos(position) {
return this;
}
-$(document).ready(function()
-{
+$(document).ready(function () {
+ twister.html.blanka.appendTo('body').hide();
+ twister.tmpl.followingList = extractTemplate('#template-following-list');
+ twister.tmpl.followingUser = extractTemplate('#template-following-user');
+ twister.tmpl.postRtReference = extractTemplate('#template-post-rt-reference')
+ .on('mouseup', {feeder: '.post-rt-reference'}, openConversationClick);
+ twister.tmpl.postRtBy = extractTemplate('#template-post-rt-by');
+
var path = window.location.pathname;
var page = path.split("/").pop();
- if (page.indexOf("following.html") === 0) {
- initInterfaceFollowing();
- initHashWatching();
- } else if (page.indexOf("login.html") === 0) {
+ if (page.indexOf("login.html") === 0) {
initInterfaceLogin();
} else if (page.indexOf("network.html") === 0) {
initInterfaceNetwork();
diff --git a/js/interface_home.js b/js/interface_home.js
index 6510b87..c7b4e1b 100644
--- a/js/interface_home.js
+++ b/js/interface_home.js
@@ -100,22 +100,6 @@ var InterfaceFunctions = function() {
args.cbFunc(args.cbArg);
}, {cbFunc:cbFunc, cbArg:cbArg});
- $(window)
- .on('eventFollow', function(e, user) {
- $('.mini-profile .following-count').text(followingUsers.length - 1);
- setTimeout(requestTimelineUpdate, 1000, 'latest', postsPerRefresh, [user], promotedPostsOnly);
- })
- .on('eventUnfollow', function(e, user) {
- $('.mini-profile .following-count').text(followingUsers.length - 1);
- $('.wrapper .postboard .post').each( function() {
- var elem = $(this);
- if ((elem.find('[data-screen-name="' + user + '"]').length
- && !elem.find(".post-rt-by .open-profile-modal").text())
- || elem.find(".post-rt-by .open-profile-modal").text() === '@' + user)
- elem.remove();
- });
- });
-
if ($.Options.WhoToFollow.val === 'enable')
initWhoToFollow();
else
diff --git a/js/interface_localization.js b/js/interface_localization.js
index 47ede16..a76107b 100644
--- a/js/interface_localization.js
+++ b/js/interface_localization.js
@@ -53,6 +53,7 @@ if(preferredLanguage == "en"){
"If you stay in this page your actions may not work.\n" +
"Do you want to check [Network Status page](%{page}) instead?",
"confirm_terminate_daemon": "Are you sure you want to exit the daemon?\nThe Twister client will stop working.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Change user",
"Checking...": "Checking...", // checking if username is available
"Collapse": "Collapse", // smaller view of a post
@@ -68,7 +69,7 @@ if(preferredLanguage == "en"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Direct messages with %{username}",
"Disable": "Disable",
- "Display mentions to @": "Display mentions to @",
+ "display_mentions": "Display mentions",
"Display retransmissions": "Display retransmissions",
"DNS to obtain list of peers:": "DNS to obtain list of peers:",
"downloading_block_chain": "Downloading block chain, please wait before continuing (block chain is %{days} days old).",
@@ -84,7 +85,7 @@ if(preferredLanguage == "en"){
"File APIs not supported in this browser.": "File APIs not supported in this browser.",
"Follow": "Follow",
"Following config": "Following config",
- "Which way do you want to follow": "Which way do you want to follow",
+ "select_way_to_follow_@": "Which way do you want to follow @%{alias}",
"Followed by": "Followed by",
"followed_by": "Followed by %{username}",
"Followers": "Followers",
@@ -126,6 +127,7 @@ if(preferredLanguage == "en"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Not available", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister cannot perform desktop notification: unknown error occured.",
"notify_desktop_perm_denied": "Twister cannot perform desktop notification: permission denied.\n\nIf you want to get notifications, allow them for %{this_domain} in settings of your browser.",
"notify_desktop_test": "All the twisters gonna twist.\nNow you are welcome too.",
@@ -159,7 +161,7 @@ if(preferredLanguage == "en"){
"seconds": "%{smart_count} second |||| %{smart_count} seconds",
"send": "send",
"Send post with username": "Send post with username ",
- "Sent Direct Message": "Sent Direct Message",
+ "send_DM": "Send direct message",
"Sent Post to @": "Sent Post to @",
"Setup account": "Setup account",
"The File APIs are not fully supported in this browser.": "The File APIs are not fully supported in this browser.",
@@ -374,6 +376,7 @@ if(preferredLanguage == "es"){
"Si te quedas en esta página tus acciones pueden no funcionar.\n" +
"¿Quieres comprobar la [página de estado de la red](%{page}) en su lugar?",
"confirm_terminate_daemon": "Are you sure you want to exit the daemon?\nThe Twister client will stop working.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Cambiar de usuario",
"Checking...": "Comprobando ...", // checking if username is available
"Collapse": "Colapsar", // smaller view of a post
@@ -389,7 +392,7 @@ if(preferredLanguage == "es"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Mensajes directos con %{username}",
"Disable": "Inhabilitar",
- "Display mentions to @": "Visualización de menciones a @",
+ "display_mentions": "Visualización de menciones",
"Display retransmissions": "Visualización de retransmisiones",
"DNS to obtain list of peers:": "DNS para obtener la lista de los pares:",
"downloading_block_chain": "Descarga de la cadena de bloques, por favor espere antes de continuar (la cadena de bloques esta %{days} días).",
@@ -405,7 +408,7 @@ if(preferredLanguage == "es"){
"File APIs not supported in this browser.": "Los archivos API no compatibles con este navegador",
"Follow": "Seguir",
"Following config": "Following config",
- "Which way do you want to follow": "Which way do you want to follow",
+ "select_way_to_follow_@": "Which way do you want to follow @%{alias}",
"Followed by": "Seguido por",
"followed_by": "Seguido por %{username}",
"Followers": "Seguidores",
@@ -447,6 +450,7 @@ if(preferredLanguage == "es"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "Nadie", // used to promote a post without attaching the user
"Not available": "No disponible", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister cannot perform desktop notification: unknown error occured.",
"notify_desktop_perm_denied": "Twister cannot perform desktop notification: permission denied.\n\nIf you want to get notifications, allow them for %{this_domain} in settings of your browser.",
"notify_desktop_test": "All the twisters gonna twist.\nNow you are welcome too.",
@@ -480,7 +484,7 @@ if(preferredLanguage == "es"){
"seconds": "%{smart_count} segundo |||| %{smart_count} segundos",
"send": "send",
"Send post with username": "Enviar post con nombre de usuario ",
- "Sent Direct Message": "Mensaje directo",
+ "send_DM": "Mensaje directo",
"Sent Post to @": "El Post enviado a @",
"Setup account": "Configuración de la cuenta",
"The File APIs are not fully supported in this browser.": "Las API de archivos no son totalmente compatibles con este navegador.",
@@ -679,6 +683,7 @@ if(preferredLanguage == "uk"){
"Якщо ви залишитесь на цій сторінці ваші дії можуть не спрацювати.\n" +
"Чи бажаєте ви перевірити [сторінку зі статусом мережі](%{page})?",
"confirm_terminate_daemon": "Ви впевнені, що бажаєте завершити роботу?\nКлієнт Twister буде зупинено допоки ви не запустите його знову.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Змінити користувача",
"Checking...": "Перевірка...", // checking if username is available
"Collapse": "Згорнути", // smaller view of a post
@@ -694,7 +699,7 @@ if(preferredLanguage == "uk"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Direct messages with %{username}",
"Disable": "Вимкнено",
- "Display mentions to @": "Показати сповіщення @",
+ "display_mentions": "Показати сповіщення",
"Display retransmissions": "Показати пересилання",
"DNS to obtain list of peers:": "DNS для отримання пірів:",
"dns address": "адреса DNS",
@@ -711,7 +716,7 @@ if(preferredLanguage == "uk"){
"File APIs not supported in this browser.": "File APIs не підтримуєтся цим браузером.",
"Follow": "Читати",
"Following config": "Налаштування читання",
- "Which way do you want to follow": "У який спосіб ви бажаєте читати",
+ "select_way_to_follow_@": "У який спосіб ви бажаєте читати @%{alias}",
"Followed by": "читає",
"followed_by": "%{username} читає",
"Followers": "Читачі",
@@ -753,6 +758,7 @@ if(preferredLanguage == "uk"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "анонім", // used to promote a post without attaching the user
"Not available": "Не доступне", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister не може створити сповіщення: невідома помилка.",
"notify_desktop_perm_denied": "Twister не може створити сповіщення на робочому столі: доступ обмежено.\n\nЯкщо ви бажаєте отримувати сповіщення, дозвольте їх виконання в налаштуваннях браузера для %{this_domain}.",
"notify_desktop_test": "Є дещо новеньке у стрічці.",
@@ -786,7 +792,7 @@ if(preferredLanguage == "uk"){
"seconds": "%{smart_count} секунда |||| %{smart_count} секунд",
"send": "відіслати",
"Send post with username": "Надіслати повідомлення від",
- "Sent Direct Message": "Надіслати особисте повідомлення",
+ "send_DM": "Надіслати особисте повідомлення",
"Sent Post to @": "Надіслати твіст @",
"Setup account": "Обліковий запис",
"The File APIs are not fully supported in this browser.": "File APIs не повністю підтримується браузером.",
@@ -983,6 +989,7 @@ if(preferredLanguage == "zh-CN"){
"如果你留在此页面你的操作将不会生效。\n" +
"你要跳转到[网络状态页](%{page})吗?",
"confirm_terminate_daemon": "你确定要退出后台进程?\nTwister 客户端将停止工作。",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "切换用户",
"Checking...": "检查中...", // checking if username is available
"Collapse": "折叠", // smaller view of a post
@@ -998,7 +1005,7 @@ if(preferredLanguage == "zh-CN"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Direct messages with %{username}",
"Disable": "关闭",
- "Display mentions to @": "显示@",
+ "display_mentions": "显示",
"Display retransmissions": "显示转发",
"DNS to obtain list of peers:": "用DNS获取节点列表:",
"downloading_block_chain": "区块链下载中,请等待下载完成(区块链仍落后 %{days} 天)。",
@@ -1014,7 +1021,7 @@ if(preferredLanguage == "zh-CN"){
"File APIs not supported in this browser.": "这个浏览器不支持 File API。",
"Follow": "关注",
"Following config": "关注配置",
- "Which way do you want to follow": "你想以哪种方式关注",
+ "select_way_to_follow_@": "你想以哪种方式关注 @%{alias}",
"Followed by": "关注者",
"followed_by": "被 %{username} 关注",
"Followers": "粉丝",
@@ -1056,6 +1063,7 @@ if(preferredLanguage == "zh-CN"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "无名", // used to promote a post without attaching the user
"Not available": "用户名不可用", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister 无法发出桌面提醒:发生未知错误。",
"notify_desktop_perm_denied": "Twister 无法发出桌面提醒:权限被拒绝。\n\n如果你想收到提醒,请在你的浏览器设置中允许 %{this_domain} 发出提醒。",
"notify_desktop_test": "我们都在用 Twister。\n欢迎你的加入。",
@@ -1089,7 +1097,7 @@ if(preferredLanguage == "zh-CN"){
"seconds": "%{smart_count} 秒",
"send": "发送",
"Send post with username": "发送推文的用户名",
- "Sent Direct Message": "发送私信",
+ "send_DM": "发送私信",
"Sent Post to @": "发送推文 @",
"Setup account": "设置账号",
"The File APIs are not fully supported in this browser.": "这个浏览器不能完全支持 File API。",
@@ -1304,6 +1312,7 @@ if(preferredLanguage == "nl"){
"If you stay in this page your actions may not work.\n" +
"Do you want to check [Network Status page](%{page}) instead?",
"confirm_terminate_daemon": "Are you sure you want to exit the daemon?\nThe Twister client will stop working.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Gebruiker wijzigen",
"Checking...": "Controleren...", // checking if username is available
"Collapse": "Uitklappen", // smaller view of a post
@@ -1319,7 +1328,7 @@ if(preferredLanguage == "nl"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Direct messages with %{username}",
"Disable": "Uitschakelen",
- "Display mentions to @": "Toon vermeldingen voor @",
+ "display_mentions": "Toon vermeldingen",
"Display retransmissions": "Toon retransmissions",
"DNS to obtain list of peers:": "DNS om peers lijst op te halen:",
"downloading_block_chain": "Bezig met downloaden block chain, wacht a.u.b. voordat je doorgaat (block chain is %{days} dagen oud).",
@@ -1335,7 +1344,7 @@ if(preferredLanguage == "nl"){
"File APIs not supported in this browser.": "File APIs worden nie ondersteund in deze browser.",
"Follow": "Volgen",
"Following config": "Following config",
- "Which way do you want to follow": "Which way do you want to follow",
+ "select_way_to_follow_@": "Which way do you want to follow @%{alias}",
"Followed by": "Gevolgd door",
"followed_by": "Gevolgd door %{username}",
"Followers": "Volgers",
@@ -1377,6 +1386,7 @@ if(preferredLanguage == "nl"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Niet beschikbaar", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister cannot perform desktop notification: unknown error occured.",
"notify_desktop_perm_denied": "Twister cannot perform desktop notification: permission denied.\n\nIf you want to get notifications, allow them for %{this_domain} in settings of your browser.",
"notify_desktop_test": "All the twisters gonna twist.\nNow you are welcome too.",
@@ -1410,7 +1420,7 @@ if(preferredLanguage == "nl"){
"seconds": "%{smart_count} seconde |||| %{smart_count} seconden",
"send": "Verstuur",
"Send post with username": "Verstuur bericht met gebruikersnaam ",
- "Sent Direct Message": "Verstuur privébericht",
+ "send_DM": "Verstuur privébericht",
"Sent Post to @": "Verstuur bericht naar @",
"Setup account": "Account instellingen",
"The File APIs are not fully supported in this browser.": "The File APIs are not fully supported in this browser.",
@@ -1609,6 +1619,7 @@ if(preferredLanguage == "it"){
"Se rimani su questa pagina, Twister potrebbe non funzionare.\n" +
"Vuoi controllare lo [stato della rete Twister](%{page}), invece?",
"confirm_terminate_daemon": "Are you sure you want to exit the daemon?\nThe Twister client will stop working.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Cambia utente",
"Checking...": "Controllo in corso...", // checking if username is available
"Collapse": "Chiudi", // smaller view of a post
@@ -1624,7 +1635,7 @@ if(preferredLanguage == "it"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Messaggi Diretti come %{username}",
"Disable": "Disabilitato",
- "Display mentions to @": "Mostra le menzioni di @",
+ "display_mentions": "Mostra le menzioni",
"Display retransmissions": "Mostra Ripubblicazioni",
"DNS to obtain list of peers:": "DNS per la lista dei nodi:",
"downloading_block_chain": "Scaricamento della catena di blocchi in corso, attendere prego (la catena risale a %{days} giorni fa).",
@@ -1640,7 +1651,7 @@ if(preferredLanguage == "it"){
"File APIs not supported in this browser.": "File APIs non supportati in questo browser.",
"Follow": "Segui",
"Following config": "Following config",
- "Which way do you want to follow": "Which way do you want to follow",
+ "select_way_to_follow_@": "Which way do you want to follow @%{alias}",
"Followed by": "Seguito da",
"followed_by": "Seguiti da %{username}",
"Followers": "Lettori",
@@ -1682,6 +1693,7 @@ if(preferredLanguage == "it"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "nessuno", // used to promote a post without attaching the user
"Not available": "Non disponibile", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister cannot perform desktop notification: unknown error occured.",
"notify_desktop_perm_denied": "Twister cannot perform desktop notification: permission denied.\n\nIf you want to get notifications, allow them for %{this_domain} in settings of your browser.",
"notify_desktop_test": "All the twisters gonna twist.\nNow you are welcome too.",
@@ -1715,7 +1727,7 @@ if(preferredLanguage == "it"){
"seconds": "%{smart_count} secondo |||| %{smart_count} secondi",
"send": "Invia",
"Send post with username": "Pubblica come utente ",
- "Sent Direct Message": "Messaggi Diretti inviati",
+ "send_DM": "Messaggi Diretti inviati",
"Sent Post to @": "Messaggi inviati a @",
"Setup account": "Configurazione Utente",
"The File APIs are not fully supported in this browser.": "Le API File non sono interamente supportate da questo browser.",
@@ -1912,6 +1924,7 @@ if(preferredLanguage == "fr"){
"Si vous restez dans cette page vos actions peuvent ne pas être prises en compte.\n" +
"Voulez-vous consulter la [page d'état du réseau](%{page}) à la place?",
"confirm_terminate_daemon": "Are you sure you want to exit the daemon?\nThe Twister client will stop working.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Changer d'utilisateur",
"Checking...": "Vérification...", // checking if username is available
"Collapse": "Fermer", // smaller view of a post
@@ -1927,7 +1940,7 @@ if(preferredLanguage == "fr"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Messages privés avec %{username}",
"Disable": "Désactiver",
- "Display mentions to @": "Afficher les mentions pour @",
+ "display_mentions": "Afficher les mentions",
"Display retransmissions": "Afficher les retransmissions",
"DNS to obtain list of peers:": "DNS où obtenir une liste des pairs:",
"downloading_block_chain": "Téléchargement de la chaîne de blocs, veuillez patienter avant de continuer (la chaîne de blocs a %{days} jours de retard).",
@@ -1943,7 +1956,7 @@ if(preferredLanguage == "fr"){
"File APIs not supported in this browser.": "L'API de fichiers n'est pas pris en charge dans votre navigateur.",
"Follow": "Suivre",
"Following config": "Following config",
- "Which way do you want to follow": "Which way do you want to follow",
+ "select_way_to_follow_@": "Which way do you want to follow @%{alias}",
"Followed by": "Suivi par",
"followed_by": "Suivi par %{username}",
"Followers": "Abonnés",
@@ -1985,6 +1998,7 @@ if(preferredLanguage == "fr"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Non disponible", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Impossible d'afficher les notifications: une erreur inconnue est survenue.",
"notify_desktop_perm_denied": "Impossible d'afficher les notifications: autorisation refusée.\n\nSi tu souhaites afficher les notifications, autorise le %{this_domain} dans les paramêtres de ton navigateur.",
"notify_desktop_test": "All the twisters gonna twist.\nBienvenue à toi!",
@@ -2018,7 +2032,7 @@ if(preferredLanguage == "fr"){
"seconds": "%{smart_count} seconde |||| %{smart_count} secondes",
"send": "envoyer",
"Send post with username": "Envoyer le billet avec le pseudo",
- "Sent Direct Message": "Message privé envoyé",
+ "send_DM": "Message privé envoyé",
"Sent Post to @": "Envoyer un billet à @",
"Setup account": "Configuration du compte",
"The File APIs are not fully supported in this browser.": "L'API de fichier n'est pas entièrement pris en charge dans votre navigateur.",
@@ -2219,6 +2233,7 @@ if(preferredLanguage == "ru"){
"Если вы останетесь на этой странице ваши действия могут быть не выполнены.\n" +
"Не хотите перейти на [страницу настройки сети](%{page})?",
"confirm_terminate_daemon": "Вы уверены, что хотите выключить демон?\nTwister клиент перестанет работать.",
+ "confirm_unfollow_@": "Действительно отписаться от @%{alias}?",
"Change user": "Сменить пользователя",
"Checking...": "Проверка...",
"Collapse": "Свернуть",
@@ -2234,7 +2249,7 @@ if(preferredLanguage == "ru"){
"Group Messages — Join Group": "Групповые сообщения — Присоединиться к группе",
"direct_messages_with": "Личная переписка с %{username}",
"Disable": "Отключено",
- "Display mentions to @": "Показать ответы для @",
+ "display_mentions": "Показать упоминания",
"Display retransmissions": "Показать репосты",
"DNS to obtain list of peers:": "DNS адрес для получения пиров:",
"downloading_block_chain": "Загрузка цепочки блоков, пожалуйста подождите, (Цепочка блоков устарела на %{days} дней).",
@@ -2250,11 +2265,11 @@ if(preferredLanguage == "ru"){
"File APIs not supported in this browser.": "Ваш браузер не поддерживает File APIs.",
"Follow": "Подписаться",
"Following config": "Настройка подписки",
- "Which way do you want to follow": "Выберите тип подписки на",
+ "select_way_to_follow_@": "Выбери же тип подписки на @%{alias}",
"Followed by": "Подписчик у",
"followed_by": "%{username} подписан",
- "Followers": "Читателей",
- "Following": "Читаемых",
+ "Followers": "Читатели",
+ "Following": "Читаемые",
"Following users": "Подписанные пользователи",
"Force connection to peer:": "Принудительно подключиться к пиру:",
"General information": "Основное",
@@ -2292,6 +2307,7 @@ if(preferredLanguage == "ru"){
"new_group_messages": "%{smart_count} новое сообщение в группе |||| %{smart_count} новых групповых сообщений",
"nobody": "Анонимно", // used to promote a post without attaching the user
"Not available": "Недоступно",
+ "warn_following_not_any": "Пока что таки нет читаемых!\nПоди ж найди кого-нибудь да и подпишись.",
"notify_desktop_error": "Твистер не может выполнить уведомление: произошла неизвестная ошибка.",
"notify_desktop_perm_denied": "Твистер не может выполнить уведомление: разрешение не получено.\n\nЧтобы получать уведомления, разрешите их для %{this_domain} в настройках вашего браузера.",
"notify_desktop_test": "Одна лягушка сказала:\n'если не буду квакать — лопну'.\nВы нужны нам, берегите себя.",
@@ -2325,7 +2341,7 @@ if(preferredLanguage == "ru"){
"seconds": "%{smart_count} секунда |||| %{smart_count} секунд",
"send": "отправить",
"Send post with username": "Отправить сообщение от имени",
- "Sent Direct Message": "Отправить личное сообщение",
+ "send_DM": "Отправить личное сообщение",
"Sent Post to @": "Отправить сообщение для @",
"Setup account": "Настроить аккаунт",
"The File APIs are not fully supported in this browser.": "File APIs не полностью поддерживается этим браузером.",
@@ -2528,6 +2544,7 @@ if(preferredLanguage == "de"){
"Wenn du auf dieser Seite bleibst können deine Handlungen nicht funktionieren.\n" +
"Möchtest du stattdessen den [Netzwerkstatus](%{page}) überprüfen?",
"confirm_terminate_daemon": "Are you sure you want to exit the daemon?\nThe Twister client will stop working.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Benutzer wechseln",
"Checking...": "Überprüfe...", // checking if username is available
"Collapse": "Einklappen", // smaller view of a post
@@ -2543,7 +2560,7 @@ if(preferredLanguage == "de"){
"Group Messages — Join Group": "Gruppennachrichten — Gruppe beitreten",
"direct_messages_with": "Direktnachrichten mit %{username}",
"Disable": "Deaktivieren",
- "Display mentions to @": "Zeige Erwähnungen von @", //Ist das richtig? Ich weiß nicht, in welchem Zusammenhang das benutzt wird.
+ "display_mentions": "Zeige Erwähnungen", // Ist das richtig? Ich weiß nicht, in welchem Zusammenhang das benutzt wird.
"Display retransmissions": "Weiterleitungen anzeigen",
"DNS to obtain list of peers:": "DNS um Peer-Liste abzurufen:",
"dns address": "DNS-Adresse",
@@ -2560,7 +2577,7 @@ if(preferredLanguage == "de"){
"File APIs not supported in this browser.": "File APIs werden von diesem Browser nicht unterstützt.",
"Follow": "Folgen",
"Following config": "Following config",
- "Which way do you want to follow": "Which way do you want to follow",
+ "select_way_to_follow_@": "Which way do you want to follow @%{alias}",
"Followed by": "Gefolgt von",
"followed_by": "Gefolgt von %{username}",
"Followers": "Followers",
@@ -2602,6 +2619,7 @@ if(preferredLanguage == "de"){
"new_group_messages": "%{smart_count} neue Gruppen-Nachricht |||| %{smart_count} neue Gruppen-Nachrichten",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Nicht verfügbar", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister kann keine Desktop-Meldungen anzeigen: ein unbekannter Fehler trat auf.",
"notify_desktop_perm_denied": "Twister kann keine Desktop-Meldungen anzeigen: Keine Berechtigung.\n\nWenn Du Meldungen angezeigt haben möchtest, erlaube sie für %{this_domain} in den Einstellungen Deines Browsers.",
"notify_desktop_test": "All die Twisterer werden twisten..\nDu bist nun auch willkommen!",
@@ -2635,7 +2653,7 @@ if(preferredLanguage == "de"){
"seconds": "%{smart_count} Sekunde |||| %{smart_count} Sekunden",
"send": "senden",
"Send post with username": "Sende Post mit Benutzernamen ",
- "Sent Direct Message": "Direktnachricht senden",
+ "send_DM": "Direktnachricht senden",
"Sent Post to @": "Sende Post an @",
"Setup account": "Accounteinstellungen",
"The File APIs are not fully supported in this browser.": "Die File-API's werden von diesem Browser nicht vollständig unterstützt.",
@@ -2835,6 +2853,7 @@ if(preferredLanguage == "ja"){
"このページを使用しつづければ、あなたの変更が適用されないおそれがあります。\n" +
"[ネットワーク状態ペー](%{page})ジへ移動して確認しますか?",
"confirm_terminate_daemon": "Are you sure you want to exit the daemon?\nThe Twister client will stop working.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "ユーザーを変更",
"Checking...": "チェック...", // checking if username is available
"Collapse": "閉じる", // smaller view of a post
@@ -2850,7 +2869,7 @@ if(preferredLanguage == "ja"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Direct messages with %{username}",
"Disable": "停止",
- "Display mentions to @": "メンションを表示する",
+ "display_mentions": "メンションを表示する",
"Display retransmissions": "リトランスミットを表示する",
"DNS to obtain list of peers:": "ピア取得用のDNS:",
"downloading_block_chain": "ブロックチェインをダウンロードしています。しばらくお待ちください。(ブロックチェーンは%{days}日送れています)",
@@ -2866,7 +2885,7 @@ if(preferredLanguage == "ja"){
"File APIs not supported in this browser.": "利用しているブラウザはファイルAPIをサポートしていません。",
"Follow": "フォロー",
"Following config": "Following config",
- "Which way do you want to follow": "Which way do you want to follow",
+ "select_way_to_follow_@": "Which way do you want to follow @%{alias}",
"Followed by": "フォローされている",
"followed_by": "%{username}にフォローされている",
"Followers": "フォロワー",
@@ -2908,6 +2927,7 @@ if(preferredLanguage == "ja"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "ナナシ", // used to promote a post without attaching the user
"Not available": "使用中", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister cannot perform desktop notification: unknown error occured.",
"notify_desktop_perm_denied": "Twister cannot perform desktop notification: permission denied.\n\nIf you want to get notifications, allow them for %{this_domain} in settings of your browser.",
"notify_desktop_test": "All the twisters gonna twist.\nNow you are welcome too.",
@@ -2941,7 +2961,7 @@ if(preferredLanguage == "ja"){
"seconds": "%{smart_count} 秒 |||| %{smart_count} 秒",
"send": "送信",
"Send post with username": "プロモートメッセージの送信元",
- "Sent Direct Message": "ダイレクトメッセージを送る",
+ "send_DM": "ダイレクトメッセージを送る",
"Sent Post to @": "メンションを投稿する",
"Setup account": "アカウント設定",
"The File APIs are not fully supported in this browser.": "ご使用のブラウザーは完全にファイルAPIに対応していません。",
@@ -3138,6 +3158,7 @@ if(preferredLanguage == "pt-BR"){
"Se permanecer nesta página suas ações podem não ter efeito.\n" +
"Gostaria de verificar o [Estado da Rede](%{page}) ao invés disso?",
"confirm_terminate_daemon": "Are you sure you want to exit the daemon?\nThe Twister client will stop working.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Trocar usuário",
"Checking...": "Verificando...", // checking if username is available
"Collapse": "Recolher", // smaller view of a post
@@ -3153,7 +3174,7 @@ if(preferredLanguage == "pt-BR"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Mensagens Diretas com %{username}",
"Disable": "Desabilitado",
- "Display mentions to @": "Exibir menções a @",
+ "display_mentions": "Exibir menções",
"Display retransmissions": "Exibir retransmissões",
"DNS to obtain list of peers:": "DNS para obter a lista de nós:",
"downloading_block_chain": "Baixando a Cadeia de Blocos, por favor aguarde (A Cadeia de Blocos está %{days} dias desatualizada).",
@@ -3169,7 +3190,7 @@ if(preferredLanguage == "pt-BR"){
"File APIs not supported in this browser.": "O gerenciamento de arquivos não é suportado neste navegador.",
"Follow": "Seguir",
"Following config": "Following config",
- "Which way do you want to follow": "Which way do you want to follow",
+ "select_way_to_follow_@": "Which way do you want to follow @%{alias}",
"Followed by": "Seguido por",
"followed_by": "Seguido por %{username}",
"Followers": "Seguidores",
@@ -3211,6 +3232,7 @@ if(preferredLanguage == "pt-BR"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Indisponível", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister cannot perform desktop notification: unknown error occured.",
"notify_desktop_perm_denied": "Twister cannot perform desktop notification: permission denied.\n\nIf you want to get notifications, allow them for %{this_domain} in settings of your browser.",
"notify_desktop_test": "All the twisters gonna twist.\nNow you are welcome too.",
@@ -3245,7 +3267,7 @@ if(preferredLanguage == "pt-BR"){
"seconds": "%{smart_count} segundo |||| %{smart_count} segundos",
"send": "enviar",
"Send post with username": "Promover esta mensagem como usuário",
- "Sent Direct Message": "Mensagens Diretas trocadas",
+ "send_DM": "Mensagens Diretas trocadas",
"Sent Post to @": "Postagens enviadas para @",
"Setup account": "Configurar conta",
"The File APIs are not fully supported in this browser.": "O gerenciamento de arquivos não é completamente suportado neste navegador.",
@@ -3445,6 +3467,7 @@ if(preferredLanguage == "tr"){
"Eğer bu sayfada kalırsanız eylemlerinizi işlemeyebilir.\n" +
"Bunun yerine [Ağ Durumu sayfasını](%{page}) kontrol etmek ister misiniz?",
"confirm_terminate_daemon": "Hizmeti sonlandırmak istiyor musun?\nTwister istemcisi çalışmayacak.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Kullanıcı değiştir",
"Checking...": "Denetleniyor...", // checking if username is available
"Collapse": "Kapat", // smaller view of a post
@@ -3460,7 +3483,7 @@ if(preferredLanguage == "tr"){
"Group Messages — Join Group": "Grup Mesajları — Gruba katıl",
"direct_messages_with": "%{username} ile Direk Mesajlar",
"Disable": "Kullanılmaz",
- "Display mentions to @": "@ adının geçtiği gönderiler",
+ "display_mentions": "@ adının geçtiği gönderiler", // FIXME
"Display retransmissions": "Tekrar iletimleri göster",
"DNS to obtain list of peers:": "Eş listesini almak için DNS:",
"downloading_block_chain": "Blok zinciri indiriliyor, devam edebilmek için lütfen bekleyiniz (blok zinciri %{days} günlük).",
@@ -3476,7 +3499,7 @@ if(preferredLanguage == "tr"){
"File APIs not supported in this browser.": "Tarayıcınızda dosya API'si desteklenmiyor.",
"Follow": "Takip et",
"Following config": "Takip ayarları",
- "Which way do you want to follow": "Nasıl takip etmek istiyorsun",
+ "select_way_to_follow_@": "Nasıl takip etmek istiyorsun @%{alias}",
"Followed by": "Takip edenler",
"followed_by": "%{username} tarafından takip edilenler",
"Followers": "Takipçiler",
@@ -3518,6 +3541,7 @@ if(preferredLanguage == "tr"){
"new_group_messages": "%{smart_count} yeni grup mesajı |||| %{smart_count} yeni grup mesajı",
"nobody": "hiçkimse", // used to promote a post without attaching the user
"Not available": "Kullanılamaz", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twister masaüstü uyarısını gösterimiyor: bilimeyen bir hata oluştu.",
"notify_desktop_perm_denied": "Twister masaüstü uyarısını gösteremiyor: yetkilendirme hatası.\n\nUyarıları almak istiyorsanız, tarayıcı ayarlarında %{this_domain} alan adı için izin veriniz.",
"notify_desktop_test": "Kasırga her yanı saracak\nBu karnavala hoşgeldin!",
@@ -3551,7 +3575,7 @@ if(preferredLanguage == "tr"){
"seconds": "%{smart_count} saniye |||| %{smart_count} saniye",
"send": "gönder",
"Send post with username": "İletiyi kullanıcı adıyla gönder ",
- "Sent Direct Message": "Direk Mesaj Gönder",
+ "send_DM": "Direk Mesaj Gönder",
"Sent Post to @": "@ Kullanıcıya Gönder",
"Setup account": "Hesap ayarları",
"The File APIs are not fully supported in this browser.": "Dosya API'si tarayıcınızda tam olarak desteklenmiyor.",
@@ -3749,6 +3773,7 @@ if(preferredLanguage == "cs"){
"Pokud zůstanete na této stránce, vaše akce možná nebudou fungovat.\n" +
"Chcete se místo toho podívat na [stav sítě](%{page})?",
"confirm_terminate_daemon": "Skutečně chcete ukončit server?\nTwister tím vypnete.",
+ "confirm_unfollow_@": "Are you sure you want to unfollow @%{alias}?",
"Change user": "Změnit uživatele",
"Checking...": "Ověřuji...", // checking if username is available
"Collapse": "Složit", // smaller view of a post
@@ -3764,7 +3789,7 @@ if(preferredLanguage == "cs"){
"Group Messages — Join Group": "Group Messages — Join Group",
"direct_messages_with": "Direct messages with %{username}",
"Disable": "Vypnuto",
- "Display mentions to @": "Zobrazit zmínky o @",
+ "display_mentions": "Zobrazit zmínky",
"Display retransmissions": "Zobrazit přeposlané",
"DNS to obtain list of peers:": "DNS pro načtení seznamu uzlů:",
"downloading_block_chain": "Stahuji blockchain, prosím počkejte (blockchain je %{days} dnů starý).",
@@ -3780,7 +3805,7 @@ if(preferredLanguage == "cs"){
"File APIs not supported in this browser.": "Upozornění: váš webový prohlížeč nepodporuje File API.",
"Follow": "Sledovat",
"Following config": "Nastavení sledování",
- "Which way do you want to follow": "Zvolte způsob sledování",
+ "select_way_to_follow_@": "Zvolte způsob sledování @%{alias}",
"Followed by": "tohoto uživatele sleduje",
"followed_by": "Uživatelé, které sleduje %{username}",
"Followers": "Sledující",
@@ -3822,6 +3847,7 @@ if(preferredLanguage == "cs"){
"new_group_messages": "%{smart_count} new group message |||| %{smart_count} new group messages",
"nobody": "nikdo", // used to promote a post without attaching the user
"Not available": "Tuto přezdívku již někdo používá", // username is not available
+ "warn_following_not_any": "Not following any twisters!\nSearch and follow someone.",
"notify_desktop_error": "Twisteru se nepodařilo zobrazit upozornění na ploše: došlo k neznámé chybě.",
"notify_desktop_perm_denied": "Twisteru se nepodařilo zobrazit upozornění na ploše: přístup byl odepřen.\n\nPokud chcete používat upozornění na ploše, povolte je pro %{this_domain} v nastavení vašeho prohlížeče.",
"notify_desktop_test": "Twister to umí pořádně roztočit.\nKaždý je tu vítán.",
@@ -3856,7 +3882,7 @@ if(preferredLanguage == "cs"){
"seconds": "%{smart_count} vteřinou |||| %{smart_count} vteřinami |||| %{smart_count} vteřinami",
"send": "odeslat",
"Send post with username": "Příspěvek vložit pod přezdívkou ",
- "Sent Direct Message": "Poslat přímou zprávu",
+ "send_DM": "Poslat přímou zprávu",
"Sent Post to @": "Poslat veřejný příspěvek pro @",
"Setup account": "Upravit profil",
"The File APIs are not fully supported in this browser.": "Upozornění: váš webový prohlížeč nepodporuje File API.",
diff --git a/js/mobile_abstract.js b/js/mobile_abstract.js
index 4099741..5e75d10 100644
--- a/js/mobile_abstract.js
+++ b/js/mobile_abstract.js
@@ -63,15 +63,26 @@ var MAL = function()
}
}
+ this.warnFollowingNotAny = function(cbFunc, cbReq) {
+ if ($.hasOwnProperty('mobile'))
+ alert(polyglot.t('warn_following_not_any'));
+ else
+ alertPopup({
+ //txtTitle: polyglot.t(''), add some title (not 'error', please) or KISS
+ txtMessage: polyglot.t('warn_following_not_any'),
+ cbConfirm: cbFunc,
+ cbConfirmReq: cbReq,
+ cbClose: 'cbConfirm'
+ });
+ };
- this.followingListLoaded = function() {
- if( $.hasOwnProperty("mobile") ) {
+ this.followingListLoaded = function(followingList) {
+ if ($.hasOwnProperty('mobile')) {
$.mobile.hidePageLoadingMsg();
- $(".following-list").listview('refresh');
- } else {
- $(".postboard-loading").hide();
- }
- }
+ followingList.listview('refresh');
+ } else
+ followingList.find('.loading-roller').hide();
+ };
this.searchUserListLoaded = function() {
if( $.hasOwnProperty("mobile") ) {
diff --git a/js/tmobile.js b/js/tmobile.js
index 1fb1b45..c296a5c 100644
--- a/js/tmobile.js
+++ b/js/tmobile.js
@@ -161,7 +161,10 @@ var router=new $.mobile.Router(
}
$.mobile.showPageLoadingMsg();
$("#following a.ui-btn").removeClass("ui-btn-active");
- showFollowingUsers();
+ var followingList = twister.tmpl.followingList.clone(true).appendTo($("#following .content"))
+ .closest('.following-list').listview();
+ showFollowingUsers(followingList);
+ followingList.find('[data-role="button"]').button();
});
},
post: function(type,match,ui) {
diff --git a/js/twister_directmsg.js b/js/twister_directmsg.js
index 97431e3..16aaf47 100644
--- a/js/twister_directmsg.js
+++ b/js/twister_directmsg.js
@@ -324,7 +324,7 @@ function openGroupMessagesNewGroupModal() {
groupMsgCreateGroup(elemForm.find('.description').val(), peersToInvite);
- closeModal();
+ closeModal(event);
});
}
@@ -375,7 +375,7 @@ function openGroupMessagesJoinGroupModal() {
for (var i = 0; i < groups.length; i++)
groupMsgInviteToGroup(groups[i].getAttribute('data-screen-name'), [defaultScreenName]);
- closeModal();
+ closeModal(event);
});
modal.content.find('.secret-key-import, .username-import').on('input', importSecretKeypress);
@@ -388,8 +388,8 @@ function openGroupMessagesJoinGroupModal() {
twisterRpc('importprivkey', [secretKey, groupAlias],
function(req, ret) {
groupMsgInviteToGroup(req.groupAlias, [defaultScreenName]);
- closeModal();
- }, {groupAlias: groupAlias},
+ closeModal(req.elem);
+ }, {groupAlias: groupAlias, elem: elemModule},
function(req, ret) {
alert(polyglot.t('Error in \'importprivkey\'', {rpc: ret.message}));
}
@@ -544,16 +544,16 @@ function initInterfaceDirectMsg() {
});
$('.group-messages-control .leave').on('click', function (event) {
- var elemEvent = $(event.target);
- var groupAlias = elemEvent.closest('[data-screen-name]').attr('data-screen-name');
- confirmPopup(event, {
- titleTxt: polyglot.t('сonfirm_group_leaving_header'),
- messageTxt: polyglot.t('сonfirm_group_leaving_body', {alias: groupAlias}),
- confirmFunc: function (groupAlias) {
+ var groupAlias = $(event.target).closest('[data-screen-name]').attr('data-screen-name');
+ event.data = {
+ txtTitle: polyglot.t('сonfirm_group_leaving_header'),
+ txtMessage: polyglot.t('сonfirm_group_leaving_body', {alias: groupAlias}),
+ cbConfirm: function (groupAlias) {
groupMsgLeaveGroup(groupAlias, function () {history.back();});
},
- confirmFuncArgs: groupAlias
- });
+ cbConfirmReq: groupAlias
+ };
+ confirmPopup(event);
});
$('.group-messages-control .new').on('click', function () {
diff --git a/js/twister_following.js b/js/twister_following.js
index a9747c0..744d974 100644
--- a/js/twister_following.js
+++ b/js/twister_following.js
@@ -373,7 +373,6 @@ function follow(user, publicFollow, cbFunc, cbArg) {
if( followingUsers.indexOf(user) < 0 ) {
followingUsers.push(user);
twisterFollowingO.update(user);
- $(window).trigger("eventFollow", user)
}
if( publicFollow == undefined || publicFollow )
_isFollowPublic[user] = true;
@@ -389,8 +388,6 @@ function unfollow(user, cbFunc, cbArg) {
if (i >= 0) {
followingUsers.splice(i, 1);
twisterFollowingO.update(user);
- // FIXME also need to check list of pending posts to remove from there
- $(window).trigger('eventUnfollow', user);
}
delete _isFollowPublic[user];
saveFollowing();
@@ -512,46 +509,6 @@ function getWhoFollows(username, item) {
}
}
-// adds following users to the interface (following.html)
-function showFollowingUsers(){
- var $notFollowing = $(".not-following-any");
- if( followingEmptyOrMyself() ) {
- $notFollowing.show();
- } else {
- $notFollowing.hide();
- }
-
- var $followingList = $(".following-list");
- var $template = $("#following-user-template").detach();
-
- $followingList.empty();
- $followingList.append($template);
-
- for( var i = 0; i < followingUsers.length; i++ ) {
- var resItem = $template.clone(true);
- resItem.removeAttr('id');
- resItem.show();
- resItem.find(".mini-profile-info").attr("data-screen-name", followingUsers[i]);
- resItem.find(".following-screen-name").text(followingUsers[i]);
- resItem.find("a.open-profile-modal").attr("href",$.MAL.userUrl(followingUsers[i]));
- resItem.find("a.direct-messages-with-user").attr("href", $.MAL.dmchatUrl(followingUsers[i]));
- if (isPublicFollowing(followingUsers[i])) {
- resItem.find(".public-following").text(polyglot.t("Public"));
- } else {
- resItem.find(".public-following").text(polyglot.t("Private")).addClass( "private" );
- }
- getAvatar(followingUsers[i],resItem.find(".mini-profile-photo"));
- getFullname(followingUsers[i],resItem.find(".mini-profile-name"));
- if( followingUsers[i] == defaultScreenName ) {
- resItem.find("button").hide();
- }
-
- resItem.prependTo($followingList);
- toggleFollowButton(followingUsers[i], true)
- }
- $.MAL.followingListLoaded();
-}
-
function processWhoToFollowSuggestion(suggestion, followedBy) {
if (suggestion) {
var module = $('.module.who-to-follow');
@@ -664,37 +621,16 @@ function processDropdownUserResults(event, results) {
getFullname(results[i], item.find('.mini-profile-name'));
item.appendTo(container);
- if (followingUsers.indexOf(results[i]) !== -1)
- toggleFollowButton(results[i], true);
+ toggleFollowButton({
+ button: item.find('.follow'),
+ peerAlias: results[i],
+ toggleUnfollow: followingUsers.indexOf(results[i]) !== -1 ? true : false
+ });
}
$.MAL.searchUserListLoaded();
}
-function userClickFollow(e) {
- e.stopPropagation();
- e.preventDefault();
-
- if (!defaultScreenName) {
- alert(polyglot.t('You have to log in to follow users.'));
- return;
- }
-
- var username = $(e.target).closest('[data-screen-name]').attr('data-screen-name');
- var content = $('#following-config-modal-template').children().clone(true);
-
- content.closest('.following-config-modal-content').attr('data-screen-name', username);
- content.find('.following-config-method-message').text(polyglot.t('Which way do you want to follow'));
- content.find('.following-screen-name b').text(username);
-
- openModal({
- classBase: '.prompt-wrapper',
- classAdd: 'following-config-modal',
- content: content,
- title: polyglot.t('Following config')
- });
-}
-
function initUserSearch() {
var elem = $('.userMenu-search-field')
.on('click input',
@@ -703,16 +639,6 @@ function initUserSearch() {
.on('keyup', userSearchEnter)
;
$('.userMenu-search').clickoutside(closeSearchDialog.bind(elem));
-
- // following stuff should be moved to special function
- $('button.follow').on('click', userClickFollow);
- $('.following-config-method-buttons .public-following')
- .on('click', function(e) {
- setFollowingMethod(e);
- closePrompt();
- window.setTimeout(loadModalFromHash, 500); // delay reload so dhtput may do it's job
- })
- ;
}
function userSearchEnter(event) {
@@ -723,37 +649,6 @@ function userSearchEnter(event) {
}
}
-function followingListPublicCheckbox(e) {
- e.stopPropagation();
-
- var $this = $(this);
- var username = $this.closest(".mini-profile-info").attr("data-screen-name");
- var publicFollow = false;
- $this.toggleClass( "private" );
- if( $this.hasClass( "private" ) ) {
- $this.text( polyglot.t("Private") );
- } else {
- $this.text( polyglot.t("Public") );
- publicFollow = true;
- }
-
- //console.log("set following method of @" +username +" for "+publicFollow);
- follow(username, publicFollow);
-}
-
-function setFollowingMethod(event) {
- var button = $(event.target);
- var username = button.closest('.following-config-modal-content').attr('data-screen-name');
-
- follow(username,
- (button.hasClass('private')) ? false : true, // is folowing public
- toggleFollowButton, username, true // last two are args for toggleFollowButton()
- );
-
- event.stopPropagation();
-}
-
-
function requestSwarmProgress() {
twisterRpc("getlasthave", [defaultScreenName],
function(args, ret) {processSwarmProgressPartial(ret);}, null,
@@ -794,83 +689,3 @@ function followingChangedUser() {
_followSuggestions = [];
_lastLoadFromDhtTime = 0;
}
-
-function initInterfaceFollowing() {
- initInterfaceCommon();
- initUserSearch();
- initInterfaceDirectMsg();
-
- $(".mini-profile-info .public-following").bind( "click", followingListPublicCheckbox );
-
- $(".mentions-from-user").bind( "click", openMentionsModal );
-
- initUser( function() {
- if( !defaultScreenName ) {
- alert(polyglot.t("username_undefined"));
- $.MAL.goLogin();
- return;
- }
- checkNetworkStatusAndAskRedirect();
-
- $(".postboard-loading").fadeIn();
- loadFollowing( function(args) {
- twisterFollowingO = TwisterFollowing(defaultScreenName);
-
- showFollowingUsers();
- requestSwarmProgress();
- });
- initMentionsCount();
- initDMsCount();
- });
-
- $(window)
- .on('eventFollow', function(e, user) {
- $('.mini-profile .following-count').text(followingUsers.length - 1);
- showFollowingUsers();
- })
- .on('eventUnfollow', function(e, user) {
- $('.mini-profile .following-count').text(followingUsers.length - 1);
- showFollowingUsers();
- });
-}
-
-
-var InterfaceFunctions = function () {
- this.init = function () {
- initUser(initFollowing_);
- };
-
- function initFollowing_(cbFunc, cbArg) {
- var $miniProfile = $(".left .mini-profile");
- if(!defaultScreenName)
- {
-
- }
- else
- {
- $miniProfile.find("a.mini-profile-name").attr("href",$.MAL.userUrl(defaultScreenName));
- $miniProfile.find("a.open-profile-modal").attr("href",$.MAL.userUrl(defaultScreenName));
- $miniProfile.find(".mini-profile-name").text(defaultScreenName);
- getFullname( defaultScreenName, $miniProfile.find(".mini-profile-name") );
- getAvatar( defaultScreenName, $miniProfile.find(".mini-profile-photo").find("img") );
- getPostsCount( defaultScreenName, $miniProfile.find(".posts-count") );
- getFollowers( defaultScreenName, $miniProfile.find(".followers-count") );
-
- loadFollowing( function(args) {
- $(".left .following-count").text(followingUsers.length-1);
- initMentionsCount();
- initDMsCount();
- }, {cbFunc:cbFunc, cbArg:cbArg});
-
- }
-
- }
-};
-
-//***********************************************
-//******************* INIT **************
-//***********************************************
-if (!/\/home.html$/i.test(document.location)) { // FIXME we're doing it wrong, interfaceFunctions declaration should be inside interface common
- var interfaceFunctions = new InterfaceFunctions;
- $(document).ready(interfaceFunctions.init);
-}
diff --git a/js/twister_formatpost.js b/js/twister_formatpost.js
index a103b96..556a520 100644
--- a/js/twister_formatpost.js
+++ b/js/twister_formatpost.js
@@ -3,18 +3,13 @@
//
// Format JSON posts and DMs to HTML.
-var _templatePostRtReference;
-var _templatePostRtBy;
var _htmlFormatMsgLinkTemplateExternal;
var _htmlFormatMsgLinkTemplateUser;
var _htmlFormatMsgLinkTemplateHashtag;
$(document).ready(function() {
- // we're setting it here for perfomance improvement purpose // to not search and prepare it for for every post every time
- _templatePostRtReference = $('#post-rt-reference-template').children().clone(true);
- _templatePostRtReference.find('.post-text')
- .on('click', {feeder: '.post-rt-reference'}, openConversationClick);
- _templatePostRtBy = $('#post-rt-by-template').children().clone(true);
+ // we're setting it here for perfomance improvement purpose
+ // to not search and prepare it for for every post every time
_htmlFormatMsgLinkTemplateExternal = $('#external-page-link-template')
if (_htmlFormatMsgLinkTemplateExternal.length) {
_htmlFormatMsgLinkTemplateExternal = _htmlFormatMsgLinkTemplateExternal[0].cloneNode();
@@ -156,7 +151,7 @@ function postToElem(post, kind, promoted) {
if (userpost.msg) {
setPostReference(postContext, rt, userpost.sig_rt);
} else {
- postContext.append(_templatePostRtBy.clone(true)).addClass('post-rt-by')
+ postContext.append(twister.tmpl.postRtBy.clone(true)).addClass('post-rt-by')
.find('.post-rt-sign .prep').text(polyglot.t('post_rt_sign_prep'))
.siblings('.open-profile-modal')
.attr('href', $.MAL.userUrl(retweeted_by)).text('@' + retweeted_by)
@@ -232,7 +227,7 @@ function setPostCommon(elem, username, time) {
}
function setPostReference(elem, rt, sig_rt) {
- elem.append(_templatePostRtReference.clone(true))
+ elem.append(twister.tmpl.postRtReference.clone(true))
.find('.post-rt-reference')
.attr('data-screen-name', rt.n)
.attr('data-id', rt.k)
diff --git a/js/twister_network.js b/js/twister_network.js
index 9380588..3389458 100644
--- a/js/twister_network.js
+++ b/js/twister_network.js
@@ -304,7 +304,7 @@ function interfaceNetworkHandlers() {
function (e) {e.stopPropagation(); $(this).addClass('open'); usePostSpliting = false;});
$('.post-submit.update-spam-msg').off('click').on('click', setSpamMsg);
$('.terminate-daemon').on('click',
- {messageTxt: polyglot.t('confirm_terminate_daemon'), confirmFunc: exitDaemon}, confirmPopup);
+ {txtMessage: polyglot.t('confirm_terminate_daemon'), cbConfirm: exitDaemon}, confirmPopup);
}
diff --git a/js/twister_user.js b/js/twister_user.js
index c154de9..c0b5b73 100644
--- a/js/twister_user.js
+++ b/js/twister_user.js
@@ -273,20 +273,18 @@ function saveProfile(e) {
function completeProfileSaving(req, isAvatarDataSaved) {
if (req.isProfileDataSaved && isAvatarDataSaved) {
clearAvatarAndProfileCache(defaultScreenName);
- var titleTxt = '';
- var messageTxt = polyglot.t('profile_saved');
+ var txtTitle = '';
+ var txtMessage = polyglot.t('profile_saved');
} else {
- var titleTxt = polyglot.t('error', {error: ''});
- var messageTxt = polyglot.t('profile_not_saved');
+ var txtTitle = polyglot.t('error', {error: ''});
+ var txtMessage = polyglot.t('profile_not_saved');
}
- confirmPopup(null, {
- titleTxt: titleTxt,
- messageTxt: messageTxt,
- confirmTxt: polyglot.t('btn_ok'),
- confirmFunc: $.MAL.enableButton,
- confirmFuncArgs: $('.submit-changes'),
- closeFunc: 'confirmFunc',
- removeCancel: true
+ alertPopup({
+ txtTitle: txtTitle,
+ txtMessage: messageTxt,
+ cbConfirm: $.MAL.enableButton,
+ cbConfirmReq: $('.submit-changes'),
+ cbClose: 'cbConfirm'
});
}
diff --git a/network.html b/network.html
index b17a461..0873a4e 100644
--- a/network.html
+++ b/network.html
@@ -44,7 +44,6 @@