Browse Source

Merge pull request #348 from miguelfreitas/blaster

sync with blaster
master
miguelfreitas 9 years ago
parent
commit
a03729b083
  1. 12
      css/profile.css
  2. 212
      css/style.css
  3. 637
      following.html
  4. 120
      home.html
  5. 1134
      js/interface_common.js
  6. 47
      js/interface_home.js
  7. 240
      js/interface_localization.js
  8. 56
      js/mobile_abstract.js
  9. 4
      js/options.js
  10. 20
      js/tmobile.js
  11. 56
      js/twister_actions.js
  12. 77
      js/twister_directmsg.js
  13. 238
      js/twister_following.js
  14. 110
      js/twister_formatpost.js
  15. 695
      js/twister_io.js
  16. 2
      js/twister_network.js
  17. 8
      js/twister_timeline.js
  18. 41
      js/twister_user.js
  19. 15
      network.html
  20. 6
      options.html
  21. 7
      profile-edit.html
  22. 18
      theme_calm/css/profile.css
  23. 227
      theme_calm/css/style.css
  24. 519
      theme_nin/css/style.css
  25. 4
      theme_nin/js/theme_option.js
  26. 239
      theme_nin/sass/_following.sass
  27. 126
      tmobile.html

12
css/profile.css

@ -101,8 +101,8 @@ @@ -101,8 +101,8 @@
{
margin-bottom: 8px;
}
.forEdition .profile-card-main input
{
.forEdition .profile-card-main input, .forEdition .profile-card-main textarea {
display: block;
margin: 0 auto;
background: rgba( 0, 0, 0, .1 );
@ -113,16 +113,20 @@ @@ -113,16 +113,20 @@
text-align: center;
transition: all .2s linear;
}
.forEdition .profile-card-main input:hover,
.forEdition .profile-card-main input:focus,
.forEdition .profile-card-main textarea:hover, .forEdition .profile-card-main textarea:focus,
.forEdition .profile-card-photo:hover
{
background: rgba( 0, 0, 0, .3 );
}
.input-description
{
.input-description {
width: 90%;
max-width: 90%;
}
.input-name
{
font-size: 20px;

212
css/style.css

@ -46,14 +46,17 @@ ol, ul, li @@ -46,14 +46,17 @@ ol, ul, li
{
list-style: none;
}
a
{
a {
color: #E34F42;
text-decoration: none;
}
a:hover
{
a:hover {
text-decoration: underline;
cursor: pointer;
}
blockquote, q
{
quotes: none;
@ -123,7 +126,7 @@ button:disabled:hover, button.disabled:hover { @@ -123,7 +126,7 @@ button:disabled:hover, button.disabled:hover {
color: rgba(255, 255, 255, .8);
}
button.follow, button.unfollow, .following-list button.private {
button.follow, button.unfollow, .following-own-modal .following-list button.private {
color: rgba( 0, 0, 0, .4 );
background: none;
border: solid 1px rgba( 0, 0, 0, .2 );
@ -131,19 +134,19 @@ button.follow, button.unfollow, .following-list button.private { @@ -131,19 +134,19 @@ button.follow, button.unfollow, .following-list button.private {
font-size: 12px;
}
.following-list .public-following {
.following-own-modal .following-list .public-following {
padding: 4px 16px;
font-size: 12px;
}
.following-list .public-following:hover {
.following-own-modal .following-list .public-following:hover {
color: rgba( 0, 0, 0, .4 );
background: none;
border: solid 1px rgba( 0, 0, 0, .2 );
padding: 3px 15px;
}
button.follow:hover, button.unfollow:hover, .following-list button.private:hover {
button.follow:hover, button.unfollow:hover, .following-own-modal .following-list button.private:hover {
color: #fff;
background: #45474d;
}
@ -545,10 +548,7 @@ button.follow:hover, button.unfollow:hover, .following-list button.private:hover @@ -545,10 +548,7 @@ button.follow:hover, button.unfollow:hover, .following-list button.private:hover
position: relative;
z-index: 2;
}
.following-list .mini-profile-name
{
padding: 5px 5px 5px 5px;
}
.profile-data
{
@ -584,58 +584,51 @@ button.follow:hover, button.unfollow:hover, .following-list button.private:hover @@ -584,58 +584,51 @@ button.follow:hover, button.unfollow:hover, .following-list button.private:hover
display: block;
font-size: 16px;
}
.mini-profile-actions
{
position: relative;
width: auto;
display: inline-block;
.mini-profile-actions {
position: absolute;
top: 0;
right: 8px;
}
.mini-profile-actions span
{
.mini-profile-actions span {
color: #e34f42;
cursor: pointer;
font-size: 12px;
display: inline-block;
transition: all .2s linear;
position: relative;
z-index: 10;
}
.mini-profile-actions ul
{
.mini-profile-actions ul {
height: 0;
overflow: hidden;
position: absolute;
z-index: 20;
right: 0;
transition: height .2s linear;
background: #fff;
z-index: 3;
}
.mini-profile-actions:hover span
{
}
.mini-profile-actions:hover span:after
{
}
.mini-profile-actions:hover ul
{
height: 118px;
box-shadow: 0 2px 5px #65686f;
.mini-profile-actions:hover ul {
/*height: ;*/
border: solid 1px rgba(69, 71, 77, .1);
border-right: solid 4px rgba(227, 79, 66, .82);
box-shadow: 8px 10px 10px 0px rgba(0, 0, 0, .2);
}
.mini-profile-actions ul li
{
.mini-profile-actions ul > li {
white-space: nowrap;
color: rgba( 0, 0, 0, .7 );
font-size: 13px;
color: rgba(0, 0, 0, .7);
font-size: 12px;
cursor: pointer;
padding: 5px;
margin: 2px;
padding: 4px 16px 4px 8px;
}
.mini-profile-actions ul li + li
{
margin: 0 2px;
}
.mini-profile-actions:hover ul li:hover
{
background: rgba( 0, 0, 0, .7 );
color: #fff;
.mini-profile-actions ul > li:hover {
background-color: #FEFEDF;
}
.mini-profile-info a:hover
{
text-decoration: none;
@ -682,7 +675,6 @@ button.follow:hover, button.unfollow:hover, .following-list button.private:hover @@ -682,7 +675,6 @@ button.follow:hover, button.unfollow:hover, .following-list button.private:hover
border-radius: 3px;
border: solid 1px rgba(0, 0, 0, .3 );
margin-left: 55px;
margin-bottom: 10px;
padding: 4px;
font-size: 13px;
}
@ -761,6 +753,16 @@ textarea.splited-post { @@ -761,6 +753,16 @@ textarea.splited-post {
height: 35px;
transition: all .6s linear;
}
.post-area-new .post-textarea-edit-bar {
font-size: 11px;
margin: 2px 0;
}
.post-area-new .post-textarea-edit-bar > * {
margin: 2px 4px;
}
.post-area-remaining
{
font-size: 13px;
@ -778,6 +780,56 @@ textarea.splited-post { @@ -778,6 +780,56 @@ textarea.splited-post {
.post .show-more:before {
content: '💭';
}
/* FIXME need to rework and replace all .twister-user to get same vis */
.twister-peer {
margin: 0;
min-height: 72px;
padding: 4px;
border-bottom: solid 1px rgba(69, 71, 77, .1);
border-top: solid 1px rgba(69, 71, 77, .1);
}
.twister-peer + .twister-peer {
border-top: none;
}
.twister-peer .avatar {
float: left;
width: 48px;
height: 48px;
overflow: hidden;
margin: 4px;
}
.twister-peer .avatar img {
width: 48px;
height: auto;
border-radius: 16%;
}
.twister-peer .name, .twister-peer .alias {
color: #E34F42;
display: inline-block;
}
.twister-peer .name {
font-weight: 600;
}
.twister-peer .avatar:hover, .twister-peer .name:hover, .twister-peer .alias:hover {
cursor: pointer;
}
.twister-peer .bio {
text-align: center;
padding: 4px;
}
.twister-peer .bio a {
color: #E34F42;
}
/***********************************
********************* WHO TO FOLLOW
***********************************/
@ -2199,68 +2251,60 @@ ol.toptrends-list { @@ -2199,68 +2251,60 @@ ol.toptrends-list {
*********** FOLLOWING PAGE ***********
**************************************/
.following .header-bold {
display: block;
width: 100%;
margin: 0px auto 12px auto;
.following-own-modal.modal-wrapper {
width: 666px;
margin-left: -333px;
}
.following-list
{
overflow-y: auto;
.following-own-modal .following-list {
text-align: center;
}
.following ol.following-list > li{
width: 425px;
height: 160px;
margin: 5px;
padding: 8px;
float: left;
border: solid 1px rgba( 69, 71, 77, .1 );
.following-own-modal .following-list > li {
display: inline-block;
text-align: initial;
width: 320px;
height: 120px;
margin: 2px;
padding: 2px;
border: solid 1px rgba(69, 71, 77, .1);
background: #fff;
}
.w1200 .following ol.following-list > li{
width: 385px;
.following-own-modal .following-list > li:hover {
border: solid 1px rgba(227, 79, 66, .5);
}
.following ol.following-list > li:hover{
border: solid 1px rgba( 227, 79, 66, .5 );
.following-own-modal .following-list .mini-profile-name {
padding: 4px;
}
.following-list .mini-screen-name {
.following-own-modal .following-list .mini-screen-name {
position: absolute;
top: 32px;
}
.following-list .following-config
{
.following-own-modal .following-list .following-config {
width: 100%;
position: absolute;
top: 64px;
top: 62px;
text-align: center;
}
.following-list .following-config button
{
.following-own-modal .following-list .following-config button {
display: inline-block;
}
.following-list .mini-profile-actions
{
position: absolute;
top: 0;
right: 8px;
z-index: 10;
.following-own-modal .following-list .mini-profile-actions:hover ul {
height: 50px;
}
.following-list .swarm-status
{
.following-own-modal .following-list .swarm-status {
font: 12px "Open Sans", sans-serif;
display: block;
position: absolute;
top: 120px;
right: 8px;
top: 94px;
right: 32px;
}
/*************************************
@ -2292,6 +2336,10 @@ ul.dropdown-menu .active, ul.dropdown-menu .active a { @@ -2292,6 +2336,10 @@ ul.dropdown-menu .active, ul.dropdown-menu .active a {
cursor: pointer;
}
ul.dropdown-menu li a {
color: black;
}
.post-rt-reference {
background-color: #FAFAFA;

637
following.html

@ -1,637 +0,0 @@ @@ -1,637 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Following</title>
<link id="stylecss" rel="stylesheet" href="css/style.css" type="text/css"/>
<link id="profilecss" rel="stylesheet" href="css/profile.css" type="text/css"/>
<script src="js/jquery.min.js"></script>
<script src="js/jQueryPlugins.js"></script>
<script src="js/jquery.json-2.4.js"></script>
<script src="js/jquery.jsonrpcclient.js"></script>
<script src="js/jquery.storageapi.js"></script>
<script src="js/options.js"></script>
<script src="js/franc.js"></script>
<script src="js/notify.js"></script>
<script src="js/mobile_abstract.js"></script>
<script src="js/twister_io.js"></script>
<script src="js/polyglot.min.js"></script>
<script src="js/interface_localization.js"></script>
<script src="js/twister_network.js"></script>
<script src="js/twister_user.js"></script>
<script src="js/twister_formatpost.js"></script>
<script src="js/twister_newmsgs.js"></script>
<script src="js/twister_following.js"></script>
<script src="js/twister_directmsg.js"></script>
<script src="js/twister_actions.js"></script>
<script src="js/interface_common.js"></script>
<script src="js/jquery.textcomplete.min.js"></script>
<link rel="shortcut icon" type="image/png" href="img/twister_mini.png" />
</head>
<body>
<!-- MENU SUPERIOR INIT -->
<nav class="userMenu">
<ul>
<li class="userMenu-home"><a href="home.html"><span class="selectable_theme theme_original label">Home</span></a></li>
<li class="userMenu-network selectable_theme theme_original theme_nin"><a class="label" href="network.html">Network</a></li>
<li class="userMenu-profile selectable_theme theme_original theme_nin"><a class="label" href="profile-edit.html">Profile</a></li>
<li class="userMenu-config">
<a class="userMenu-config-dropdown" href="#">
<div class="config-menu dialog-modal">
<div class="mini-profile-info selectable_theme theme_original">
<div class="mini-profile-photo"><img src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
<a href="#" class="mini-profile-name">Fulano da Silva</a>
<span class="mini-profile-view">View</span>
</div>
<a class="dropdown-menu-item" href="options.html">Options</a>
<a class="dropdown-menu-item" href="profile-edit.html">Setup account</a>
<a class="dropdown-menu-item" href="following.html">Following users</a>
<a class="dropdown-menu-item" href="network.html">Network config</a>
<a class="dropdown-menu-item" href="login.html">Change user</a>
<a class="dropdown-menu-item direct-messages selectable_theme theme_original theme_calm" href="#">Direct Messages</a>
<a class="dropdown-menu-item groupmessages selectable_theme theme_original theme_calm" href="#">Group Messages</a>
</div>
</a>
</li>
<li class="userMenu-connections">
<a href="#">
<span class="messages-qtd" style="display:none;">0</span>
</a>
</li>
<li class="userMenu-messages">
<a href="#">
<span class="messages-qtd" style="display:none;">0</span>
</a>
</li>
<li class="userMenu-groupmessages">
<a href="#">
<span class="messages-qtd" style="display:none;">0</span>
</a>
</li>
<li class="userMenu-dhtindicator selectable_theme theme_calm"><a href="network.html"></a></li>
<!-- BUSCA -->
<li class="userMenu-search">
<input type="text" class="userMenu-search-field" placeholder="search"/>
<div class="search-results dialog-modal">
<ul class="userMenu-search-sugestions" style="display: none;">
<li><a href="#">Fulano</a></li>
<li><a href="#">Outro Fulano</a></li>
<li><a href="#">Mais outro</a></li>
</ul>
<ul class="userMenu-search-profiles"></ul>
</div>
</li>
</ul>
</nav>
<!-- MENU SUPERIOR END -->
<div class="wrapper">
<!-- LADO ESQUERDO DE MÓDULOS INIT -->
<div class="dashboard left">
<!-- THEME NIN added sub-menu (mentions, messages and edit profile) -->
<ul class="mini-profile-indicators selectable_theme theme_nin">
<li class="userMenu-connections">
<a href="#" title="Mentions"><span class="messages-qtd" style="display:none;">0</span><span>Mentions</span></a>
</li>
<li class="userMenu-groupmessages">
<a href="#" title="Group Messages"><span class="messages-qtd" style="display:none;">0</span><span>Group Messages</span></a>
</li>
<li class="userMenu-messages">
<a href="#" title="Direct Messages"><span class="messages-qtd" style="display:none;">0</span><span>Messages</span></a>
</li>
</ul>
<!-- PROFILE MODULE INIT -->
<div class="module mini-profile selectable_theme theme_nin">
<div class="mini-profile-info">
<div class="mini-profile-photo"><img src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
<a href="#" class="mini-profile-name open-profile-modal"></a>
<span class="mini-profile-view">View</span>
</div>
<ul class="module profile-data">
<li><a href="#" class="open-profile-modal"><span class="posts-count">&nbsp;</span><span class="label">Posts</span></a></li>
<li class="current"><a href="following.html" class="open-following-page"><span class="following-count">&nbsp;</span><span class="label">Following</span></a></li>
<li><a href="#" class="open-followers"><span class="followers-count">&nbsp;</span><span class="label">Followers</span> *</a></li>
</ul>
</div>
<!-- PROFILE MODULE INIT -->
</div>
<!-- LADO ESQUERDO DE MÓDULOS INIT -->
<div class="following">
<h2 class="header-bold"> Following </h2>
<div class="postboard-loading" style="display: none;">
<div></div>
</div>
<ol class="following-list">
<li id="following-user-template" style="display: none;">
<div class="mini-profile-info" data-screen-name="">
<a href="#" class="open-profile-modal">
<img class="mini-profile-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<span class="mini-profile-name">Fulano da Silva</span>
<span class="mini-screen-name">@
<b class="following-screen-name"></b>
</span>
</a>
<div>
<div class="mini-profile-actions">
<span>Actions ▼</span>
<ul>
<li class="direct-messages-with-user">Sent Direct Message</li>
<li>Sent Post to @
<b class="following-screen-name"></b>
</li>
<li class="mentions-from-user">Display mentions to @
<b class="following-screen-name"></b>
</li>
<li>Display retransmissions</li>
</ul>
</div>
<div class="following-config">
<button class="follow">Follow</button>
<button class="public-following">Public</button>
</div>
</div>
<div>
<span class="swarm-status" style="display: none;"></span>
</div>
</div>
</li>
</ol>
<div class="not-following-any" style="display:none;">
<div> Not following any users! </div>
<div> Search some users in the right-upper search box and follow them. </div>
</div>
</div>
<!-- LADO ESQUERDO DE MÓDULOS END -->
</div>
<ul id="modals-minimized"></ul>
<!-- TEMPLATES INIT -->
<div id="templates" style="display:none;">
<div id="search-profile-template">
<li>
<div class="mini-profile-info">
<a class="open-profile-modal">
<img class="mini-profile-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo" />
<span class="mini-screen-name">@<b></b></span>
<span class="mini-profile-name"></span>
</a>
<button class="follow">Follow</button>
</div>
</li>
</div>
<!-- TEMPLATE DE WHO-TO-FOLLOW SUGGESTION -->
<li id="follow-suggestion-template" class="twister-user">
<div class="">
<a href="#" class="twister-user-name open-profile-modal">
<img class="twister-user-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
</a>
</div>
<div class="twister-user-info" data-screen-name="">
<a href="#" class="twister-user-name open-profile-modal">
<span class="twister-user-tag"></span>
</a>
<div class="followers">
<span class="label">Followed by</span>
<span class="followed-by"></span>
</div>
<a class="twister-user-remove">&times;</a>
<button class="follow">Follow</button>
</div>
</li>
<!-- TEMPLATE DA OL INVÓLUCRO DAS LIST ELEMENTS DO POST EXPANDIDO INIT -->
<ol class="expanded-post">
</ol>
<!-- TEMPLATE DA OL INVÓLUCRO DAS LIST ELEMENTS DO POST EXPANDIDO END -->
<!-- TEMPLATE DOS 3 TIPOS DE LI DO POST EXPANDIDO INIT -->
<li class="ancestor module post">
</li>
<div id="post-preview-template">
<div id="post-preview" class="post-text">
</div>
</div>
<li id="post-template" class="module post" data-time="">
<div class="post-data" data-userpost="" data-content_to_rt="" data-content_to_sigrt=""
data-screen-name="" data-id="" data-text="" data-text-mentions="">
<div class="post-photo"><img class="avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
<div class="post-info">
<a href="#" class="post-info-name open-profile-modal"></a>
<span class="post-info-tag"></span>
<a class="post-info-time"><span class="post-info-sent"></span> <span></span></a>
</div>
<p class="post-text"></p>
<div class="post-context" style="display: none;"></div>
<span class="post-expand">Expand</span>
<!-- elementos de interação com o post que são exibidos no hover -->
<div class="post-interactions">
<span class="post-reply">Reply</span>
<span class="post-propagate">Retransmit</span>
<!--span class="post-favorite">Favorite</span-->
</div>
<div class="expanded-content" style="display: none;">
<ul class="post-stats" style="display: none;">
<li class="stat-count">
<span class="stat-count-value"></span>
<span>Retransmits</span>
</li>
<li class="avatar-row">
<!-- use "avatar-row-template" here -->
</li>
</ul>
<div class="preview-container">
</div>
<div class="post-reply-content" style="display: block;">
<form class="post-area-new">
<textarea placeholder="Reply..."></textarea>
<div class="post-area-extras">
<span class="post-area-remaining">140</span>
<button class="undo-unicode disabled" disabled="disabled">undo</button>
<button class="post-submit disabled" disabled="disabled">post</button>
</div>
</form>
</div>
<span class="show-more label">Show more in this conversation...</span>
</div> <!-- expanded-content -->
</div> <!-- post-data -->
</li> <!-- post-template -->
<div id="post-rt-reference-template">
<div class="post-rt-reference">
<div class="post-photo"><img class="avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo" /></div>
<div class="post-info">
<a href="#" class="post-info-name open-profile-modal"></a>
<span class="post-info-tag"></span>
<a class="post-info-time"><span></span></a>
</div>
<p class="post-text"></p>
</div>
</div>
<div id="post-rt-by-template">
<i class="post-rt-icon"></i>
<div class="post-rt-sign">
<span class="prep">twisted again by</span><a class="open-profile-modal"></a>
</div>
<div class="post-rt-time">
<span class="prep">at</span><span class="time"></span>
</div>
</div>
<!-- template for user links in message (open profile modal) -->
<a id="msg-user-link-template" class="open-profile-modal"></a>
<!-- template for user links in message (open profile modal) -->
<a id="external-page-link-template" rel="nofollow" target="_blank"></a>
<!-- template for user links in message (open profile modal) -->
<a id="hashtag-link-template" class="open-hashtag-modal"></a>
<!-- template para ir dentro de avatar-row -->
<a id="avatar-row-template" class="open-profile-modal" href="">
<img class="size24" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<span class="user-name-tooltip"></span>
</a>
<li class="descendant module post">
</li>
<div class="modal-wrapper">
<div class="modal-header">
<h3></h3>
<span class="minimize-modal"><b>_</b></span>
<span id="closeModal" class="modal-close">&times;</span>
<span class="modal-back">&lt;</span>
<span class="mark-all-as-read"></span>
</div>
<div class="modal-content"></div>
<div class="modal-blackout"></div>
</div>
<div class="prompt-wrapper">
<div class="modal-header">
<h3></h3>
<span class="modal-close prompt-close">&times;</span>
</div>
<div class="modal-content"></div>
</div>
<div id="confirm-popup-template">
<div class="message"></div>
<div class="modal-buttons">
<button class="confirm"></button>
<button class="cancel"></button>
</div>
</div>
<div id="reTwist-modal-template">
<div class="post-area">
<form class="post-area-new open">
<textarea placeholder="New Post..."></textarea>
<div class="post-area-extras">
<span class="post-area-remaining">140</span>
<button class="undo-unicode disabled" disabled="disabled">undo</button>
<button class="post-submit disabled" disabled="disabled">post</button>
</div>
<div class="modal-buttons">
<span class="switch-mode">Switch to Reply</span>
<button class="modal-propagate">Retransmit</button>
</div>
</form>
</div>
</div>
<div id="reply-modal-template">
<div class="post-area">
<form class="post-area-new open">
<textarea placeholder="New Post..."></textarea>
<div class="post-area-extras">
<span class="switch-mode">Switch to Retransmit</span>
<span class="post-area-remaining">140</span>
<button class="undo-unicode disabled" disabled="disabled">undo</button>
<button class="post-submit disabled" disabled="disabled">post</button>
</div>
</form>
</div>
</div>
<!-- MODAL DE DIRECT MESSAGES INIT -->
<!-- Este modal possui dois templates, o primeiro da lista de pessoas que enviaram mensagens e o segundo
com a thread de mensagens individual -->
<div class="direct-messages-template">
<ol class="direct-messages-list">
<!-- use "dm-snippet-template here -->
</ol>
</div>
<li id="dm-snippet-template" class="module post message">
<div class="post-photo"><img src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
<div class="post-info">
<a href="#" class="post-info-name open-profile-modal"></a>
<span class="post-info-tag">@</span>
<a href="#" class="post-info-time" title=""><span></span></a>
</div>
<!-- o texto do post (restrição de caracteres?) -->
<p class="post-text"></p>
<div class="messages-qtd">0</div>
</li>
<div class="messages-thread-template">
<ol class="direct-messages-thread">
<!-- use "dm-chat-template" here -->
</ol>
</div>
<!-- cada li é uma mensagem -->
<li id="dm-chat-template" class="module post message">
<div class="post-photo"><img src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
<div class="post-info">
<a class="post-info-name open-profile-modal"></a>
<a class="post-info-time"><span class="post-info-sent"></span> <span></span></a>
</div>
<p class="post-text"></p>
</li>
<div class="dm-form-template">
<form class="post-area-new open">
<textarea placeholder="New direct message..."></textarea>
<div class="post-area-extras">
<span class="post-area-remaining">140</span>
<button class="undo-unicode disabled" disabled="disabled">undo</button>
<button title="Direct messages are encrypted, only you and receiver can read them" style="margin-right:7.5%;" class="dm-submit disabled" disabled="disabled">send</button>
</div>
</form>
</div>
<!-- MODAL DE DIRECT MESSAGES INIT -->
<div id="group-messages-profile-modal-control-template">
<div class="group-messages-control b-buttons">
<button class="new">New group</button>
<button class="join">Join group</button>
</div>
</div>
<div id="group-messages-messages-modal-control-template">
<div class="group-messages-control b-buttons">
<button class="profile">Profile</button>
<button class="invite">Invite peers</button>
<button class="leave">Leave group</button>
<div class="invite-form">
<textarea placeholder="@peer1 @peer2 …"></textarea><button disabled="disabled">Invite</button>
</div>
</div>
</div>
<div id="group-profile-modal-template">
<div class="profile-card" data-screen-name="">
<div class="profile-card-main">
<div class="profile-bio">
<input class="group-description"></input>
<button class="save a-button" disabled="disabled">Save</button>
<button class="cancel a-button">Cancel</button>
</div>
</div>
<div class="profile-card-buttons group-messages-control b-buttons">
<button class="direct-messages-with-user" disabled="disabled">Messages</button>
<button class="invite" disabled="disabled">Invite peers</button>
<button class="show-secret-key" disabled="disabled">Secret Key</button>
<button class="leave" disabled="disabled">Leave group</button>
<div class="invite-form">
<textarea placeholder="@peer1 @peer2 …"></textarea><button disabled="disabled">Invite</button>
</div>
<div class="secret-key"></div>
</div>
</div>
<div class="members"></div>
</div>
<div id="group-profile-member-template">
<div class="twister-user">
<div>
<a class="twister-user-name open-profile-modal">
<img class="twister-user-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
</a>
</div>
<div class="twister-user-info" data-screen-name="">
<a class="twister-user-name open-profile-modal">
<span class="twister-user-full"></span>
<span class="twister-user-tag"></span>
</a>
<div class="bio"></div>
</div>
</div>
</div>
<div id="group-messages-new-group-template">
<div class="module">
<div>
<p class="label">Group description</p>
<textarea class="description" placeholder="Describe group"></textarea>
</div>
<div>
<p class="label">Peers to invite</p>
<textarea class="invite" placeholder="Invite somebody"></textarea>
</div>
<div>
<button class="create" disabled="disabled">Create</button>
</div>
</div>
</div>
<div id="group-messages-join-group-template">
<div class="module">
<div>
<p class="label">Select group(s)</p>
<ul class="groups-list"></ul>
</div>
<div>
<button class="join" disabled="disabled">Join</button>
</div>
</div>
<div class="module">
<div>
<p class="label">Import secret key</p>
<input class="secret-key-import" type="textbox" placeholder="52-characters secret" size="52" rows="1"></input>
</div>
<div>
<p class="label">With group alias</p>
<input class="username-import" type="textbox" placeholder="Type group alias here" size="16" rows="1"></input>
</div>
<div>
<button class="import-secret-key" disabled="disabled">Import key</button>
</div>
</div>
</div>
<div id="groups-list-item-template">
<li>
<input type="checkbox" /> <a class="twister-user-name open-profile-modal"></a> // <span class="description"></span>
</li>
</div>
<!-- MODAL DE PROFILE -->
<div id="profile-modal-template">
<!-- ÁREA DE PROFILE PHOTO INIT -->
<div class="profile-card" data-screen-name="">
<!-- Coloquei a imagem de fundo do card do usuário como background da div
abaixo inline na tag para poder ser alterada dinamicamente
style="background: url(img/imgBack.png) no-repeat center center;"-->
<div class="profile-card-main">
<img class="profile-card-photo" src="img/grayed_avatar_placeholder_24.png"/>
<h1 class="profile-name"></h1>
<h2 class="profile-screen-name">@<b></b></h2>
<div>
<span class="profile-location"></span>
<a class="profile-url" rel="nofollow" target="_blank"></a>
</div>
<div class="profile-bio"></div>
<div id="msngrswr">
<div id="toxbtnwr" class="profile-extra-contact">
<a class="profile-tox"><span class="selectable_theme theme_nin">TOX</span></a><a class="tox-ctc"></a>
</div>
<div id="bmbtnwr" class="profile-extra-contact">
<a class="profile-bitmessage"><span class="selectable_theme theme_nin">BM</span></a><a class="bitmessage-ctc"></a>
</div>
</div>
</div>
<div class="twister-user-info">
<div class="clearfix">
<ul class="module profile-data">
<li><a href="#"><span class="posts-count">&nbsp;</span><span class="label">Posts</span></a></li>
<li><a href="#" class="open-following-modal"><span class="following-count">&nbsp;</span><span class="label">Following</span></a></li>
<li><a href="#"><span class="followers-count">&nbsp;</span><span class="label">Followers</span></a></li>
</ul>
</div>
<div class="profile-card-buttons b-buttons">
<button class="follow" href="#">Follow</button>
<button class="direct-messages-with-user" href="#">Direct Messages</button>
<button class="mentions-from-user" href="#">Mentions</button>
</div>
</div>
<div class="who-follow"></div>
</div>
<!-- ÁREA DE POSTS END -->
<!-- ÁREA DE POSTS INIT -->
<div class="postboard">
<h2>
<span>Posts</span>
<!-- o botão de novas postagens deve ser ocultado quando o usuário clicá-lo via javascript -->
<button class="postboard-news" style="display:none;"></button>
</h2>
<ol id="profile-posts" class="postboard-posts">
</ol>
</div>
<!-- ÁREA DE POSTS END -->
</div>
<!-- MODAL DE PROFILE END -->
<!-- MODAL DE HASHTAGS -->
<div id="hashtag-modal-template">
<!-- ÁREA DE POSTS INIT -->
<div class="postboard">
<h2>
Posts
<!-- o botão de novas postagens deve ser ocultado quando o usuário clicá-lo via javascript -->
<button class="postboard-news" style="display:none;"></button>
</h2>
<ol id="profile-posts" class="postboard-posts">
</ol>
</div>
<!-- ÁREA DE POSTS END -->
</div>
<!-- MODAL DE HASHTAGS END -->
<!-- MODAL DE FOLLOWING -->
<div id="following-modal-template">
<!-- ÁREA DE PROFILE PHOTO INIT -->
<h2>All users publicly followed by <span class="following-screen-name">@<b></b></span></h2>
<!-- ÁREA DE PROFILE END -->
<!-- ÁREA DE FOLLOWING INIT -->
<ol class="">
<li id="following-by-user-template" style="display: none;">
<div class="mini-following-info" data-screen-name="">
<a href="#" class="open-profile-modal">
<img class="mini-profile-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<span class="mini-following-name">Fulano da Silva</span>
<span class="mini-screen-name">@
<b class="following-screen-name"></b>
</span>
</a>
</div>
</li>
</ol>
<!-- ÁREA DE FOLLOWERS END -->
</div>
<!-- MODAL DE FOLLOWING END -->
<!-- MODAL OF FOLLOWING CONFIG -->
<div id="following-config-modal-template">
<!-- ÁREA OF FOLLOWING METHOD -->
<div class="following-config-modal-content" data-screen-name="">
<h2><span class="following-config-method-message">Which way do you want to follow</span> <span class="following-screen-name">@<b></b></span>:</h2>
<div class="following-config-method-buttons">
<button class="public-following">Public</button>
<button class="public-following private">Private</button>
</div>
</div>
<!-- ÁREA OF FOLLOWING METHOD END -->
</div>
<!-- MODAL OF FOLLOWING CONFIG END -->
</div>
<!-- TEMPLATES END -->
<audio id="player"></audio>
<audio id="playerSec"></audio>
</body>
</html>

120
home.html

@ -42,17 +42,18 @@ @@ -42,17 +42,18 @@
<li class="userMenu-network selectable_theme theme_original theme_nin"><a class="label" href="network.html">Network</a></li>
<li class="userMenu-profile selectable_theme theme_original theme_nin"><a class="label" href="profile-edit.html">Profile</a></li>
<li class="userMenu-config">
<a class="userMenu-config-dropdown" href="#">
<a class="userMenu-config-dropdown">
<div class="config-menu dialog-modal">
<div class="mini-profile-info selectable_theme theme_original">
<div class="mini-profile-photo"><img src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
<a href="#" class="mini-profile-name">Fulano da Silva</a>
<span class="mini-profile-view">View</span>
</div>
<a class="dropdown-menu-item uri-shortener">URI shortener</a>
<a class="dropdown-menu-item" href="options.html">Options</a>
<a class="dropdown-menu-item" href="network.html">Network config</a>
<a class="dropdown-menu-item" href="profile-edit.html">Setup account</a>
<a class="dropdown-menu-item dropdown-menu-following" href="following.html">Following users</a>
<a class="dropdown-menu-item dropdown-menu-following" href="#following">Following users</a>
<a class="dropdown-menu-item" href="login.html">Change user</a>
<a class="dropdown-menu-item promoted-posts-only selectable_theme theme_original theme_calm" href="#">Switch to Promoted posts</a>
<a class="dropdown-menu-item direct-messages selectable_theme theme_original theme_calm" href="#">Direct Messages</a>
@ -117,8 +118,8 @@ @@ -117,8 +118,8 @@
</div>
<ul class="module profile-data">
<li><a href="#" class="open-profile-modal"><span class="posts-count">&nbsp;</span><span class="label">Posts</span></a></li>
<li><a href="following.html" class="open-following-page"><span class="following-count">&nbsp;</span><span class="label">Following</span></a></li>
<li><a href="#" class="open-followers"><span class="followers-count">&nbsp;</span><span class="label">Followers</span> *</a></li>
<li><a href="#following" class="open-following-page"><span class="following-count">&nbsp;</span><span class="label">Following</span></a></li>
<li><a class="open-followers"><span class="followers-count"></span><span class="label">Followers</span> *</a></li>
</ul>
<div class="post-area">
@ -312,6 +313,14 @@ @@ -312,6 +313,14 @@
</div>
</div>
<div id="template-post-textarea-edit-bar">
<div class="post-textarea-edit-bar"><!-- TODO add buttons to format text --></div>
</div>
<div id="template-shorten-uri">
<a class="shorten-uri">shorten URL</a>
</div>
<li id="post-template" class="module post" data-time="">
<div class="post-data" data-userpost="" data-content_to_rt="" data-content_to_sigrt=""
data-screen-name="" data-id="" data-text="" data-text-mentions="">
@ -357,7 +366,7 @@ @@ -357,7 +366,7 @@
</div> <!-- post-data -->
</li> <!-- post-template -->
<div id="post-rt-reference-template">
<div id="template-post-rt-reference">
<div class="post-rt-reference">
<div class="post-photo"><img class="avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo" /></div>
<div class="post-info">
@ -369,7 +378,7 @@ @@ -369,7 +378,7 @@
</div>
</div>
<div id="post-rt-by-template">
<div id="template-post-rt-by">
<i class="post-rt-icon"></i>
<div class="post-rt-sign">
<span class="prep">twisted again by</span><a class="open-profile-modal"></a>
@ -385,6 +394,9 @@ @@ -385,6 +394,9 @@
<a id="external-page-link-template" rel="nofollow" target="_blank"></a>
<!-- template for user links in message (open profile modal) -->
<a id="hashtag-link-template" class="open-hashtag-modal"></a>
<div id="template-link-shortened">
<a class="link-shortened" rel="nofollow" target="_blank"></a>
</div>
<!-- template para ir dentro de avatar-row -->
<a id="avatar-row-template" class="open-profile-modal" href="">
@ -457,23 +469,22 @@ @@ -457,23 +469,22 @@
<!-- MODAL DE DIRECT MESSAGES INIT -->
<!-- Este modal possui dois templates, o primeiro da lista de pessoas que enviaram mensagens e o segundo
com a thread de mensagens individual -->
<div class="direct-messages-template">
<ol class="direct-messages-list">
<!-- use "dm-snippet-template here -->
</ol>
<div id="template-direct-messages-list">
<ol class="direct-messages-list"></ol>
</div>
<li id="dm-snippet-template" class="module post message">
<div class="post-photo"><img src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
<div class="post-info">
<a href="#" class="post-info-name open-profile-modal"></a>
<span class="post-info-tag">@</span>
<a href="#" class="post-info-time" title=""><span></span></a>
</div>
<!-- o texto do post (restrição de caracteres?) -->
<p class="post-text"></p>
<div class="messages-qtd">0</div>
</li>
<div id="template-direct-messages-list-item">
<li class="module post message">
<div class="post-photo"><img src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
<div class="post-info">
<a class="post-info-name open-profile-modal"></a>
<span class="post-info-tag">@</span>
<a class="post-info-time"><span></span></a>
</div>
<p class="post-text"></p>
<div class="messages-qtd">0</div>
</li>
</div>
<div class="messages-thread-template">
<ol class="direct-messages-thread">
@ -665,6 +676,10 @@ @@ -665,6 +676,10 @@
</div>
<!-- MODAL DE PROFILE END -->
<div id="template-profile-show-more-followers">
<a class="show-more-followers"></a>
</div>
<!-- MODAL DE HASHTAGS -->
<div id="hashtag-modal-template">
<!-- ÁREA DE POSTS INIT -->
@ -684,6 +699,61 @@ @@ -684,6 +699,61 @@
</div>
<!-- MODAL DE HASHTAGS END -->
<div id="template-followers-list">
<ol class="followers-list">
<div class="loading-roller">
<div></div>
</div>
</ol>
</div>
<div id="template-followers-peer">
<li class="twister-peer">
<div class="avatar"><img src="img/grayed_avatar_placeholder_24.png" alt="avatar" /></div>
<div class="name"></div>
<div class="alias"></div>
<div class="bio"></div>
</li>
</div>
<div id="template-following-list">
<ol class="following-list">
<div class="loading-roller">
<div></div>
</div>
</ol>
</div>
<div id="template-following-peer">
<li>
<div class="mini-profile-info">
<a href="#" class="open-profile-modal">
<img class="mini-profile-photo" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<span class="mini-profile-name">Fulano da Silva</span>
<span class="mini-screen-name">@<b class="following-screen-name"></b></span>
</a>
<div>
<div class="mini-profile-actions">
<span>Actions ▼</span>
<ul>
<li class="direct-messages-with-user">Send direct message</li>
<!-- TODO <li>Send post</li>-->
<li class="mentions-from-user">Display mentions</li>
<!-- WTF <li>Display retransmissions</li> -->
</ul>
</div>
<div class="following-config">
<button class="follow">Follow</button>
<button class="public-following">Public</button>
</div>
</div>
<div>
<span class="swarm-status" style="display: none;"></span>
</div>
</div>
</li>
</div>
<!-- MODAL DE FOLLOWING -->
<div id="following-modal-template">
<!-- ÁREA DE PROFILE PHOTO INIT -->
@ -708,19 +778,15 @@ @@ -708,19 +778,15 @@
</div>
<!-- MODAL DE FOLLOWING END -->
<!-- MODAL OF FOLLOWING CONFIG -->
<div id="following-config-modal-template">
<!-- ÁREA OF FOLLOWING METHOD -->
<div class="following-config-modal-content" data-screen-name="">
<h2><span class="following-config-method-message">Which way do you want to follow</span> <span class="following-screen-name">@<b></b></span>:</h2>
<div class="following-config-modal-content">
<span class="following-config-method-message">Which way do you want to follow @</span>
<div class="following-config-method-buttons">
<button class="public-following">Public</button>
<button class="public-following private">Private</button>
</div>
</div>
<!-- ÁREA OF FOLLOWING METHOD END -->
</div>
<!-- MODAL OF FOLLOWING CONFIG END -->
</div>
<!-- TEMPLATES END -->

1134
js/interface_common.js

File diff suppressed because it is too large Load Diff

47
js/interface_home.js

@ -33,6 +33,8 @@ var InterfaceFunctions = function() { @@ -33,6 +33,8 @@ var InterfaceFunctions = function() {
requestTimelineUpdate("latestFirstTime",postsPerRefresh,followingUsers,promotedPostsOnly);
});
cleanupStorage();
initInterfaceCommon();
initUserSearch();
initInterfaceDirectMsg();
@ -55,11 +57,6 @@ var InterfaceFunctions = function() { @@ -55,11 +57,6 @@ var InterfaceFunctions = function() {
$miniProfile.find(".posts-count").text("0");
$miniProfile.find(".following-count").text("0");
$miniProfile.find(".followers-count").text("0");
$miniProfile.find("a.open-following-page").attr("href","#");
$miniProfile.find("a.open-following-page").bind("click", function()
{ alert(polyglot.t("You are not following anyone because you are not logged in."))} );
$miniProfile.find("a.open-followers").bind("click", function()
{ alert(polyglot.t("You don't have any followers because you are not logged in."))} );
$(".dropdown-menu-following").attr("href","#");
$(".dropdown-menu-following").bind("click", function()
{ alert(polyglot.t("You are not following anyone because you are not logged in."))} );
@ -98,22 +95,6 @@ var InterfaceFunctions = function() { @@ -98,22 +95,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
@ -272,12 +253,12 @@ function refreshTwistdayReminder() { @@ -272,12 +253,12 @@ function refreshTwistdayReminder() {
var listCurrent = module.find('.current .list');
var listUpcoming = module.find('.upcoming .list');
var d = new Date();
var todayYear = d.getUTCFullYear();
var todayMonth = d.getUTCMonth();
var todayDate = d.getUTCDate();
var todaySec = Date.UTC(todayYear, todayMonth, todayDate,
d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds()) /1000;
var thatSec;
var curYear = d.getFullYear(), curYearUTC = d.getUTCFullYear();
var curMonth = d.getMonth();
var curDate = d.getDate();
var curSecUTC = Date.UTC(curYearUTC, d.getUTCMonth(), d.getUTCDate(),
d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds()) / 1000;
var upcSecUTC;
posts.sort(function(a, b) {
return (parseInt(a.userpost.time) > parseInt(b.userpost.time)) ? 1 : -1;
@ -287,16 +268,16 @@ function refreshTwistdayReminder() { @@ -287,16 +268,16 @@ function refreshTwistdayReminder() {
if (followingUsers.indexOf(posts[i].userpost.n) > -1) {
d.setTime(0);
d.setUTCSeconds(posts[i].userpost.time);
if (d.getUTCMonth() === todayMonth && d.getUTCDate() === todayDate) {
if (d.getMonth() === curMonth && d.getDate() === curDate) {
addLuckyToList(listCurrent, posts[i]);
removeLuckyFromList(listUpcoming, posts[i].userpost.n);
} else if (showUpcomingTimer > 0) {
thatSec = Date.UTC(todayYear, d.getUTCMonth(), d.getUTCDate(),
d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds()) /1000;
if (thatSec > todaySec && thatSec -todaySec <= showUpcomingTimer) {
upcSecUTC = Date.UTC(curYearUTC, d.getUTCMonth(), d.getUTCDate(),
d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds()) / 1000;
if (upcSecUTC > curSecUTC && upcSecUTC - curSecUTC <= showUpcomingTimer) {
d.setTime(0);
d.setUTCSeconds(thatSec);
addLuckyToList(listUpcoming, posts[i], d.getTime() /1000);
d.setUTCSeconds(upcSecUTC);
addLuckyToList(listUpcoming, posts[i], d.getTime() / 1000);
} else {
removeLuckyFromList(listCurrent, posts[i].userpost.n);
removeLuckyFromList(listUpcoming, posts[i].userpost.n);

240
js/interface_localization.js

@ -53,6 +53,7 @@ if(preferredLanguage == "en"){ @@ -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"){ @@ -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,10 +85,11 @@ if(preferredLanguage == "en"){ @@ -84,10 +85,11 @@ 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",
"Followers_of": "Followers of @%{alias}",
"Following": "Following",
"Following users": "Following users",
"Force connection to peer:": "Force connection to peer:",
@ -126,6 +128,12 @@ if(preferredLanguage == "en"){ @@ -126,6 +128,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +167,13 @@ if(preferredLanguage == "en"){ @@ -159,9 +167,13 @@ 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",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "The File APIs are not fully supported in this browser.",
"time_ago": "%{time} ago", // 5 minutes ago
"Time of the last block:": "Time of the last block: ",
@ -374,6 +386,7 @@ if(preferredLanguage == "es"){ @@ -374,6 +386,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 +402,7 @@ if(preferredLanguage == "es"){ @@ -389,7 +402,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,10 +418,11 @@ if(preferredLanguage == "es"){ @@ -405,10 +418,11 @@ 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",
"Followers_of": "Seguidores de @%{alias}",
"Following": "Siguiendo",
"Following users": "Siguiendo los usuarios",
"Force connection to peer:": "Forzar la conexión a los pares:",
@ -447,6 +461,12 @@ if(preferredLanguage == "es"){ @@ -447,6 +461,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +500,13 @@ if(preferredLanguage == "es"){ @@ -480,9 +500,13 @@ 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",
"shorten_URI": "Acortar URL",
"shorten_URI_enter_link": "Introducir el enlace largo.\n"
+ "¡Ten cuidado! Se envía un twist 'oculto' después de obtener"
+ "de cada nueva URL, incluso si no publicas algo todavía.",
"The File APIs are not fully supported in this browser.": "Las API de archivos no son totalmente compatibles con este navegador.",
"time_ago": "hace %{time}", // 5 minutes ago
"Time of the last block:": "Hora del último bloque: ",
@ -679,6 +703,7 @@ if(preferredLanguage == "uk"){ @@ -679,6 +703,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 +719,7 @@ if(preferredLanguage == "uk"){ @@ -694,7 +719,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,10 +736,11 @@ if(preferredLanguage == "uk"){ @@ -711,10 +736,11 @@ 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": "Читачі",
"Followers_of": "Читачі @%{alias}",
"Following": "Читає",
"Following users": "Підписані користувачі",
"Force connection to peer:": "Примусове з’єднання з піром:",
@ -753,6 +779,12 @@ if(preferredLanguage == "uk"){ @@ -753,6 +779,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"notify_desktop_error": "Twister не може створити сповіщення: невідома помилка.",
"notify_desktop_perm_denied": "Twister не може створити сповіщення на робочому столі: доступ обмежено.\n\nЯкщо ви бажаєте отримувати сповіщення, дозвольте їх виконання в налаштуваннях браузера для %{this_domain}.",
"notify_desktop_test": "Є дещо новеньке у стрічці.",
@ -786,9 +818,13 @@ if(preferredLanguage == "uk"){ @@ -786,9 +818,13 @@ if(preferredLanguage == "uk"){
"seconds": "%{smart_count} секунда |||| %{smart_count} секунд",
"send": "відіслати",
"Send post with username": "Надіслати повідомлення від",
"Sent Direct Message": "Надіслати особисте повідомлення",
"send_DM": "Надіслати особисте повідомлення",
"Sent Post to @": "Надіслати твіст @",
"Setup account": "Обліковий запис",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "File APIs не повністю підтримується браузером.",
"time_ago": "%{time} тому", // 5 minutes ago
"Time of the last block:": "Час останнього блоку: ",
@ -983,6 +1019,7 @@ if(preferredLanguage == "zh-CN"){ @@ -983,6 +1019,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 +1035,7 @@ if(preferredLanguage == "zh-CN"){ @@ -998,7 +1035,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,10 +1051,11 @@ if(preferredLanguage == "zh-CN"){ @@ -1014,10 +1051,11 @@ 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": "粉丝",
"Followers_of": "Followers of @%{alias}",
"Following": "关注",
"Following users": "关注的用户",
"Force connection to peer:": "强制连接到节点:",
@ -1056,6 +1094,12 @@ if(preferredLanguage == "zh-CN"){ @@ -1056,6 +1094,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"notify_desktop_error": "Twister 无法发出桌面提醒:发生未知错误。",
"notify_desktop_perm_denied": "Twister 无法发出桌面提醒:权限被拒绝。\n\n如果你想收到提醒,请在你的浏览器设置中允许 %{this_domain} 发出提醒。",
"notify_desktop_test": "我们都在用 Twister。\n欢迎你的加入。",
@ -1089,9 +1133,13 @@ if(preferredLanguage == "zh-CN"){ @@ -1089,9 +1133,13 @@ if(preferredLanguage == "zh-CN"){
"seconds": "%{smart_count} 秒",
"send": "发送",
"Send post with username": "发送推文的用户名",
"Sent Direct Message": "发送私信",
"send_DM": "发送私信",
"Sent Post to @": "发送推文 @",
"Setup account": "设置账号",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "这个浏览器不能完全支持 File API。",
"time_ago": "%{time} 之前", // 5 minutes ago
"Time of the last block:": "最新区块的时间:",
@ -1304,6 +1352,7 @@ if(preferredLanguage == "nl"){ @@ -1304,6 +1352,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 +1368,7 @@ if(preferredLanguage == "nl"){ @@ -1319,7 +1368,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,10 +1384,11 @@ if(preferredLanguage == "nl"){ @@ -1335,10 +1384,11 @@ 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",
"Followers_of": "Followers of @%{alias}",
"Following": "Volgend",
"Following users": "Volgende gebruikers",
"Force connection to peer:": "Forceer connectie met peer:",
@ -1377,6 +1427,12 @@ if(preferredLanguage == "nl"){ @@ -1377,6 +1427,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +1466,13 @@ if(preferredLanguage == "nl"){ @@ -1410,9 +1466,13 @@ 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",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "The File APIs are not fully supported in this browser.",
"time_ago": "%{time} geleden", // 5 minutes ago
"Time of the last block:": "Tijd van de laatste block: ",
@ -1609,6 +1669,7 @@ if(preferredLanguage == "it"){ @@ -1609,6 +1669,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 +1685,7 @@ if(preferredLanguage == "it"){ @@ -1624,7 +1685,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,10 +1701,11 @@ if(preferredLanguage == "it"){ @@ -1640,10 +1701,11 @@ 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",
"Followers_of": "Followers of @%{alias}",
"Following": "Seguiti",
"Following users": "Utenti seguiti",
"Force connection to peer:": "Forza connessione al nodo:",
@ -1682,6 +1744,12 @@ if(preferredLanguage == "it"){ @@ -1682,6 +1744,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +1783,13 @@ if(preferredLanguage == "it"){ @@ -1715,9 +1783,13 @@ 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",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "Le API File non sono interamente supportate da questo browser.",
"time_ago": "%{time} fa", // 5 minutes ago
"Time of the last block:": "Orario del blocco più recente: ",
@ -1912,6 +1984,7 @@ if(preferredLanguage == "fr"){ @@ -1912,6 +1984,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 +2000,7 @@ if(preferredLanguage == "fr"){ @@ -1927,7 +2000,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,10 +2016,11 @@ if(preferredLanguage == "fr"){ @@ -1943,10 +2016,11 @@ 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",
"Followers_of": "Followers of @%{alias}",
"Following": "Abonnements",
"Following users": "Following users",
"Force connection to peer:": "Forcer la connection à un pair:",
@ -1985,6 +2059,12 @@ if(preferredLanguage == "fr"){ @@ -1985,6 +2059,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +2098,13 @@ if(preferredLanguage == "fr"){ @@ -2018,9 +2098,13 @@ 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",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"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.",
"time_ago": "Il y a %{time}", // 5 minutes ago
"Time of the last block:": "Heure du dernier bloc: ",
@ -2219,6 +2303,7 @@ if(preferredLanguage == "ru"){ @@ -2219,6 +2303,7 @@ if(preferredLanguage == "ru"){
"Если вы останетесь на этой странице ваши действия могут быть не выполнены.\n" +
"Не хотите перейти на [страницу настройки сети](%{page})?",
"confirm_terminate_daemon": "Вы уверены, что хотите выключить демон?\nTwister клиент перестанет работать.",
"confirm_unfollow_@": "Действительно отписаться от @%{alias}?",
"Change user": "Сменить пользователя",
"Checking...": "Проверка...",
"Collapse": "Свернуть",
@ -2234,7 +2319,7 @@ if(preferredLanguage == "ru"){ @@ -2234,7 +2319,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 +2335,12 @@ if(preferredLanguage == "ru"){ @@ -2250,11 +2335,12 @@ 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": "Читатели",
"Followers_of": "Читатели @%{alias}",
"Following": "Читаемые",
"Following users": "Подписанные пользователи",
"Force connection to peer:": "Принудительно подключиться к пиру:",
"General information": "Основное",
@ -2292,6 +2378,12 @@ if(preferredLanguage == "ru"){ @@ -2292,6 +2378,12 @@ 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Поди ж найди кого-нибудь да и подпишись.",
"warn_followers_not_all": "Пока что нет простого способа узнать список всех подписчиков.\n"
+ "Счётчик показывает лишь количество известных пиров твоего торрента.\n"
+ "В списке ниже включены те, главным образом, на кого подписан(а) ты сам(а).",
"warn_followers_not_all_of": "Пока что нет простого способа узнать список всех подписчиков.\n"
+ "В списке ниже, возможно, лишь некоторые из тех, кто подписан на @%{alias} публично.",
"notify_desktop_error": "Твистер не может выполнить уведомление: произошла неизвестная ошибка.",
"notify_desktop_perm_denied": "Твистер не может выполнить уведомление: разрешение не получено.\n\nЧтобы получать уведомления, разрешите их для %{this_domain} в настройках вашего браузера.",
"notify_desktop_test": "Одна лягушка сказала:\n'если не буду квакать — лопну'.\nВы нужны нам, берегите себя.",
@ -2325,9 +2417,13 @@ if(preferredLanguage == "ru"){ @@ -2325,9 +2417,13 @@ if(preferredLanguage == "ru"){
"seconds": "%{smart_count} секунда |||| %{smart_count} секунд",
"send": "отправить",
"Send post with username": "Отправить сообщение от имени",
"Sent Direct Message": "Отправить личное сообщение",
"send_DM": "Отправить личное сообщение",
"Sent Post to @": "Отправить сообщение для @",
"Setup account": "Настроить аккаунт",
"shorten_URI": "Сокр. URL",
"shorten_URI_enter_link": "Введи длинную ссылку.\n"
+ "Будь осторожнее! Ты отправляешь 'скрытый' твист после получения\n"
+ "каждой новой URL, даже если ты ещё не успел(а) ничего никуда отправить.",
"The File APIs are not fully supported in this browser.": "File APIs не полностью поддерживается этим браузером.",
"time_ago": "%{time} назад", // 5 minutes ago
"Time of the last block:": "Время последнего блока: ",
@ -2528,6 +2624,7 @@ if(preferredLanguage == "de"){ @@ -2528,6 +2624,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 +2640,7 @@ if(preferredLanguage == "de"){ @@ -2543,7 +2640,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,10 +2657,11 @@ if(preferredLanguage == "de"){ @@ -2560,10 +2657,11 @@ 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",
"Followers_of": "Followers of @%{alias}",
"Following": "Folgt",
"Following users": "Folgt Benutzern",
"Force connection to peer:": "Erzwinge Verbindung zu Peer:",
@ -2602,6 +2700,12 @@ if(preferredLanguage == "de"){ @@ -2602,6 +2700,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +2739,13 @@ if(preferredLanguage == "de"){ @@ -2635,9 +2739,13 @@ 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",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "Die File-API's werden von diesem Browser nicht vollständig unterstützt.",
"time_ago": "vor %{time}", // 5 minutes ago
"Time of the last block:": "Zeit des letzten Blocks: ",
@ -2668,7 +2776,7 @@ if(preferredLanguage == "de"){ @@ -2668,7 +2776,7 @@ if(preferredLanguage == "de"){
"Create a new user": "Neuen Benutzer erstellen",
"Login": "Einloggen",
"Check availability": "Verfügbarkeit überprüfen",
"Create this nickname": "Nichnamen erstellen",
"Create this nickname": "Nicknamen erstellen",
"Type nickname here": "Nicknamen hier eingeben",
"Import secret key": "Privaten Schlüssel hier importieren",
"52-characters secret": "52 Zeichen Geheimnis",
@ -2835,6 +2943,7 @@ if(preferredLanguage == "ja"){ @@ -2835,6 +2943,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 +2959,7 @@ if(preferredLanguage == "ja"){ @@ -2850,7 +2959,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,10 +2975,11 @@ if(preferredLanguage == "ja"){ @@ -2866,10 +2975,11 @@ 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": "フォロワー",
"Followers_of": "Followers of @%{alias}",
"Following": "フォロー",
"Following users": "フォローしているユーザー",
"Force connection to peer:": "強制的に経由するピア:",
@ -2908,6 +3018,12 @@ if(preferredLanguage == "ja"){ @@ -2908,6 +3018,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +3057,13 @@ if(preferredLanguage == "ja"){ @@ -2941,9 +3057,13 @@ if(preferredLanguage == "ja"){
"seconds": "%{smart_count} 秒 |||| %{smart_count} 秒",
"send": "送信",
"Send post with username": "プロモートメッセージの送信元",
"Sent Direct Message": "ダイレクトメッセージを送る",
"send_DM": "ダイレクトメッセージを送る",
"Sent Post to @": "メンションを投稿する",
"Setup account": "アカウント設定",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "ご使用のブラウザーは完全にファイルAPIに対応していません。",
"time_ago": "%{time}前", // 5 minutes ago
"Time of the last block:": "最新ブロックの生成日時: ",
@ -3138,6 +3258,7 @@ if(preferredLanguage == "pt-BR"){ @@ -3138,6 +3258,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 +3274,7 @@ if(preferredLanguage == "pt-BR"){ @@ -3153,7 +3274,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,10 +3290,11 @@ if(preferredLanguage == "pt-BR"){ @@ -3169,10 +3290,11 @@ 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",
"Followers_of": "Seguidores de @%{alias}",
"Following": "Seguindo",
"Following users": "Usuários que sigo",
"Force connection to peer:": "Forçar conexão com o nó:",
@ -3211,6 +3333,12 @@ if(preferredLanguage == "pt-BR"){ @@ -3211,6 +3333,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +3373,13 @@ if(preferredLanguage == "pt-BR"){ @@ -3245,9 +3373,13 @@ 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",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "O gerenciamento de arquivos não é completamente suportado neste navegador.",
"time_ago": "%{time} atrás", // 5 minutes ago
"Time of the last block:": "Horário do último bloco: ",
@ -3445,6 +3577,7 @@ if(preferredLanguage == "tr"){ @@ -3445,6 +3577,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 +3593,7 @@ if(preferredLanguage == "tr"){ @@ -3460,7 +3593,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,10 +3609,11 @@ if(preferredLanguage == "tr"){ @@ -3476,10 +3609,11 @@ 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",
"Followers_of": "Followers of @%{alias}",
"Following": "Takip edilenler",
"Following users": "Takip edilen kullanıcılar",
"Force connection to peer:": "Bağlantı için zorlanacak eş:",
@ -3518,6 +3652,12 @@ if(preferredLanguage == "tr"){ @@ -3518,6 +3652,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +3691,13 @@ if(preferredLanguage == "tr"){ @@ -3551,9 +3691,13 @@ 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ı",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "Dosya API'si tarayıcınızda tam olarak desteklenmiyor.",
"time_ago": "%{time} önce", // 5 minutes ago
"Time of the last block:": "Son blok saati: ",
@ -3749,6 +3893,7 @@ if(preferredLanguage == "cs"){ @@ -3749,6 +3893,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 +3909,7 @@ if(preferredLanguage == "cs"){ @@ -3764,7 +3909,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,10 +3925,11 @@ if(preferredLanguage == "cs"){ @@ -3780,10 +3925,11 @@ 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í",
"Followers_of": "Followers of @%{alias}",
"Following": "Sledovaní",
"Following users": "Sledovaní uživatelé",
"Force connection to peer:": "Vyžádat připojení k uzlu:",
@ -3822,6 +3968,12 @@ if(preferredLanguage == "cs"){ @@ -3822,6 +3968,12 @@ 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.",
"warn_followers_not_all": "Well, currently here's no easy way to obtain all your followers.\n"
+ "The counter indicates only a number of known peers sharing your torrent.\n"
+ "In the list below are included ones, mostly, who are followed by you.",
"warn_followers_not_all_of": "Well, currently here's no easy way to obtain all followers of whoever.\n"
+ "In the list below are included only few, perhaps, of ones who follow @%{alias} publicly.",
"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,9 +4008,13 @@ if(preferredLanguage == "cs"){ @@ -3856,9 +4008,13 @@ 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",
"shorten_URI": "Shorten URL",
"shorten_URI_enter_link": "Enter the long link.\n"
+ "Be careful! You send a 'hidden' twist after getting\n"
+ "of each new URL even if you ain't post anything yet.",
"The File APIs are not fully supported in this browser.": "Upozornění: váš webový prohlížeč nepodporuje File API.",
"time_ago": "před %{time}", // 5 minutes ago
"Time of the last block:": "Čas posledního bloku: ",

56
js/mobile_abstract.js

@ -31,27 +31,24 @@ var MAL = function() @@ -31,27 +31,24 @@ var MAL = function()
}
}
this.dmThreadListLoaded = function() {
if( $.hasOwnProperty("mobile") ) {
this.commonDMsListLoaded = function () {
if ($.hasOwnProperty('mobile')) {
$.mobile.hidePageLoadingMsg();
var $dmThreadList = $("#directmsg ul.direct-messages-thread");
$dmThreadList.listview('refresh');
$('#directmsg .direct-messages-list').listview('refresh');
} else {
}
}
};
this.dmChatListLoaded = function(dmConvo) {
if( $.hasOwnProperty("mobile") ) {
this.dmConversationLoaded = function (dmConvo) {
if ($.hasOwnProperty('mobile')) {
$.mobile.hidePageLoadingMsg();
var $dmChatList = $("#dmchat ul.direct-messages-list");
$dmChatList.listview('refresh');
$.mobile.silentScroll( $(".dm-form").offset().top );
$('#dmchat .direct-messages-thread').listview('refresh');
$.mobile.silentScroll($('.dm-form').offset().top);
} else {
var modalContent = dmConvo.closest(".modal-content");
var modalContent = dmConvo.closest('.modal-content');
modalContent.scrollTop(modalContent[0].scrollHeight);
}
}
};
this.relatedPostLoaded = function() {
if( $.hasOwnProperty("mobile") ) {
@ -63,15 +60,26 @@ var MAL = function() @@ -63,15 +60,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.listLoaded = function (list) {
if ($.hasOwnProperty('mobile')) {
$.mobile.hidePageLoadingMsg();
$(".following-list").listview('refresh');
} else {
$(".postboard-loading").hide();
}
}
list.listview('refresh');
} else
list.find('.loading-roller').hide();
};
this.searchUserListLoaded = function() {
if( $.hasOwnProperty("mobile") ) {
@ -505,7 +513,7 @@ var MAL = function() @@ -505,7 +513,7 @@ var MAL = function()
jQuery.MAL = new MAL;
function playSound(player, sound) {
function playSound(player, sound, volume) {
if ($.mobile) {
} else {
var player = $('#'+player);
@ -518,7 +526,7 @@ function playSound(player, sound) { @@ -518,7 +526,7 @@ function playSound(player, sound) {
else
player.attr({type: 'audio/ogg', src: 'sound/' + sound + '.ogg'});
player[0].volume = $.Options.playerVol.val;
player[0].volume = (typeof volume === 'number') ? volume : $.Options.playerVol.val;
player[0].play();
} else
console.warn('cannot find player to play sound, selector: #'+player);
@ -535,7 +543,9 @@ function filterLang(string) { @@ -535,7 +543,9 @@ function filterLang(string) {
var langFilterReason = '';
var langFilterList = $.Options.filterLangList.val;
if (langFilterList.length > 0) {
if (!string) {
langFilterReason = polyglot.t('this is undefined', {'this': 'string'});
} else if (langFilterList.length > 0) {
var langFilterAccuracy = $.Options.filterLangAccuracy.val;
langFilterPass = (langFilterMode === 'whitelist') ? false : true;
langFilterReason = polyglot.t('this doesnt contain that', {'this': polyglot.t(langFilterMode), 'that': polyglot.t('language of this')});

4
js/options.js

@ -378,8 +378,8 @@ function tickOptionsPostPreview() { @@ -378,8 +378,8 @@ function tickOptionsPostPreview() {
var elem = $('#opt-mod-posts-display #post-preview');
var imgPreviewCont = elem.find('.preview-container');
elem.children().first().html(htmlFormatMsg(
polyglot.t('post_preview_dummy', {logo: '/img/twister_mini.png', site: 'http://twister.net.co'})).html);
fillElemWithTxt(elem.children().first(),
polyglot.t('post_preview_dummy', {logo: '/img/twister_mini.png', site: 'http://twister.net.co'}));
if ($.Options.displayPreview.val === 'enable') {
imgPreviewCont.empty();

20
js/tmobile.js

@ -26,7 +26,7 @@ function initializeTwister( redirectNetwork, redirectLogin, cbFunc, cbArg ) { @@ -26,7 +26,7 @@ function initializeTwister( redirectNetwork, redirectLogin, cbFunc, cbArg ) {
// reply text counter both newmsg and dmchat
$('.post-area-new textarea')
.off('input keyup')
.on('focus', posPostPreview)
.on('focus', poseTextareaPostTools)
.on('keyup', replyTextInput)
.on('keyup', function() { replyTextUpdateRemaining(this); })
;
@ -101,6 +101,7 @@ var router=new $.mobile.Router( @@ -101,6 +101,7 @@ var router=new $.mobile.Router(
initializeTwister( true, true, function() {
if( !$("#home .posts").children().length ) {
$.mobile.showPageLoadingMsg();
cleanupStorage();
getFullname( defaultScreenName, $("#home .rtitle"));
$(".mentions-count").attr("href","#mentions?user="+defaultScreenName );
$.MAL.setPostTemplate( $("#post-template-home") );
@ -160,7 +161,10 @@ var router=new $.mobile.Router( @@ -160,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();
appendFollowingToElem(followingList);
followingList.find('[data-role="button"]').button();
});
},
post: function(type,match,ui) {
@ -268,9 +272,8 @@ var router=new $.mobile.Router( @@ -268,9 +272,8 @@ var router=new $.mobile.Router(
directmsg: function(type,match,ui) {
$.mobile.showPageLoadingMsg();
initializeTwister( true, true, function() {
var $dmThreadList = $("#directmsg ul.direct-messages-thread");
$.mobile.showPageLoadingMsg();
requestDMsnippetList($dmThreadList);
requestDMsnippetList($('#directmsg .direct-messages-list'));
});
},
dmchat: function(type,match,ui) {
@ -278,7 +281,7 @@ var router=new $.mobile.Router( @@ -278,7 +281,7 @@ var router=new $.mobile.Router(
$.mobile.showPageLoadingMsg();
initializeTwister( true, true, function() {
var user = params.user;
var dmConvo = $("#dmchat ul.direct-messages-list");
var dmConvo = $('#dmchat .direct-messages-thread');
$("#dmchat .rtitle").text("Chat @" + user);
$("#dmchat textarea").val("");
dmConvo.html("");
@ -492,7 +495,7 @@ function handleAvatarFileSelectMobile(evt) { @@ -492,7 +495,7 @@ function handleAvatarFileSelectMobile(evt) {
}
}
function openConversationClick(event) {
function handleClickOpenConversation(event) {
event.stopPropagation();
event.preventDefault();
@ -586,9 +589,8 @@ function tmobileTick() { @@ -586,9 +589,8 @@ function tmobileTick() {
requestQuery(tmobileQueryReq);
}
if( curPage == "dmchat" ) {
requestDmConversation($("#dmchat ul.direct-messages-list"),dmChatUser);
}
if (curPage === 'dmchat')
requestDmConversation($('#dmchat .direct-messages-thread'), dmChatUser);
}
$(document).bind('mobileinit', function () {

56
js/twister_actions.js

@ -156,18 +156,13 @@ function requestRTs(postLi) @@ -156,18 +156,13 @@ function requestRTs(postLi)
}
}
function appendPostToContainer(postFromJson, containerToAppend)
{
// posts without 'msg' may be used for metadata like 'url'
// and are not meant to be displayed.
if (typeof(postFromJson['userpost']['msg']) === 'undefined' &&
typeof(postFromJson['userpost']['rt']) === 'undefined' )
function appendPostToElem(post, elem) {
// posts without 'msg' and 'rt.msg' may be used for metadata like 'url' and are not meant to be displayed
if (!post.userpost.msg && (!post.userpost.rt || (post.userpost.rt && !post.userpost.rt.msg)))
return;
var newStreamPost = postToElem(postFromJson, "original");
newStreamPost.hide();
containerToAppend.append( newStreamPost );
newStreamPost.slideDown("fast");
postToElem(post, 'original').hide().appendTo(elem).slideDown('fast');
$.MAL.postboardLoaded();
}
@ -183,7 +178,7 @@ function requestPost(containerToAppend,username,resource,cbFunc,cbArgs){ @@ -183,7 +178,7 @@ function requestPost(containerToAppend,username,resource,cbFunc,cbArgs){
//console.log(postFromJson);
appendPostToContainer(postFromJson,args.containerToAppend);
appendPostToElem(postFromJson, args.containerToAppend);
if(args.cbFunc!=undefined) args.cbFunc(args.cbArgs);
@ -217,7 +212,7 @@ function requestPostRecursively(containerToAppend,username,resource,count,useGet @@ -217,7 +212,7 @@ function requestPostRecursively(containerToAppend,username,resource,count,useGet
twisterRpc("getposts", [count,[req]],
function(args, posts) {
for( var i = 0; i < posts.length; i++ ) {
appendPostToContainer(posts[i],args.containerToAppend);
appendPostToElem(posts[i], args.containerToAppend);
}
profilePostsLoading = false;
}, {containerToAppend:containerToAppend},
@ -228,7 +223,7 @@ function requestPostRecursively(containerToAppend,username,resource,count,useGet @@ -228,7 +223,7 @@ function requestPostRecursively(containerToAppend,username,resource,count,useGet
dhtget( username, resource, "s",
function(args, postFromJson) {
if( postFromJson ) {
appendPostToContainer(postFromJson,args.containerToAppend);
appendPostToElem(postFromJson, args.containerToAppend);
if( args.count > 1 ) {
var userpost = postFromJson["userpost"];
@ -322,6 +317,41 @@ function newRtMsg(postData, msg) { @@ -322,6 +317,41 @@ function newRtMsg(postData, msg) {
}
}
function newShortURI(uri, cbFunc, cbReq) {
if (!uri || !defaultScreenName) return;
if (parseInt(twisterVersion) < 93500) {
console.warn('can\'t shorten URI "' + uri + '": daemon is obsolete, version 0.9.35 or higher is required');
return;
}
for (var i in twister.URIs)
if (twister.URIs[i] === uri) {
if (typeof cbFunc === 'function')
cbFunc(uri, i, cbReq);
return;
}
twisterRpc('newshorturl', [defaultScreenName, lastPostId + 1, uri],
function (req, ret) {
if (ret) {
ret = ret[0]; // FIXME there should be 1 element anyway for daemon version 93500
twister.URIs[ret] = req.uri;
$.localStorage.set('twistaURIs', twister.URIs);
incLastPostId();
} else
console.warn('RPC "newshorturl" error: empty response');
if (typeof req.cbFunc === 'function')
req.cbFunc(req.uri, ret, req.cbReq);
}, {uri: uri, cbFunc: cbFunc, cbReq: cbReq},
function (req, ret) {
console.warn('RPC "newshorturl" error: ' + (ret && ret.message ? ret.message : ret));
if (typeof req.cbFunc === 'function')
req.cbFunc(req.uri, ret, req.cbReq);
}, {uri: uri, cbFunc: cbFunc, cbReq: cbReq}
);
}
function updateProfileData(profileModalContent, username) {
//profileModalContent.find("a").attr("href",$.MAL.userUrl(username));

77
js/twister_directmsg.js

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
var _groupMsgInviteToGroupQueue = [];
function requestDMsnippetList(dmThreadList, forGroup) {
function requestDMsnippetList(elemList, forGroup) {
var followList = [];
for (var i = 0; i < followingUsers.length; i++)
followList.push({username: followingUsers[i]});
@ -13,40 +13,19 @@ function requestDMsnippetList(dmThreadList, forGroup) { @@ -13,40 +13,19 @@ function requestDMsnippetList(dmThreadList, forGroup) {
followList.push({username: groupChatAliases[i]});
twisterRpc('getdirectmsgs', [defaultScreenName, 1, followList],
function(req, ret) {processDMsnippet(ret, req.dmThreadList, req.forGroup);},
{dmThreadList: dmThreadList, forGroup: forGroup},
processDMsnippet, {elemList: elemList, forGroup: forGroup},
function(req, ret) {console.log('ajax error:' + ret);}, null
);
}
function processDMsnippet(dmUsers, dmThreadList, forGroup) {
dmThreadList.empty();
function processDMsnippet(req, DMs) {
req.elemList.empty();
for (var u in dmUsers) {
if ((forGroup && u[0] !== '*') || (!forGroup && u[0] === '*'))
continue;
for (var alias in DMs)
if ((req.forGroup && alias[0] === '*') || (!req.forGroup && alias[0] !== '*'))
addToCommonDMsList(req.elemList, alias, DMs[alias][0]);
// convert snipped to html and add it to date-sorted list
var dmItem = dmDataToSnippetItem(dmUsers[u][0], u);
if (_newDMsPerUser[u] > 0) {
dmItem.addClass('new')
.find('.messages-qtd').text(_newDMsPerUser[u]).show();
}
var timeDmItem = parseInt(dmItem.attr('data-time'));
var existingItems = dmThreadList.children();
for (var j = 0; j < existingItems.length; j++) {
var streamItem = existingItems.eq(j);
var timeExisting = streamItem.attr('data-time');
if (typeof timeExisting === 'undefined' || timeDmItem > parseInt(timeExisting)) {
// this post in stream is older, so post must be inserted above
streamItem.before(dmItem);
break;
}
}
if (j === existingItems.length)
dmThreadList.append(dmItem);
}
$.MAL.dmThreadListLoaded();
$.MAL.commonDMsListLoaded();
}
function requestDmConversationModal(postboard, peerAlias) {
@ -103,7 +82,7 @@ function processDmConversation(stream, peerAlias, posts) { @@ -103,7 +82,7 @@ function processDmConversation(stream, peerAlias, posts) {
streamPostsIDs.push(lastPostID);
}
}
$.MAL.dmChatListLoaded(stream);
$.MAL.dmConversationLoaded(stream);
}
if (newPosts) {
@ -183,7 +162,7 @@ function newDirectMsg(msg, peerAlias) { @@ -183,7 +162,7 @@ function newDirectMsg(msg, peerAlias) {
}
// dispara o modal de direct messages
function directMessagesPopup() {
function openCommonDMsModal() {
if (!defaultScreenName) {
alert(polyglot.t('You have to log in to use direct messages.'));
return;
@ -191,7 +170,7 @@ function directMessagesPopup() { @@ -191,7 +170,7 @@ function directMessagesPopup() {
var modal = openModal({
classAdd: 'directMessages',
content: $('.direct-messages-template').children().clone(true),
content: twister.tmpl.commonDMsList.clone(true),
title: polyglot.t('Direct Messages')
});
@ -245,7 +224,7 @@ function openGroupMessagesModal(groupAlias) { @@ -245,7 +224,7 @@ function openGroupMessagesModal(groupAlias) {
if (typeof groupAlias === 'undefined') {
var modal = openModal({
classAdd: 'directMessages groupMessages',
content: $('.direct-messages-template').children().clone(true),
content: twister.tmpl.commonDMsList.clone(true),
title: polyglot.t('Group Messages')
});
@ -324,7 +303,7 @@ function openGroupMessagesNewGroupModal() { @@ -324,7 +303,7 @@ function openGroupMessagesNewGroupModal() {
groupMsgCreateGroup(elemForm.find('.description').val(), peersToInvite);
closeModal();
closeModal(event);
});
}
@ -375,7 +354,7 @@ function openGroupMessagesJoinGroupModal() { @@ -375,7 +354,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 +367,8 @@ function openGroupMessagesJoinGroupModal() { @@ -388,8 +367,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}));
}
@ -496,11 +475,6 @@ function initInterfaceDirectMsg() { @@ -496,11 +475,6 @@ function initInterfaceDirectMsg() {
$('.groupmessages').attr('href', '#groupmessages');
$('.userMenu-groupmessages a').attr('href', '#groupmessages');
$('#dm-snippet-template').on('click', function() {
var alias = $(this).attr('data-screen-name');
window.location.hash = '#directmessages?' + (alias[0] === '*' ? 'group' : 'user') + '=' + alias;
});
$('.dm-submit').on('click', directMsgSubmit);
$('.direct-messages-with-user').on('click', function() {
window.location.hash = '#directmessages?user=' +
@ -544,16 +518,17 @@ function initInterfaceDirectMsg() { @@ -544,16 +518,17 @@ 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) {
groupMsgLeaveGroup(groupAlias, function () {history.back();});
var elemLeave = $(event.target);
var groupAlias = elemLeave.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 (req) {
groupMsgLeaveGroup(req.groupAlias, closeModal, req.elem);
},
confirmFuncArgs: groupAlias
});
cbConfirmReq: {groupAlias: groupAlias, elem: elemLeave}
};
confirmPopup(event);
});
$('.group-messages-control .new').on('click', function () {

238
js/twister_following.js

@ -132,6 +132,7 @@ TwisterFollowing.prototype = { @@ -132,6 +132,7 @@ TwisterFollowing.prototype = {
if (following.indexOf(args.tf.user) > -1) {
if (args.tf.knownFollowers.indexOf(args.fu) < 0) {
args.tf.knownFollowers.push(args.fu);
addPeerToFollowersList(getElem('.followers-modal .followers-list'), args.fu, true);
}
} else {
if (args.tf.notFollowers.indexOf(args.fu) < 0) {
@ -140,6 +141,8 @@ TwisterFollowing.prototype = { @@ -140,6 +141,8 @@ TwisterFollowing.prototype = {
var tmpi = args.tf.knownFollowers.indexOf(args.fu);
if (tmpi > -1) {
args.tf.knownFollowers.splice(tmpi, 1);
getElem('.followers-modal .followers-list')
.find('li[data-peer-alias="' + args.fu + '"]').remove();
}
}
$(".open-followers").attr("title", args.tf.knownFollowers.length.toString());
@ -373,7 +376,6 @@ function follow(user, publicFollow, cbFunc, cbArg) { @@ -373,7 +376,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 +391,6 @@ function unfollow(user, cbFunc, cbArg) { @@ -389,8 +391,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();
@ -471,7 +471,8 @@ function whoFollows(username) { @@ -471,7 +471,8 @@ function whoFollows(username) {
function fillWhoFollows(list, item, offset, size) {
for (var i = offset; i < offset + size; i++) {
var follower_link = $( '<a class="mini-follower-link"></a>' );
var follower_link = $('<a class="mini-follower-link"></a>')
.on('click mouseup', handleClickOpenProfileModal);
// link follower to profile page
follower_link.attr("data-screen-name", list[i]);
@ -483,73 +484,20 @@ function fillWhoFollows(list, item, offset, size) { @@ -483,73 +484,20 @@ function fillWhoFollows(list, item, offset, size) {
}
}
function getWhoFollows(username, item) {
if (!defaultScreenName || typeof(defaultScreenName) === 'undefined')
function getWhoFollows(peerAlias, elem) {
if (!defaultScreenName)
return;
var list = whoFollows(username);
var list = whoFollows(peerAlias);
fillWhoFollows(list, item, 0, (list.length > 5 ? 5 : list.length));
fillWhoFollows(list, elem, 0, (list.length > 5 ? 5 : list.length));
if (list.length > 5) {
var more_link = $('<a class="show-more-followers">' + polyglot.t('show_more_count', {'smart_count': list.length - 5}) + '</a>');
more_link.on('click', function() {
fillWhoFollows(list, item, 5, list.length - 5);
var $this = $(this);
$this.remove();
$this.text(polyglot.t('hide'));
$this.unbind('click');
$this.bind('click', function() {
item.html('');
getWhoFollows(username, item);
});
item.append($this);
});
item.append(more_link);
}
}
// 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();
if (list.length > 5)
twister.tmpl.profileShowMoreFollowers.clone(true)
.text(polyglot.t('show_more_count', {'smart_count': list.length - 5}))
.on('mouseup', {route: '#followers?user=' + peerAlias}, routeOnClick)
.appendTo(elem)
;
}
function processWhoToFollowSuggestion(suggestion, followedBy) {
@ -644,7 +592,9 @@ function searchPartialUsername(event) { @@ -644,7 +592,9 @@ function searchPartialUsername(event) {
_searchingPartialName = '';
}
}, event,
function(req, ret) {console.warn('ajax error:' + ret.message);}, null
function(req, ret) {
console.warn('RPC "listusernamespartial" error: ' + (ret && ret.message ? ret.message : ret));
}, null
);
}
@ -664,37 +614,16 @@ function processDropdownUserResults(event, results) { @@ -664,37 +614,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 +632,6 @@ function initUserSearch() { @@ -703,16 +632,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 +642,6 @@ function userSearchEnter(event) { @@ -723,37 +642,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 +682,3 @@ function followingChangedUser() { @@ -794,83 +682,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);
}

110
js/twister_formatpost.js

@ -3,18 +3,13 @@ @@ -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();
@ -30,6 +25,7 @@ $(document).ready(function() { @@ -30,6 +25,7 @@ $(document).ready(function() {
_htmlFormatMsgLinkTemplateHashtag = _htmlFormatMsgLinkTemplateHashtag[0].cloneNode();
_htmlFormatMsgLinkTemplateHashtag.removeAttribute('id');
}
twister.tmpl.linkShortened = extractTemplate('#template-link-shortened')[0];
});
// format "userpost" to html element
@ -64,7 +60,7 @@ function postToElem(post, kind, promoted) { @@ -64,7 +60,7 @@ function postToElem(post, kind, promoted) {
if (post.sig_wort)
userpost.sig_wort = post.sig_wort;
if (userpost.rt) {
if (userpost.rt && userpost.rt.msg) {
rt = userpost.rt;
if (userpost.msg) {
username = userpost.n;
@ -92,7 +88,7 @@ function postToElem(post, kind, promoted) { @@ -92,7 +88,7 @@ function postToElem(post, kind, promoted) {
}
// Now create the html elements
var elem = $.MAL.getPostTemplate().clone(true);
var elem = $.MAL.getPostTemplate().clone(true).appendTo(twister.html.detached);
elem.removeAttr('id')
.addClass(kind)
.attr('data-time', time)
@ -125,8 +121,7 @@ function postToElem(post, kind, promoted) { @@ -125,8 +121,7 @@ function postToElem(post, kind, promoted) {
setPostCommon(elem, username, time);
msg = htmlFormatMsg(msg);
elem.find('.post-text').html(msg.html);
msg = fillElemWithTxt(elem.find('.post-text'), msg); // fillElemWithTxt() returns result of htmlFormatMsg(msg)
postData.attr('data-text-mentions', msg.mentions.join()); // FIXME no idea why do we need this attribute since we don't use it but use data-reply-to instead
if (username !== defaultScreenName) {
@ -156,7 +151,7 @@ function postToElem(post, kind, promoted) { @@ -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,12 +227,12 @@ function setPostCommon(elem, username, time) { @@ -232,12 +227,12 @@ 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)
.attr('data-userpost', $.toJSON({userpost: rt, sig_userpost: sig_rt}))
.find('.post-text').html(htmlFormatMsg(rt.msg).html)
.find('.post-text').each(function (i, elem) {fillElemWithTxt($(elem), rt.msg);})
;
setPostCommon(elem, rt.n, rt.time);
}
@ -256,32 +251,6 @@ function setPostInfoSent(n, k, item) { @@ -256,32 +251,6 @@ function setPostInfoSent(n, k, item) {
}
}
// format dmdata (returned by getdirectmsgs) to display in "snippet" per user list
function dmDataToSnippetItem(dmData, remoteUser) {
var dmItem = $("#dm-snippet-template").clone(true);
dmItem.removeAttr('id');
dmItem.attr('data-screen-name', remoteUser);
dmItem.attr("data-last_id", dmData.id);
dmItem.attr("data-time", dmData.time);
dmItem.find(".post-info-tag").text("@" + remoteUser);
dmItem.find("a.post-info-name").attr("href", $.MAL.userUrl(remoteUser));
dmItem.find("a.dm-chat-link").attr("href", $.MAL.dmchatUrl(remoteUser));
getAvatar( remoteUser, dmItem.find(".post-photo").find("img") );
if( remoteUser.length && remoteUser[0] === '*' )
getGroupChatName( remoteUser, dmItem.find("a.post-info-name") );
else
getFullname( remoteUser, dmItem.find("a.post-info-name") );
dmItem.find(".post-text").html(htmlFormatMsg(dmData.text).html);
dmItem.find('.post-info-time')
.attr('title', timeSincePost(dmData.time))
.find('span:last')
.text(timeGmtToText(dmData.time))
;
return dmItem;
}
// format dmdata (returned by getdirectmsgs) to display in conversation thread
function postToElemDM(dmData, localUser, remoteUser) {
var senderAlias = (dmData.from && dmData.from.length && dmData.from.charCodeAt(0))
@ -305,7 +274,7 @@ function postToElemDM(dmData, localUser, remoteUser) { @@ -305,7 +274,7 @@ function postToElemDM(dmData, localUser, remoteUser) {
.text(timeGmtToText(dmData.time))
;
setPostInfoSent(senderAlias, dmData.k, elem.find('.post-info-sent'));
elem.find('.post-text').html(htmlFormatMsg(dmData.text).html);
fillElemWithTxt(elem.find('.post-text'), dmData.text);
return elem;
}
@ -605,10 +574,8 @@ function htmlFormatMsg(msg, opt) { @@ -605,10 +574,8 @@ function htmlFormatMsg(msg, opt) {
return msg.str;
}
if (!msg) {
console.warn('htmlFormatMsg() error: input string is empty');
if (!msg)
return {html: '', mentions: []};
}
if (opt && opt.markout)
var markoutOpt = opt.markout;
@ -660,36 +627,33 @@ function htmlFormatMsg(msg, opt) { @@ -660,36 +627,33 @@ function htmlFormatMsg(msg, opt) {
+ '</samp><br>'
);
} else {
if (getSubStrEnd(msg.str, i + 1, whiteSpacesUrl, false, '') < k) // use only first word as href target, others drop silently
k = getSubStrEnd(msg.str, i + 1, whiteSpacesUrl, false, '');
if ((x = getSubStrEnd(msg.str, i + 1, whiteSpacesUrl, false, '')) < k) // use only first word as href target, others drop silently
k = x;
linkName = applyHtml( // we're handling markup inside [] of []()
markout(markout(markout(markout(
{str: linkName, htmlEntities: msg.htmlEntities},
markoutOpt, '*', 'b'), // bold
markoutOpt, '~', 'i'), // italic
markoutOpt, '_', 'u'), // underlined
markoutOpt, '-', 's') // striketrough
)
.replace(/&(?!lt;|gt;)/g, '&amp;');
if (markoutOpt === 'apply') {
msg = msgAddHtmlEntity(msg, j - 1, getSubStrEnd(msg.str, k + 1, ')', true, '') + 2,
newHtmlEntityLink(_htmlFormatMsgLinkTemplateExternal,
proxyURL(msg.str.slice(i, k + 1)),
applyHtml( // we're trying markup inside [] of []()
markout(markout(markout(markout(
{str: linkName, htmlEntities: msg.htmlEntities},
markoutOpt, '*', 'b'), // bold
markoutOpt, '~', 'i'), // italic
markoutOpt, '_', 'u'), // underlined
markoutOpt, '-', 's') // striketrough
)
.replace(/&(?!lt;|gt;)/g, '&amp;')
)
);
if (msg.str.slice(i, i + 6).toLowerCase() === 'twist:' && msg.str[i + 17] === '='
&& getSubStrStart(msg.str, i + 16, stopCharsRightHashtags, false, '') === i + 6)
msg = msgAddHtmlEntity(msg, j - 1, getSubStrEnd(msg.str, k + 1, ')', true, '') + 2,
newHtmlEntityLink(twister.tmpl.linkShortened,
msg.str.slice(i, i + 18), linkName)
);
else
msg = msgAddHtmlEntity(msg, j - 1, getSubStrEnd(msg.str, k + 1, ')', true, '') + 2,
newHtmlEntityLink(_htmlFormatMsgLinkTemplateExternal,
proxyURL(msg.str.slice(i, k + 1)), linkName)
);
} else { // markoutOpt === 'clear' so we're clearing markup
str = msg.str.slice(i, k + 1);
msg = msgAddHtmlEntity(msg, j - 1, getSubStrEnd(msg.str, k + 1, ')', true, '') + 2,
applyHtml( // we're trying to clear markup inside [] of []()
markout(markout(markout(markout(
{str: linkName, htmlEntities: msg.htmlEntities},
markoutOpt, '*', 'b'), // bold
markoutOpt, '~', 'i'), // italic
markoutOpt, '_', 'u'), // underlined
markoutOpt, '-', 's') // striketrough
)
.replace(/&(?!lt;|gt;)/g, '&amp;')
);
linkName);
// here we put link target as plain text to handle it usual way (search http[s]:// and so on)
i = msg.i + 1
msg.str = msg.str.slice(0, i) + ' ' + str + msg.str.slice(i);
@ -726,6 +690,12 @@ function htmlFormatMsg(msg, opt) { @@ -726,6 +690,12 @@ function htmlFormatMsg(msg, opt) {
i = msg.i;
}
}
} else if (msg.str.slice(i, i + 6).toLowerCase() === 'twist:' && msg.str[i + 17] === '='
&& getSubStrStart(msg.str, i + 16, stopCharsRightHashtags, false, '') === i + 6) {
str = msg.str.slice(i, i + 18);
msg = msgAddHtmlEntity(msg, i, i + str.length,
newHtmlEntityLink(twister.tmpl.linkShortened, str, str));
i = msg.i;
}
}

695
js/twister_io.js

@ -10,10 +10,10 @@ @@ -10,10 +10,10 @@
function twisterRpc(method, params, resultFunc, resultArg, errorFunc, errorArg) {
// removing hardcoded username from javascript: please use url http://user:pwd@localhost:28332 instead
//var foo = new $.JsonRpcClient({ ajaxUrl: '/', username: 'user', password: 'pwd'});
var foo = new $.JsonRpcClient({ ajaxUrl: window.location.pathname.replace(/[^\/]*$/, '') });
var foo = new $.JsonRpcClient({ajaxUrl: window.location.pathname.replace(/[^\/]*$/, '')});
foo.call(method, params,
function(ret) { resultFunc(resultArg, ret); },
function(ret) { if(ret != null) errorFunc(errorArg, ret); }
function(ret) {resultFunc(resultArg, ret);},
function(ret) {if (ret != null) errorFunc(errorArg, ret);} // FIXME why only if "(ret != null)"?
);
}
@ -36,73 +36,72 @@ var _maxDhtgets = 5; @@ -36,73 +36,72 @@ var _maxDhtgets = 5;
var _queuedDhtgets = [];
// private function to define a key in _dhtgetPendingMap
function _dhtgetLocator(username, resource, multi) {
return username+";"+resource+";"+multi;
function _dhtgetLocator(peerAlias, resource, multi) {
return peerAlias + ';' + resource + ';' + multi;
}
function _dhtgetAddPending(locator, cbFunc, cbArg)
{
if( !(locator in _dhtgetPendingMap) ) {
function _dhtgetAddPending(locator, cbFunc, cbReq) {
if (!_dhtgetPendingMap[locator]) {
_dhtgetPendingMap[locator] = [];
}
_dhtgetPendingMap[locator].push( {cbFunc:cbFunc, cbArg:cbArg} );
_dhtgetPendingMap[locator].push({cbFunc: cbFunc, cbReq: cbReq});
}
function _dhtgetProcessPending(locator, multi, ret)
{
if( locator in _dhtgetPendingMap ) {
for( var i = 0; i < _dhtgetPendingMap[locator].length; i++) {
function _dhtgetProcessPending(locator, multi, ret) {
if (_dhtgetPendingMap[locator]) {
for (var i = 0; i < _dhtgetPendingMap[locator].length; i++) {
var cbFunc = _dhtgetPendingMap[locator][i].cbFunc;
var cbArg = _dhtgetPendingMap[locator][i].cbArg;
var cbReq = _dhtgetPendingMap[locator][i].cbReq;
if( multi == 's' ) {
if( ret[0] != undefined ) {
cbFunc(cbArg, ret[0]["p"]["v"], ret);
if (multi === 'url') {
cbFunc(cbReq, ret); // here is decodeshorturl case
} else if (multi === 's') {
if (typeof ret[0] !== 'undefined') {
cbFunc(cbReq, ret[0].p.v, ret);
} else {
cbFunc(cbArg, null);
cbFunc(cbReq);
}
} else {
var multiret = [];
for (var j = 0; j < ret.length; j++) {
multiret.push(ret[j]["p"]["v"]);
multiret.push(ret[j].p.v);
}
cbFunc(cbArg, multiret, ret);
cbFunc(cbReq, multiret, ret);
}
}
delete _dhtgetPendingMap[locator];
} else {
console.log("warning: _dhtgetProcessPending with unknown locator "+locator);
console.warn('_dhtgetProcessPending(): unknown locator ' + locator);
}
}
function _dhtgetAbortPending(locator)
{
if( locator in _dhtgetPendingMap ) {
for( var i = 0; i < _dhtgetPendingMap[locator].length; i++) {
function _dhtgetAbortPending(locator) {
if (_dhtgetPendingMap[locator]) {
for (var i = 0; i < _dhtgetPendingMap[locator].length; i++) {
var cbFunc = _dhtgetPendingMap[locator][i].cbFunc;
var cbArg = _dhtgetPendingMap[locator][i].cbArg;
cbFunc(cbArg, null);
var cbReq = _dhtgetPendingMap[locator][i].cbReq;
cbFunc(cbReq);
}
delete _dhtgetPendingMap[locator];
} else {
console.log("warning: _dhtgetAbortPending with unknown locator "+locator);
console.warn('_dhtgetAbortPending(): unknown locator ' + locator);
}
}
// get data from dht resource
// the value ["v"] is extracted from response and returned to callback
// null is passed to callback in case of an error
function dhtget( username, resource, multi, cbFunc, cbArg, timeoutArgs ) {
//console.log('dhtget '+username+' '+resource+' '+multi);
var locator = _dhtgetLocator(username, resource, multi);
if( locator in _dhtgetPendingMap) {
_dhtgetAddPending(locator, cbFunc, cbArg);
function dhtget(peerAlias, resource, multi, cbFunc, cbReq, timeoutArgs) {
//console.log('dhtget ' + peerAlias + ' ' + resource + ' ' + multi);
var locator = _dhtgetLocator(peerAlias, resource, multi);
if (_dhtgetPendingMap[locator]) {
_dhtgetAddPending(locator, cbFunc, cbReq);
} else {
_dhtgetAddPending(locator, cbFunc, cbArg);
_dhtgetAddPending(locator, cbFunc, cbReq);
// limit the number of simultaneous dhtgets.
// this should leave some sockets for other non-blocking daemon requests.
if( _dhtgetsInProgress < _maxDhtgets ) {
_dhtgetInternal( username, resource, multi, timeoutArgs );
if (_dhtgetsInProgress < _maxDhtgets) {
_dhtgetInternal(peerAlias, resource, multi, timeoutArgs);
} else {
// just queue the locator. it will be unqueue when some dhtget completes.
_queuedDhtgets.push(locator);
@ -110,204 +109,265 @@ function dhtget( username, resource, multi, cbFunc, cbArg, timeoutArgs ) { @@ -110,204 +109,265 @@ function dhtget( username, resource, multi, cbFunc, cbArg, timeoutArgs ) {
}
}
function _dhtgetInternal( username, resource, multi, timeoutArgs ) {
var locator = _dhtgetLocator(username, resource, multi);
// decode shortened url
// the expanded url is returned to callback
// null is passed to callback in case of an error
function decodeShortURI(locator, cbFunc, cbReq, timeoutArgs) {
if (!locator) return;
if (parseInt(twisterVersion) < 93500) {
console.warn('can\'t fetch URI "' + req + '": daemon is obsolete, version 0.9.35 or higher is required');
return;
}
if (_dhtgetPendingMap[locator]) {
_dhtgetAddPending(locator, cbFunc, cbReq);
} else {
_dhtgetAddPending(locator, cbFunc, cbReq);
// limit the number of simultaneous decodeshorturl's and dhtgets.
// this should leave some sockets for other non-blocking daemon requests.
if (_dhtgetsInProgress < _maxDhtgets) {
_decodeshorturlInternal(locator, timeoutArgs);
} else {
// just queue the locator. it will be unqueue when some dhtget completes.
_queuedDhtgets.push(locator);
}
}
}
function _dhtgetInternal(peerAlias, resource, multi, timeoutArgs) {
var locator = _dhtgetLocator(peerAlias, resource, multi);
_dhtgetsInProgress++;
argsList = [peerAlias, resource, multi];
if (typeof timeoutArgs !== 'undefined') {
argsList = argsList.concat(timeoutArgs);
}
twisterRpc('dhtget', argsList,
function(req, ret) {
_dhtgetsInProgress--;
_dhtgetProcessPending(req.locator, req.multi, ret);
_dhtgetDequeue();
}, {locator: locator, multi: multi},
function(req, ret) {
console.warn('RPC "dhtget" error: ' + (ret && ret.message ? ret.message : ret));
_dhtgetsInProgress--;
_dhtgetAbortPending(req);
_dhtgetDequeue();
}, locator
);
}
function _decodeshorturlInternal(locator, timeoutArgs) {
_dhtgetsInProgress++;
argsList = [username,resource,multi];
if( typeof timeoutArgs !== 'undefined' ) {
argsList = [locator];
if (typeof timeoutArgs !== 'undefined') {
argsList = argsList.concat(timeoutArgs);
}
twisterRpc("dhtget", argsList,
function(args, ret) {
_dhtgetsInProgress--;
_dhtgetProcessPending(args.locator, args.multi, ret);
_dhtgetDequeue();
}, {locator:locator,multi:multi},
function(cbArg, ret) {
console.log("ajax error:" + ret);
_dhtgetsInProgress--;
_dhtgetAbortPending(locator);
_dhtgetDequeue();
}, locator);
twisterRpc('decodeshorturl', argsList,
function(req, ret) {
_dhtgetsInProgress--;
_dhtgetProcessPending(req, 'url', ret);
_dhtgetDequeue();
}, locator,
function(req, ret) {
console.warn('RPC "decodeshorturl" error: ' + (ret && ret.message ? ret.message : ret));
_dhtgetsInProgress--;
_dhtgetAbortPending(req);
_dhtgetDequeue();
}, locator
);
}
function _dhtgetDequeue() {
if( _queuedDhtgets.length ) {
var locatorSplit = _queuedDhtgets.pop().split(";");
_dhtgetInternal(locatorSplit[0], locatorSplit[1], locatorSplit[2]);
if (_queuedDhtgets.length) {
var locator = _queuedDhtgets.pop();
var locatorSplit = locator.split(';');
if (locatorSplit.length === 3) {
_dhtgetInternal(locatorSplit[0], locatorSplit[1], locatorSplit[2]);
} else {
_decodeshorturlInternal( locator )
}
}
}
// removes queued dhtgets (requests that have not been made to the daemon)
// this is used by user search dropdown to discard old users we are not interested anymore
function removeUserFromDhtgetQueue(username) {
var resources = ["profile","avatar"]
function removeUserFromDhtgetQueue(peerAlias) {
var resources = ['profile', 'avatar']
for (var i = 0; i < resources.length; i++) {
var locator = _dhtgetLocator(username,resources[i],"s");
var locator = _dhtgetLocator(peerAlias, resources[i], 's');
var locatorIndex = _queuedDhtgets.indexOf(locator);
if( locatorIndex > -1 ) {
_queuedDhtgets.splice(locatorIndex,1);
if (locatorIndex > -1) {
_queuedDhtgets.splice(locatorIndex, 1);
delete _dhtgetPendingMap[locator];
}
}
}
function removeUsersFromDhtgetQueue(users) {
for (var i = 0; i < users.length; i++ ) {
removeUserFromDhtgetQueue( users[i] );
for (var i = 0; i < users.length; i++) {
removeUserFromDhtgetQueue(users[i]);
}
}
// store value at the dht resource
function dhtput( username, resource, multi, value, sig_user, seq, cbFunc, cbArg ) {
twisterRpc("dhtput", [username,resource,multi, value, sig_user, seq],
function(args, ret) {
if( args.cbFunc )
args.cbFunc(args.cbArg, true);
}, {cbFunc:cbFunc, cbArg:cbArg},
function(args, ret) {
console.log("ajax error:" + ret);
if( args.cbFunc )
args.cbFunc(args.cbArg, false);
}, cbArg);
}
// get something from profile and store it in item.text or do callback
function getProfileResource( username, resource, item, cbFunc, cbArg ){
var profile = undefined;
if( username in _profileMap ) {
profile = _profileMap[username];
function dhtput(peerAlias, resource, multi, value, sig_user, seq, cbFunc, cbReq) {
twisterRpc('dhtput', [peerAlias, resource, multi, value, sig_user, seq],
function(req, ret) {
if (req.cbFunc)
req.cbFunc(req.cbReq, true);
}, {cbFunc: cbFunc, cbReq: cbReq},
function(req, ret) {
console.warn('RPC "dhtput" error: ' + (ret && ret.message ? ret.message : ret));
if (req.cbFunc)
req.cbFunc(req.cbReq, false);
}, {cbFunc: cbFunc, cbReq: cbReq}
);
}
// get something from profile and store it in elem.text or do callback
function getProfileResource(peerAlias, resource, elem, cbFunc, cbReq) {
var profile;
if (_profileMap[peerAlias]) {
profile = _profileMap[peerAlias];
} else {
profile = _getResourceFromStorage("profile:" + username);
profile = _getResourceFromStorage('profile:' + peerAlias);
}
if( profile ) {
_profileMap[username] = profile;
if( item )
item.text(profile[resource]);
if( cbFunc )
cbFunc(cbArg, profile[resource]);
if (profile) {
_profileMap[peerAlias] = profile;
if (elem)
elem.text(profile[resource]);
if (cbFunc)
cbFunc(cbReq, profile[resource]);
} else {
dhtget( username, "profile", "s",
function(args, profile) {
if( profile ) {
_profileMap[args.username] = profile;
_putResourceIntoStorage("profile:" + username, profile);
if( args.item )
args.item.text(profile[resource]);
if( args.cbFunc )
args.cbFunc(args.cbArg, profile[resource]);
} else {
if( args.cbFunc )
args.cbFunc(args.cbArg, null);
}
}, {username:username,item:item,cbFunc:cbFunc,cbArg:cbArg});
dhtget(peerAlias, 'profile', 's',
function(req, profile) {
if (profile) {
_profileMap[req.peerAlias] = profile;
_putResourceIntoStorage('profile:' + peerAlias, profile);
if (req.elem)
req.elem.text(profile[resource]);
if (req.cbFunc)
req.cbFunc(req.cbReq, profile[resource]);
} else {
if (req.cbFunc)
req.cbFunc(req.cbReq);
}
}, {peerAlias: peerAlias, elem: elem, cbFunc: cbFunc, cbReq: cbReq}
);
}
}
// get fullname and store it in item.text
function getFullname( username, item ){
// Set the username first in case the profile has no fullname
item.text(username);
getProfileResource( username, "fullname", undefined,
function(args, value) {
if( value ) {
value.replace(/^\s+|\s+$/g, '');
if( value.length )
args.item.text(value);
}
}, {item: item} );
if (typeof(twisterFollowingO) !== 'undefined' &&
($.Options.isFollowingMe.val === 'everywhere' || item.hasClass('profile-name'))) {
if (twisterFollowingO.knownFollowers.indexOf(username) > -1) {
item.addClass('isFollowing');
item.attr("title", polyglot.t("follows you"));
} else if (twisterFollowingO.notFollowers.indexOf(username) === -1) {
if (typeof(twisterFollowingO.followingsFollowings[username]) !== 'undefined' &&
typeof(twisterFollowingO.followingsFollowings[username]["following"]) !== 'undefined') {
if (twisterFollowingO.followingsFollowings[username]["following"].indexOf(defaultScreenName) > -1) {
twisterFollowingO.knownFollowers.push(username);
twisterFollowingO.save();
item.addClass('isFollowing');
item.attr("title", polyglot.t("follows you"));
// get fullname and store it in elem.text
function getFullname(peerAlias, elem) {
elem.text(peerAlias); // fallback: set the peerAlias first in case the profile has no fullname
getProfileResource(peerAlias, 'fullname', undefined,
function(req, name) {
if (name && (name = name.trim()))
req.elem.text(name);
if (typeof twisterFollowingO !== 'undefined' && // FIXME delete this check when you fix client init sequence
($.Options.isFollowingMe.val === 'everywhere' || req.elem.hasClass('profile-name'))) {
// here we try to detect if peer follows us and then display it
if (twisterFollowingO.knownFollowers.indexOf(req.peerAlias) > -1) {
req.elem.addClass('isFollowing');
req.elem.attr('title', polyglot.t('follows you'));
} else if (twisterFollowingO.notFollowers.indexOf(req.peerAlias) === -1) {
if (twisterFollowingO.followingsFollowings[req.peerAlias] &&
twisterFollowingO.followingsFollowings[req.peerAlias].following) {
if (twisterFollowingO.followingsFollowings[req.peerAlias].following.indexOf(defaultScreenName) > -1) {
if (twisterFollowingO.knownFollowers.indexOf(req.peerAlias) === -1) {
twisterFollowingO.knownFollowers.push(req.peerAlias);
twisterFollowingO.save();
addPeerToFollowersList(getElem('.followers-modal .followers-list'), req.peerAlias, true);
$('.open-followers').attr('title', twisterFollowingO.knownFollowers.length.toString());
}
req.elem.addClass('isFollowing');
req.elem.attr('title', polyglot.t('follows you'));
}
} else {
loadFollowingFromDht(req.peerAlias, 1, [], 0,
function (req, following, seqNum) {
if (following.indexOf(defaultScreenName) > -1) {
if (twisterFollowingO.knownFollowers.indexOf(req.peerAlias) === -1) {
twisterFollowingO.knownFollowers.push(req.peerAlias);
addPeerToFollowersList(getElem('.followers-modal .followers-list'), req.peerAlias, true);
$('.open-followers').attr('title', twisterFollowingO.knownFollowers.length.toString());
}
req.elem.addClass('isFollowing');
req.elem.attr('title', polyglot.t('follows you'));
} else if (twisterFollowingO.notFollowers.indexOf(req.peerAlias) === -1)
twisterFollowingO.notFollowers.push(req.peerAlias);
twisterFollowingO.save();
}, {elem: req.elem, peerAlias: req.peerAlias}
);
}
}
} else {
loadFollowingFromDht(username, 1, [], 0, function (args, following, seqNum) {
if (following.indexOf(args.user) > -1) {
item.addClass('isFollowing');
item.attr("title", polyglot.t("follows you"));
if (twisterFollowingO.knownFollowers.indexOf(args.username) < 0)
twisterFollowingO.knownFollowers.push(args.username);
} else
twisterFollowingO.notFollowers.push(args.username);
twisterFollowingO.save();
}, {"user": defaultScreenName, "item": item, "username": username});
}
}
$(".open-followers").attr("title", twisterFollowingO.knownFollowers.length.toString());
}
}, {elem: elem, peerAlias: peerAlias}
);
}
// get bio, format it as post message and store result to elem
function getBioToElem(peerAlias, elem) {
getProfileResource(peerAlias, 'bio', undefined,
function (req, ret) {
req.elem.html(htmlFormatMsg(ret).html);
}, {elem: elem}
);
getProfileResource(peerAlias, 'bio', undefined, fillElemWithTxt, elem);
}
// get tox address and store it in item.text
function getTox( username, item ){
getProfileResource( username, "tox", false, function(item, text){
//item.empty();
if(text) {
item.attr('href', 'tox:'+text);
item.next().attr('data', text).attr('title', 'Copy to clipboard');
item.parent().css('display','inline-block').parent().show();
}
}, item);
// get tox address and store it in elem.text
function getTox(peerAlias, elem) {
getProfileResource(peerAlias, 'tox', false,
function(elem, val) {
if (val) {
elem.attr('href', 'tox:' + val);
elem.next().attr('data', val).attr('title', 'Copy to clipboard');
elem.parent().css('display', 'inline-block').parent().show();
}
}, elem
);
}
// get bitmessage address and store it in item.text
function getBitmessage( username, item ){
getProfileResource( username, "bitmessage", false, function(item, text){
//item.empty();
if(text) {
item.attr('href', 'bitmsg:'+text+'?action=add&label='+username);
item.next().attr('data', text).attr('title', 'Copy to clipboard');
item.parent().css('display','inline-block').parent().show();
}
}, item);
// get bitmessage address and store it in elem.text
function getBitmessage(peerAlias, elem) {
getProfileResource(peerAlias, 'bitmessage', false,
function(elem, val) {
if (val) {
elem.attr('href', 'bitmsg:' + val + '?action=add&label=' + peerAlias);
elem.next().attr('data', val).attr('title', 'Copy to clipboard');
elem.parent().css('display', 'inline-block').parent().show();
}
}, elem
);
}
// get location and store it in item.text
function getLocation( username, item ){
getProfileResource( username, "location", item);
// get location and store it in elem.text
function getLocation(peerAlias, elem) {
getProfileResource(peerAlias, 'location', elem);
}
// get location and store it in item.text
function getWebpage( username, item ){
getProfileResource( username, "url", item,
function(args, val) {
if(typeof(val) !== 'undefined') {
if (val.indexOf("://") < 0) {
val = "http://" + val;
}
args.item.attr("href", val);
}
}, {item:item} );
// get location and store it in elem.text
function getWebpage(peerAlias, elem) {
getProfileResource(peerAlias, 'url', elem,
function(elem, val) {
if (typeof(val) !== 'undefined') {
if (val.indexOf('://') < 0) {
val = 'http://' + val;
}
elem.attr('href', val);
}
}, elem
);
}
function getGroupChatName( groupalias, item ){
twisterRpc("getgroupinfo", [groupalias],
function(args, ret) {
args.item.text(ret["description"]);
}, {item:item},
function(args, ret) {
args.item.text("getgroupinfo error");
}, {item:item});
function getGroupChatName(groupAlias, elem) {
twisterRpc('getgroupinfo', [groupAlias],
function(elem, ret) {
elem.text(ret.description);
}, elem,
function(req, ret) {
console.warn('RPC "getgroupinfo" error: ' + (ret && ret.message ? ret.message : ret));
req.elem.text(req.groupAlias);
}, {elem: elem, groupAlias: groupAlias}
);
}
// we must cache avatar results to disk to lower bandwidth on
@ -315,11 +375,12 @@ function getGroupChatName( groupalias, item ){ @@ -315,11 +375,12 @@ function getGroupChatName( groupalias, item ){
// data will only cause new requests to fail.
function _getResourceFromStorage(locator) {
var storage = $.localStorage;
if( storage.isSet(locator) ) {
if (storage.isSet(locator)) {
var storedResource = storage.get(locator);
var curTime = new Date().getTime() / 1000;
// avatar is downloaded once per day
if( storedResource.time + 3600*24 > curTime ) {
// avatar is downloaded once per day FIXME why once per day? what about profiles?
// FIXME need to check what type of data is requested and what time is allowed for it
if (storedResource.time + 86400 > curTime) { // 3600 * 24
return storedResource.data;
}
}
@ -327,139 +388,199 @@ function _getResourceFromStorage(locator) { @@ -327,139 +388,199 @@ function _getResourceFromStorage(locator) {
}
function _putResourceIntoStorage(locator, data) {
$.localStorage.set(locator, {
time: Math.trunc(new Date().getTime() / 1000),
data: data
});
}
function cleanupStorage() {
var curTime = new Date().getTime() / 1000;
var storedResource = {time: curTime, data: data};
var storage = $.localStorage, keys = storage.keys(), item = '';
var delAvatars = delProfiles = 0;
for (var i = 0; i < keys.length; i++) {
item = keys[i];
// FIXME need to decide what time for type of data is allowed
if (item.substr(0, 7) === 'avatar:') {
if (storage.get(item).time + 86400 < curTime) { // 3600 * 24 hours
storage.remove(item);
delAvatars++;
//console.log('local storage item \'' + item + '\' was too old, deleted');
}
} else if (item.substr(0, 8) === 'profile:') {
if (storage.get(item).time + 86400 < curTime) { // 3600 * 24 hours
storage.remove(item);
delProfiles++;
//console.log('local storage item \'' + item + '\' was too old, deleted');
}
}
}
var storage = $.localStorage;
storage.set(locator, storedResource);
console.log('cleaning of storage is completed for ' + (new Date().getTime() / 1000 - curTime) + 's');
if (delAvatars) console.log(' ' + delAvatars + ' cached avatars was too old, deleted');
if (delProfiles) console.log(' ' + delProfiles + ' cached profiles was too old, deleted');
console.log(' ' + 'there was ' + i + ' items in total, now ' + (i - delAvatars - delProfiles));
}
// get avatar and set it in img.attr("src")
// TODO rename to getAvatarImgToELem(), move nin theme related stuff to nin's theme_option.js
function getAvatar( username, img ){
function getAvatar(peerAlias, img) {
if (!img.length)
return;
if (username === 'nobody') {
if (peerAlias === 'nobody') {
img.attr('src', ($.Options.theme.val === 'nin') ?
'theme_nin/img/tornado_avatar.png' : 'img/tornado_avatar.png');
return;
}
if( username in _avatarMap ) {
//img.attr('src', "data:image/jpg;base64,"+avatarMap[username]);
img.attr('src', _avatarMap[username]);
if (_avatarMap[peerAlias]) {
//img.attr('src', 'data:image/jpg;base64,'+avatarMap[peerAlias]);
img.attr('src', _avatarMap[peerAlias]);
} else {
var data = _getResourceFromStorage("avatar:" + username);
if( data ) {
_avatarMap[username] = data;
var data = _getResourceFromStorage('avatar:' + peerAlias);
if (data) {
switch (data.substr(0, 4)) {
case 'jpg/':
data = 'data:image/jpeg;base64,/9j/' + window.btoa(data.slice(4));
break;
case 'png/':
data = 'data:image/png;base64,' + window.btoa(data.slice(4));
break;
case 'gif/':
data = 'data:image/gif;base64,' + window.btoa(data.slice(4));
break;
}
_avatarMap[peerAlias] = data;
img.attr('src', data);
} else {
dhtget( username, "avatar", "s",
function(args, imagedata) {
if( imagedata && imagedata.length ) {
_avatarMap[args.username] = imagedata;
_putResourceIntoStorage("avatar:" + username, imagedata);
args.img.attr('src', imagedata);
}
}, {username:username,img:img} );
dhtget(peerAlias, 'avatar', 's',
function(req, imagedata) {
if (imagedata && imagedata.length) {
_avatarMap[req.peerAlias] = imagedata;
if (imagedata !== 'img/genericPerson.png') {
if (imagedata.substr(0, 27) === 'data:image/jpeg;base64,/9j/')
_putResourceIntoStorage('avatar:' + peerAlias, 'jpg/' + window.atob(imagedata.slice(27)));
else {
var s = imagedata.substr(0, 22);
if (s === 'data:image/png;base64,' || s === 'data:image/gif;base64,')
_putResourceIntoStorage('avatar:' + peerAlias, imagedata.substr(11, 3) + '/' + window.atob(imagedata.slice(22)));
else
_putResourceIntoStorage('avatar:' + peerAlias, imagedata);
}
}
req.img.attr('src', imagedata);
}
}, {peerAlias: peerAlias, img: img}
);
}
}
}
function clearAvatarAndProfileCache(username) {
function clearAvatarAndProfileCache(peerAlias) {
var storage = $.localStorage;
storage.remove("avatar:" + username);
storage.remove("profile:" + username);
if( username in _avatarMap ) {
delete _avatarMap[username];
storage.remove('avatar:' + peerAlias);
storage.remove('profile:' + peerAlias);
if (_avatarMap[peerAlias]) {
delete _avatarMap[peerAlias];
}
if( username in _profileMap ) {
delete _profileMap[username];
if (_profileMap[peerAlias]) {
delete _profileMap[peerAlias];
}
}
// get estimative for number of followers (use known peers of torrent tracker)
function getFollowers( username, item ) {
dhtget( username, "tracker", "m",
function(args, ret) {
if( ret && ret.length && ret[0]["followers"] ) {
args.item.text(ret[0]["followers"])
}
}, {username:username,item:item} );
}
function getPostsCount( username, item ) {
dhtget( username, "status", "s",
function(args, v) {
var count = 0;
if( v && v["userpost"] ) {
count = v["userpost"]["k"]+1;
}
var oldCount = parseInt(args.item.text());
if( !oldCount || count > oldCount ) {
args.item.text(count);
}
if( username == defaultScreenName && count ) {
incLastPostId( v["userpost"]["k"] );
}
}, {username:username,item:item} );
}
function getPostMaxAvailability(username, k, cbFunc, cbArg) {
twisterRpc("getpiecemaxseen", [username,k],
function(args, ret) {
args.cbFunc(args.cbArg, ret);
}, {cbFunc:cbFunc, cbArg:cbArg},
function(args, ret) {
console.log("getPostAvailability error");
}, {cbFunc:cbFunc, cbArg:cbArg});
}
function checkPubkeyExists(username, cbFunc, cbArg) {
function getFollowers(peerAlias, elem) {
dhtget(peerAlias, 'tracker', 'm',
function(elem, ret) {
if (ret && ret.length && ret[0].followers) {
elem.text(ret[0].followers)
}
}, elem
);
}
function getPostsCount(peerAlias, elem) {
dhtget(peerAlias, 'status', 's',
function(req, v) {
var count = 0;
if (v && v.userpost) {
count = v.userpost.k + 1;
}
var oldCount = parseInt(req.elem.text());
if (!oldCount || count > oldCount) {
req.elem.text(count);
}
if (peerAlias === defaultScreenName && count) {
incLastPostId(v.userpost.k);
}
}, {peerAlias: peerAlias, elem: elem}
);
}
function getPostMaxAvailability(peerAlias, k, cbFunc, cbReq) {
twisterRpc('getpiecemaxseen', [peerAlias, k],
function(req, ret) {
req.cbFunc(req.cbReq, ret);
}, {cbFunc: cbFunc, cbReq: cbReq},
function(req, ret) {
console.warn('RPC "getpiecemaxseen" error: ' + (ret && ret.message ? ret.message : ret));
}
);
}
function checkPubkeyExists(peerAlias, cbFunc, cbReq) {
// pubkey is checked in block chain db.
// so only accepted registrations are reported (local wallet users are not)
twisterRpc("dumppubkey", [username],
function(args, ret) {
args.cbFunc(args.cbArg, ret.length > 0);
}, {cbFunc:cbFunc, cbArg:cbArg},
function(args, ret) {
alert(polyglot.t("error_connecting_to_daemon"));
}, {cbFunc:cbFunc, cbArg:cbArg});
twisterRpc('dumppubkey', [peerAlias],
function(req, ret) {
req.cbFunc(req.cbReq, ret.length > 0);
}, {cbFunc: cbFunc, cbReq: cbReq},
function(req, ret) {
console.warn('RPC "dumppubkey" error: ' + (ret && ret.message ? ret.message : ret));
alert(polyglot.t('error_connecting_to_daemon'));
}
);
}
// pubkey is obtained from block chain db.
// so only accepted registrations are reported (local wallet users are not)
// cbFunc is called as cbFunc(cbArg, pubkey)
// cbFunc is called as cbFunc(cbReq, pubkey)
// if user doesn't exist then pubkey.length == 0
function dumpPubkey(username, cbFunc, cbArg) {
if( username in _pubkeyMap ) {
if( cbFunc )
cbFunc(cbArg, _pubkeyMap[username]);
function dumpPubkey(peerAlias, cbFunc, cbReq) {
if (_pubkeyMap[peerAlias]) {
if (cbFunc)
cbFunc(cbReq, _pubkeyMap[peerAlias]);
} else {
twisterRpc("dumppubkey", [username],
function(args, ret) {
if( ret.length > 0 ) {
_pubkeyMap[username] = ret;
}
args.cbFunc(args.cbArg, ret);
}, {cbFunc:cbFunc, cbArg:cbArg},
function(args, ret) {
alert(polyglot.t("error_connecting_to_daemon"));
}, {cbFunc:cbFunc, cbArg:cbArg});
twisterRpc('dumppubkey', [peerAlias],
function (req, ret) {
if (ret.length > 0) {
_pubkeyMap[peerAlias] = ret;
}
if (req.cbFunc) {
req.cbFunc(req.cbReq, ret);
}
}, {cbFunc: cbFunc, cbReq: cbReq},
function (req, ret) {
console.warn('RPC "dumppubkey" error: ' + (ret && ret.message ? ret.message : ret));
alert(polyglot.t('error_connecting_to_daemon'));
}
);
}
}
// privkey is obtained from wallet db
// so privkey is returned even for unsent transactions
function dumpPrivkey(username, cbFunc, cbArg) {
twisterRpc("dumpprivkey", [username],
function(args, ret) {
args.cbFunc(args.cbArg, ret);
}, {cbFunc:cbFunc, cbArg:cbArg},
function(args, ret) {
args.cbFunc(args.cbArg, "");
console.log("dumpprivkey: user unknown");
}, {cbFunc:cbFunc, cbArg:cbArg});
function dumpPrivkey(peerAlias, cbFunc, cbReq) {
twisterRpc('dumpprivkey', [peerAlias],
function(req, ret) {
req.cbFunc(req.cbReq, ret);
}, {cbFunc: cbFunc, cbReq: cbReq},
function(req, ret) {
req.cbFunc(req.cbReq, '');
console.warn('user unknown — RPC "dumppubkey" error: ' + (ret && ret.message ? ret.message : ret));
}, {cbFunc: cbFunc, cbReq: cbReq}
);
}

2
js/twister_network.js

@ -304,7 +304,7 @@ function interfaceNetworkHandlers() { @@ -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: 'confirm_terminate_daemon'}, cbConfirm: exitDaemon}, confirmPopup);
}

8
js/twister_timeline.js

@ -346,11 +346,9 @@ function timelineChangedUser() @@ -346,11 +346,9 @@ function timelineChangedUser()
timelineLoaded = false;
}
function willBeHidden(post){
// posts without 'msg' may be used for metadata like 'url'
// and are not meant to be displayed.
if (typeof(post['userpost']['msg']) === 'undefined' &&
typeof(post['userpost']['rt']) === 'undefined' )
function willBeHidden(post) {
// posts without 'msg' and 'rt.msg' may be used for metadata like 'url' and are not meant to be displayed
if (!post.userpost.msg && (!post.userpost.rt || (post.userpost.rt && !post.userpost.rt.msg)))
return true;
if (post['userpost']['n'] === defaultScreenName)

41
js/twister_user.js

@ -79,7 +79,7 @@ function loadWalletlUsers(cbFunc, cbArg) { @@ -79,7 +79,7 @@ function loadWalletlUsers(cbFunc, cbArg) {
function loadScreenName() {
if( $.localStorage.isSet("defaultScreenName") ) {
defaultScreenName = $.localStorage.get("defaultScreenName");
defaultScreenName = $.localStorage.get("defaultScreenName").toString();
}
}
@ -174,19 +174,6 @@ function sendNewUserTransaction(username, cbFunc) { @@ -174,19 +174,6 @@ function sendNewUserTransaction(username, cbFunc) {
}, {});
}
function importSecretKeypress() {
var secretKey = $(".secret-key-import").val();
var username = $(".username-import").val().toLowerCase();
var $importButton = $(".import-secret-key");
if( secretKey.length == 52 && username.length ) {
$.MAL.enableButton( $importButton );
} else {
$.MAL.disableButton( $importButton );
}
}
function importSecretKeyClick() {
var secretKey = $(".secret-key-import").val();
var username = $(".username-import").val().toLowerCase();
@ -214,8 +201,8 @@ function interfaceCommonLoginHandlers() { @@ -214,8 +201,8 @@ function interfaceCommonLoginHandlers() {
/* must specialize: $( ".create-user").bind( "click", function() { createUserClick( processCreateUser ); } ); */
/* must specialize: $( ".login-created-user").bind( "click", loginCreatedUser ); */
$( ".new-username" ).keyup( newUserNameKeypress );
$( ".secret-key-import" ).keyup( importSecretKeypress );
$( ".username-import" ).keyup( importSecretKeypress );
$('.secret-key-import').on('input', importSecretKeypress);
$('.username-import').on('input', importSecretKeypress);
$( ".import-secret-key").bind( "click", importSecretKeyClick );
}
@ -273,20 +260,18 @@ function saveProfile(e) { @@ -273,20 +260,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: txtMessage,
cbConfirm: $.MAL.enableButton,
cbConfirmReq: $('.submit-changes'),
cbClose: 'cbConfirm'
});
}

15
network.html

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
<script src="js/twister_formatpost.js"></script>
<script src="js/twister_following.js"></script>
<script src="js/twister_newmsgs.js"></script>
<script src="js/twister_actions.js"></script>
<script src="js/polyglot.min.js"></script>
<script src="js/interface_localization.js"></script>
<script src="js/twister_network.js"></script>
@ -35,7 +36,7 @@ @@ -35,7 +36,7 @@
<li class="userMenu-network current selectable_theme theme_original theme_nin"><a class="label" href="network.html">Network</a></li>
<li class="userMenu-profile selectable_theme theme_original theme_nin"><a class="label" href="profile-edit.html">Profile</a></li>
<li class="userMenu-config">
<a class="userMenu-config-dropdown" href="#">
<a class="userMenu-config-dropdown">
<div class="config-menu dialog-modal">
<div class="mini-profile-info selectable_theme theme_original">
<div class="mini-profile-photo"><img src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
@ -44,7 +45,6 @@ @@ -44,7 +45,6 @@
</div>
<a class="dropdown-menu-item" href="options.html">Options</a>
<a class="dropdown-menu-item" href="profile-edit.html">Setup account</a>
<a class="dropdown-menu-item" href="following.html">Following users</a>
<a class="dropdown-menu-item" href="network.html">Network config</a>
<a class="dropdown-menu-item" href="login.html">Change user</a>
</div>
@ -251,12 +251,23 @@ @@ -251,12 +251,23 @@
</div>
</div>
<div id="template-post-textarea-edit-bar">
<div class="post-textarea-edit-bar"></div>
</div>
<div id="template-shorten-uri">
<a class="shorten-uri">shorten URL</a>
</div>
<!-- template for user links in message (open profile modal) -->
<a id="msg-user-link-template" class="open-profile-modal"></a>
<!-- template for user links in message (open profile modal) -->
<a id="external-page-link-template" rel="nofollow" target="_blank"></a>
<!-- template for user links in message (open profile modal) -->
<a id="hashtag-link-template" class="open-hashtag-modal"></a>
<div id="template-link-shortened">
<a class="link-shortened" rel="nofollow" target="_blank"></a>
</div>
<div class="prompt-wrapper">
<div class="modal-header">

6
options.html

@ -33,12 +33,11 @@ @@ -33,12 +33,11 @@
<li class="userMenu-home"><a href="home.html"><span class="selectable_theme theme_original label">Home</span></a></li>
<li class="userMenu-options current"><a class="label" href="options.html">Options</a></li>
<li class="userMenu-config">
<a class="userMenu-config-dropdown" href="#">
<a class="userMenu-config-dropdown">
<div class="config-menu dialog-modal">
<a class="dropdown-menu-item" href="options.html">Options</a>
<a class="dropdown-menu-item" href="network.html">Network config</a>
<a class="dropdown-menu-item" href="profile-edit.html">Setup account</a>
<a class="dropdown-menu-item" href="following.html">Following users</a>
<a class="dropdown-menu-item" href="login.html">Change user</a>
</div>
</a>
@ -462,6 +461,9 @@ @@ -462,6 +461,9 @@
<a id="external-page-link-template" rel="nofollow" target="_blank"></a>
<!-- template for user links in message (open profile modal) -->
<a id="hashtag-link-template" class="open-hashtag-modal"></a>
<div id="template-link-shortened">
<a class="link-shortened" rel="nofollow" target="_blank"></a>
</div>
</div>
<audio id="player"></audio>

7
profile-edit.html

@ -17,6 +17,8 @@ @@ -17,6 +17,8 @@
<script src="js/polyglot.min.js"></script>
<script src="js/interface_localization.js"></script>
<script src="js/twister_user.js"></script>
<script src="js/twister_formatpost.js"></script>
<script src="js/twister_actions.js"></script>
<script src="js/twister_network.js"></script>
<script src="js/twister_following.js"></script>
<script src="js/twister_newmsgs.js"></script>
@ -38,7 +40,7 @@ @@ -38,7 +40,7 @@
<li class="userMenu-network selectable_theme theme_original theme_nin"><a class="label" href="network.html">Network</a></li>
<li class="userMenu-profile selectable_theme theme_original theme_nin current"><a class="label" href="profile-edit.html">Profile</a></li>
<li class="userMenu-config">
<a class="userMenu-config-dropdown" href="#">
<a class="userMenu-config-dropdown">
<div class="config-menu dialog-modal">
<div class="mini-profile-info selectable_theme theme_original">
<div class="mini-profile-photo"><img src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
@ -47,7 +49,6 @@ @@ -47,7 +49,6 @@
</div>
<a class="dropdown-menu-item" href="options.html">Options</a>
<a class="dropdown-menu-item" href="profile-edit.html">Setup account</a>
<a class="dropdown-menu-item" href="following.html">Following users</a>
<a class="dropdown-menu-item" href="network.html">Network config</a>
<a class="dropdown-menu-item" href="login.html">Change user</a>
</div>
@ -67,7 +68,7 @@ @@ -67,7 +68,7 @@
<img class="profile-card-photo forEdition" src="img/genericPerson.png"/>
<input type="text" class="input-name" placeholder="Full name here"/>
<h2></h2>
<input type="text" class="input-description" placeholder="Describe yourself"/>
<textarea class="input-description" placeholder="Describe yourself"></textarea>
<input type="text" class="input-city" placeholder="Location"/>
<input type="text" class="input-website" placeholder="website"/>
<input type="text" class="input-tox" placeholder="Tox address"/>

18
theme_calm/css/profile.css

@ -104,8 +104,8 @@ @@ -104,8 +104,8 @@
{
margin-bottom: 8px;
}
.forEdition .profile-card-main input
{
.forEdition .profile-card-main input, .forEdition .profile-card-main textarea {
display: block;
margin: 0 auto;
background: rgba( 255, 255, 255, .8 );
@ -115,14 +115,16 @@ @@ -115,14 +115,16 @@
text-align: center;
transition: all .2s linear;
}
.forEdition .profile-card-main input:hover
{
.forEdition .profile-card-main input:hover, .forEdition .profile-card-main textarea:hover {
background: rgba( 255, 255, 255, .7 );
}
.forEdition .profile-card-photo:hover{
background: #9096a5;
}
.forEdition .profile-card-main input:focus{
.forEdition .profile-card-main input:focus, .forEdition .profile-card-main textarea:focus {
background: #fff;
color: #4d4d4d;
}
@ -158,11 +160,13 @@ @@ -158,11 +160,13 @@
top: 30px;
right: 20px;
}
.profile-card-main input.input-description
{
.profile-card-main .input-description {
width: 90%;
max-width: 90%;
margin-top: 100px;
}
.input-name
{
font-size: 20px;

227
theme_calm/css/style.css

@ -134,7 +134,7 @@ button:disabled:hover, button.disabled:hover { @@ -134,7 +134,7 @@ button:disabled:hover, button.disabled:hover {
color: rgba(255, 255, 255, .8);
}
button.follow, button.unfollow, .following-list button.private {
button.follow, button.unfollow, .following-own-modal .following-list button.private {
color: rgba( 0, 0, 0, .4 );
background: none;
border: solid 1px rgba( 0, 0, 0, .2 );
@ -142,19 +142,19 @@ button.follow, button.unfollow, .following-list button.private { @@ -142,19 +142,19 @@ button.follow, button.unfollow, .following-list button.private {
font-size: 12px;
}
.following-list .public-following {
.following-own-modal .following-list .public-following {
padding: 4px 16px;
font-size: 12px;
}
.following-list .public-following:hover {
.following-own-modal .following-list .public-following:hover {
color: rgba( 0, 0, 0, .4 );
background: none;
border: solid 1px rgba( 0, 0, 0, .2 );
padding: 3px 15px;
}
.following-list button.private:hover {
.following-own-modal .following-list button.private:hover {
color: #fff;
background: #45474d;
}
@ -668,10 +668,7 @@ input.userMenu-search-field:focus::-ms-input-placeholder { @@ -668,10 +668,7 @@ input.userMenu-search-field:focus::-ms-input-placeholder {
position: relative;
z-index: 2;
}
.following-list .mini-profile-name
{
padding: 5px 5px 5px 5px;
}
.profile-data
{
border-left: none;
@ -704,59 +701,55 @@ input.userMenu-search-field:focus::-ms-input-placeholder { @@ -704,59 +701,55 @@ input.userMenu-search-field:focus::-ms-input-placeholder {
display: block;
font-size: 16px;
}
.mini-profile-actions
{
position: relative;
width: auto;
display: inline-block;
.mini-profile-actions {
position: absolute;
top: 0;
right: 8px;
}
.mini-profile-actions span
{
color: #e18881;
.mini-profile-actions span {
color: rgba(0, 0, 0, .5);
cursor: pointer;
font-size: 14px;
font-size: 12px;
display: inline-block;
width: 85px;
transition: all .2s linear;
position: relative;
z-index: 10;
}
.mini-profile-actions ul
{
.mini-profile-actions span:hover {
color: #768fce;
}
.mini-profile-actions ul {
height: 0;
overflow: hidden;
position: absolute;
z-index: 20;
right: 0;
transition: height .2s linear;
background: #fff;
z-index: 3;
}
.mini-profile-actions:hover span
{
}
.mini-profile-actions:hover span:after
{
}
.mini-profile-actions:hover ul
{
height: 90px;
box-shadow: 0 2px 5px #65686f;
.mini-profile-actions:hover ul {
/*height: ;*/
border: solid 1px rgba(69, 71, 77, .1);
border-right: solid 4px #B2D67B;
box-shadow: 8px 10px 10px 0px rgba(0, 0, 0, .2);
}
.mini-profile-actions ul li
{
.mini-profile-actions ul li {
white-space: nowrap;
color: rgba( 0, 0, 0, .7 );
font-size: 13px;
color: rgba(0, 0, 0, .7);
font-size: 12px;
cursor: pointer;
padding: 5px;
margin: 2px;
padding: 4px 16px 4px 8px;
}
.mini-profile-actions ul li + li
{
margin: 0 2px;
}
.mini-profile-actions:hover ul li:hover
{
background: rgba( 0, 0, 0, .7 );
color: #fff;
.mini-profile-actions ul li:hover {
background: #FCFDFF;
}
.mini-profile-info a:hover
{
text-decoration: none;
@ -803,7 +796,6 @@ input.userMenu-search-field:focus::-ms-input-placeholder { @@ -803,7 +796,6 @@ input.userMenu-search-field:focus::-ms-input-placeholder {
border-radius: 3px;
border: solid 1px rgba(0, 0, 0, .3 );
margin-left: 55px;
margin-bottom: 10px;
padding: 4px;
font-size: 13px;
}
@ -934,6 +926,16 @@ textarea.splited-post { @@ -934,6 +926,16 @@ textarea.splited-post {
height: 35px;
transition: all .6s linear;
}
.post-area-new .post-textarea-edit-bar {
font-size: 11px;
margin: 2px 0;
}
.post-area-new .post-textarea-edit-bar > * {
margin: 2px 4px;
}
.post-area-remaining
{
font-size: 13px;
@ -951,6 +953,64 @@ textarea.splited-post { @@ -951,6 +953,64 @@ textarea.splited-post {
.post .show-more:before {
content: '💭';
}
/* FIXME need to rework and replace all .twister-user to get same vis */
.twister-peer {
margin: 0;
min-height: 72px;
padding: 4px;
border-bottom: solid 1px rgba(69, 71, 77, .1);
border-top: solid 1px rgba(69, 71, 77, .1);
}
.twister-peer + .twister-peer {
border-top: none;
}
.twister-peer .avatar {
float: left;
width: 48px;
height: 48px;
overflow: hidden;
margin: 4px;
}
.twister-peer .avatar img {
width: 48px;
height: auto;
border-radius: 16%;
}
.twister-peer .name, .twister-peer .alias {
color: #768fCE;
display: inline-block;
}
.twister-peer .name {
font-weight: 600;
}
.twister-peer .avatar:hover, .twister-peer .name:hover, .twister-peer .alias:hover {
cursor: pointer;
}
.twister-peer .bio {
text-align: center;
padding: 4px;
}
.twister-peer .bio a {
font: italic 1.1em "Open Sans", sans-serif;
text-decoration: none;
color: #B46E67;
transition: all 200ms;
}
.twister-peer .bio a:hover {
color: #E18881;
opacity: .8;
}
/***********************************
********************* WHO TO FOLLOW
***********************************/
@ -2634,63 +2694,70 @@ textarea.splited-post { @@ -2634,63 +2694,70 @@ textarea.splited-post {
*********** FOLLOWING PAGE ***********
**************************************/
.following .header-bold {
display: block;
width: 100%;
margin: 0px auto 12px auto;
.following-own-modal.modal-wrapper {
width: 666px;
margin-left: -333px;
}
.following-own-modal .following-list {
text-align: center;
}
.following ol.following-list > li{
.following-own-modal .following-list > li {
display: inline-block;
width: 280px;
text-align: initial;
width: 320px;
height: 120px;
margin: 5px;
float: left;
border: 3px dashed #e0e6f5;
margin: 2px;
padding: 2px;
border: solid 1px rgba(69, 71, 77, .1);
background: #fff;
border-radius: 10px;
}
.following ol.following-list li .swarm-status {
font: 11px "Open Sans", sans-serif;
color: #343434;
display: block;
position: absolute;
top: 94px;
right: 8px;
.following-own-modal .following-list .mini-profile-name {
padding: 4px;
}
.following ol.following-list li span.mini-profile-name:hover {
.following-own-modal .following-list .mini-profile-name:hover {
color: #5e8da4;
}
.following ol.following-list li span.mini-screen-name {
.following-own-modal .following-list .mini-screen-name {
color: #5e8da4;
position: absolute;
top: 32px;
}
.following ol.following-list li span.mini-screen-name:hover {
.following-own-modal .following-list .mini-screen-name:hover {
color: #76b2ce;
}
.following ol.following-list .mini-profile-info .mini-profile-actions {
.following-own-modal .following-list .following-config {
width: 100%;
position: absolute;
top: 8px;
right: 2px;
z-index: 10;
top: 62px;
text-align: center;
}
.following ol.following-list .mini-profile-info button {
margin-top: 5px;
.following-own-modal .following-list .mini-profile-actions:hover ul {
height: 50px;
}
.following-own-modal .following-list .swarm-status {
font: 11px "Open Sans", sans-serif;
color: #343434;
display: block;
position: absolute;
top: 94px;
right: 32px;
}
.gifCheckBox {
float: right;
vertical-align: middle;
}
.following-list .following-config
{
width: 100%;
position: absolute;
top: 60px;
text-align: center;
}
/*************************************
*********** AUTOCOMPLETING ***********
**************************************/

519
theme_nin/css/style.css

@ -665,7 +665,7 @@ samp { @@ -665,7 +665,7 @@ samp {
background: #f3f2f1;
}
/* line 233, ../sass/_profile.sass */
.forEdition.profile-card .profile-card-main input {
.forEdition.profile-card .profile-card-main input, .forEdition .profile-card-main textarea {
display: block;
margin: 5px auto;
background: white;
@ -676,6 +676,7 @@ samp { @@ -676,6 +676,7 @@ samp {
transition: all 0.2s linear;
}
/* line 242, ../sass/_profile.sass */
.forEdition .profile-card-main textarea:hover, .forEdition .profile-card-main textarea:focus,
.forEdition.profile-card .profile-card-main input:hover, .forEdition.profile-card .profile-card-main input:focus {
background: white;
border-color: #aaa;
@ -684,6 +685,7 @@ samp { @@ -684,6 +685,7 @@ samp {
/* line 246, ../sass/_profile.sass */
.input-description {
width: 90%;
max-width: 90%;
}
/* line 249, ../sass/_profile.sass */
@ -1136,309 +1138,6 @@ samp { @@ -1136,309 +1138,6 @@ samp {
height: 100%;
}
/* line 1, ../sass/_following.sass */
.following {
width: 100% !important;
}
/* line 4, ../sass/_following.sass */
.following-list li {
text-align: center;
float: left;
width: 30%;
padding: 13px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
float: left;
margin: 0 2% 2% 0;
}
/* line 15, ../sass/_following.sass */
.following .mini-profile {
margin-bottom: 10px;
}
/* line 18, ../sass/_following.sass */
.following .mini-profile-info {
position: relative;
}
/* line 21, ../sass/_following.sass */
.following .mini-profile-photo {
margin: 0 auto 10px auto;
display: block;
width: 64px;
height: 64px;
overflow: hidden;
background: #E2E1DE;
}
/* line 29, ../sass/_following.sass */
.following .mini-profile-view {
display: inline;
color: rgba(0, 0, 0, 0.5);
font-size: 12px;
position: absolute;
top: 32px;
left: 65px;
z-index: 1;
}
/* line 38, ../sass/_following.sass */
.following .mini-profile-name {
font-weight: 900;
font-size: 1em;
line-height: 1em;
padding: 0;
text-decoration: none;
display: block;
color: inherit;
display: inline;
}
/* line 47, ../sass/_following.sass */
.following .mini-screen-name {
color: inherit;
display: block;
margin-bottom: 10px;
}
/* line 52, ../sass/_following.sass */
.following button, .following .mini-profile-actions span, .mini-profile-actions .following span {
display: inline-block;
margin: 5px 0;
}
/* line 55, ../sass/_following.sass */
.following button.unfollow, .following .mini-profile-actions span.unfollow, .mini-profile-actions .following span.unfollow {
background-color: #aaa;
}
/* line 57, ../sass/_following.sass */
.following button.public-following, .following .mini-profile-actions span.public-following, .mini-profile-actions .following span.public-following {
background-color: #B4C669;
}
/* line 62, ../sass/_following.sass */
.mini-profile-actions {
position: absolute;
width: auto;
top: 0;
right: -16px;
display: inline-block;
}
/* line 69, ../sass/_following.sass */
.mini-profile-actions span {
cursor: pointer !important;
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
/* line 76, ../sass/_following.sass */
.mini-profile-actions span:before {
margin: 0;
padding: 0;
line-height: 1em;
font-size: 10px;
}
/* line 81, ../sass/_following.sass */
.mini-profile-actions ul {
height: 0;
overflow: hidden;
position: absolute;
top: 2em;
right: -2em;
transition: height 0.4s linear;
transition: padding-top 0.1s linear;
background: #66686B;
z-index: 3;
}
/* line 96, ../sass/_following.sass */
.mini-profile-actions:hover ul {
padding: 8px;
height: 112px;
}
/* line 101, ../sass/_following.sass */
.mini-profile-actions ul li {
text-align: left;
margin: 0;
background: #66686B;
white-space: nowrap;
color: #aaa;
font-size: 12px;
line-height: 12px;
cursor: pointer;
display: block;
float: none;
width: auto;
padding: 8px;
}
/* line 117, ../sass/_following.sass */
.mini-profile-actions:hover ul li:hover {
color: #B4C669;
}
/* line 123, ../sass/_following.sass */
.following .who-follow {
height: auto;
background-color: rgba(69, 71, 77, 0.1);
overflow: hidden;
font-size: 12px;
}
/* line 129, ../sass/_following.sass */
.following .show-more-followers {
color: #f11;
font-weight: bold;
cursor: pointer;
float: right;
}
/* line 135, ../sass/_following.sass */
.following .mini-follower-link {
display: inline-block;
margin-right: 10px;
}
/* line 138, ../sass/_following.sass */
.following .mini-follower-link:before {
content: " ‧";
}
/* line 141, ../sass/_following.sass */
.following a.open-profile-modal {
display: inline;
text-align: center;
color: #66686B;
}
/* line 145, ../sass/_following.sass */
.following a.open-profile-modal:hover {
color: #aaa;
}
/* line 151, ../sass/_following.sass */
.following .post-area-new {
padding-bottom: 4px;
}
/* line 153, ../sass/_following.sass */
.following .post-area-new textarea {
resize: none;
width: 445px;
display: block;
transition: all 0.3s linear;
-webkit-transition: height 0.3s linear;
-moz-transition: height 0.3s linear;
-o-transition: height 0.3s linear;
-ms-transition: height 0.3s linear;
height: 28px;
border-radius: 3px;
border: solid 1px rgba(0, 0, 0, 0.3);
margin-left: 55px;
margin-bottom: 10px;
padding: 4px;
font-size: 13px;
}
/* line 170, ../sass/_following.sass */
.following .mini-profile .post-area-new {
padding: 9px;
}
/* line 172, ../sass/_following.sass */
.following .mini-profile .post-area-new textarea {
margin-left: 0;
width: 100%;
}
/* line 176, ../sass/_following.sass */
.following .post-area-new.open textarea, .following .mini-profile .post-area-new textarea, .mini-profile .following .post-area-new textarea, .following #postboard-top .post-area .post-area-new textarea, #postboard-top .post-area .following .post-area-new textarea {
height: 80px;
border: solid 1px rgba(227, 79, 66, 0.5);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
/* line 181, ../sass/_following.sass */
.following textarea.splited-post {
box-shadow: none !important;
height: 28px;
}
/* line 185, ../sass/_following.sass */
.following .splited-post-counter {
color: rgba(0, 0, 0, 0.3);
font-weight: bold;
}
/* line 188, ../sass/_following.sass */
.following .splited-post-counter:before {
content: "…";
}
/* line 191, ../sass/_following.sass */
.following .post-area-extras {
overflow: hidden;
height: 0;
text-align: right;
}
/* line 196, ../sass/_following.sass */
.following .post-submit {
background: #45474d;
color: rgba(255, 255, 255, 0.8);
border: none;
padding: 5px 10px;
cursor: pointer;
display: inline-block;
margin-top: 4px;
}
/* line 205, ../sass/_following.sass */
.following .post-area-new.open > .post-area-extras, .following .mini-profile .post-area-new > .post-area-extras, .mini-profile .following .post-area-new > .post-area-extras, .following #postboard-top .post-area .post-area-new > .post-area-extras, #postboard-top .post-area .following .post-area-new > .post-area-extras {
height: 35px;
transition: all 0.6s linear;
}
/* line 209, ../sass/_following.sass */
.following .post-area-remaining {
font-size: 13px;
}
/* line 211, ../sass/_following.sass */
.following .post-area-remaining.warn {
color: #ff0000;
}
/* line 214, ../sass/_following.sass */
.following .post .show-more {
font-size: 13px;
font-weight: bold;
margin-left: 60px;
color: rgba(0, 0, 0, 0.5);
}
/* line 219, ../sass/_following.sass */
.following .post .show-more:before {
content: "💭";
}
/* line 222, ../sass/_following.sass */
.swarm-status {
display: none !important;
}
/* line 232, ../sass/_following.sass */
.mini-following-info {
width: 45px;
height: 45px;
text-align: center;
background: white;
margin: 1%;
float: left;
}
/* line 241, ../sass/_following.sass */
.mini-following-info .mini-screen-name, .mini-following-info .mini-following-name {
display: none;
}
/* line 243, ../sass/_following.sass */
.mini-following-info .mini-profile-photo {
height: 45px;
width: 45px;
border-radius: 0;
}
/********** LOGIN AND NETWORK PAGES ****** */
/* line 4, ../sass/_network.sass */
.network.singleBlock ul {
@ -2378,6 +2077,15 @@ textarea.splited-post { @@ -2378,6 +2077,15 @@ textarea.splited-post {
transition: all 0.6s linear;
}
.post-area-new .post-textarea-edit-bar {
font-size: 11px;
margin: 2px 0;
}
.post-area-new .post-textarea-edit-bar > * {
margin: 2px 4px;
}
/* line 399, ../sass/style.sass */
.post-area-remaining {
padding-right: 3px;
@ -2387,6 +2095,63 @@ textarea.splited-post { @@ -2387,6 +2095,63 @@ textarea.splited-post {
color: #ff0000;
}
/* FIXME need to rework and replace all .twister-user to get same vis */
.twister-peer {
margin: 0;
min-height: 72px;
padding: 4px;
border-bottom: solid 1px rgba(69, 71, 77, .1);
border-top: solid 1px rgba(69, 71, 77, .1);
background: #FFF;
}
.twister-peer + .twister-peer {
border-top: none;
}
.twister-peer .avatar {
float: left;
width: 48px;
height: 48px;
overflow: hidden;
margin: 4px;
}
.twister-peer .avatar img {
width: 48px;
height: auto;
}
.twister-peer .name {
display: inline-block;
}
.twister-peer .name:hover {
color: #AAA;
}
.twister-peer .alias {
color: #AAA;
display: inline-block;
}
.twister-peer .alias:hover {
color: #B4C669;
}
.twister-peer .name {
font-weight: 600;
}
.twister-peer .avatar:hover, .twister-peer .name:hover, .twister-peer .alias:hover {
cursor: pointer;
}
.twister-peer .bio {
text-align: center;
padding: 4px;
}
/******** WHO TO FOLLOW ********/
/* line 411, ../sass/style.sass */
@ -2817,6 +2582,18 @@ ol.toptrends-list a:hover { @@ -2817,6 +2582,18 @@ ol.toptrends-list a:hover {
margin: 4px;
}
/*************************************
*********** CONFIRM POPUP ************
**************************************/
.confirm-popup.prompt-wrapper {
top: 30%;
}
.confirm-popup .message {
margin: 8px 12px 20px;
}
/****** FOLLOWING-CONFIG PROMPT ******/
.following-config-modal.prompt-wrapper {
@ -3272,6 +3049,20 @@ ol.toptrends-list a:hover { @@ -3272,6 +3049,20 @@ ol.toptrends-list a:hover {
padding: 0;
}
/*************************************
*********** FOLLOWERS MODAL **********
**************************************/
.modal-wrapper.followers-modal {
width: 520px;
height: 720px;
margin: -360px 0 0 -260px;
}
.followers-modal .modal-content {
padding: 0;
}
/****** FOLLOWING MODAL****** */
/* line 920, ../sass/style.sass */
.modal-wrapper.following-modal {
@ -3468,6 +3259,126 @@ ol.toptrends-list a:hover { @@ -3468,6 +3259,126 @@ ol.toptrends-list a:hover {
font-style: normal;
}
/*************************************
*********** FOLLOWING PAGE ***********
**************************************/
.modal-wrapper.following-own-modal {
width: 678px;
height: 600px;
margin: -300px 0 0 -339px;
}
.following-own-modal .modal-content {
padding: 0;
}
.following-own-modal .following-list {
text-align: center;
}
.following-own-modal .following-list > li {
display: inline-block;
width: 320px;
height: 160px;
margin: 2px;
padding: 2px;
border: solid 1px rgba(69, 71, 77, .1);
background: #FFF;
text-align: center;
}
.following-own-modal .following-list > li > div {
position: relative;
}
.following-own-modal .following-list > li:hover {
border-bottom: solid 1px #B4C669;
}
.following-own-modal .following-list .mini-profile-photo {
width: 64px;
height: 64px;
margin-top: 12px;
margin-bottom: 2px;
}
.following-own-modal .following-list .mini-profile-name {
padding: 4px;
}
.following-own-modal .following-list .mini-screen-name {
display: none;
}
.following-own-modal .following-list .following-config {
width: 100%;
text-align: center;
margin: 4px;
}
.following-own-modal .following-list .following-config button {
display: inline-block;
}
.following-own-modal .following-list .mini-profile-actions {
display: none;
position: absolute;
top: 0;
right: 8px;
}
.following-own-modal .following-list > li:hover .mini-profile-actions {
display: block;
}
.following-own-modal .following-list .mini-profile-actions span {
cursor: pointer;
display: inline-block;
position: relative;
z-index: 10;
background: #B4C669;
}
.following-own-modal .following-list .mini-profile-actions span:hover {
background: #AAA;
}
.following-own-modal .following-list .mini-profile-actions ul {
height: 0;
overflow: hidden;
position: absolute;
z-index: 20;
right: 0;
padding: 0;
background: #FFF;
transition: height .2s linear;
}
.following-own-modal .following-list .mini-profile-actions:hover ul {
height: 56px;
box-shadow: 8px 10px 10px 0px rgba(0, 0, 0, .2);
}
.following-own-modal .following-list .mini-profile-actions ul > li {
text-align: left;
white-space: nowrap;
color: rgba(0, 0, 0, .7);
font-size: 12px;
margin: 0;
padding: 4px 16px 4px 8px;
border-bottom: solid 1px rgba(0, 0, 0, 0);
background: #FFF;
}
.following-own-modal .following-list .mini-profile-actions ul > li:hover {
border-bottom: solid 1px #B4C669;
}
.following-own-modal .following-list .swarm-status {
font-size: 11px;
display: block;
}
/********** AUTOCOMPLETING *********/

4
theme_nin/js/theme_option.js

@ -7,8 +7,8 @@ $(function(){ @@ -7,8 +7,8 @@ $(function(){
$('img[src$="img/tornado_avatar.png"]').attr("src","theme_nin/img/tornado_avatar.png");
$('.mini-profile-actions span').html('');
$.globalEval(postToElem.toString().replace(/postContext.append\(_templatePostRtBy/,
'postContext.prependTo(postContext.parent()).append(_templatePostRtBy'));
$.globalEval(postToElem.toString().replace(/postContext.append\(twister\.tmpl\.postRtBy/,
'postContext.prependTo(postContext.parent()).append(twister.tmpl.postRtBy'));
$( '.userMenu-home.current a' ).on( 'click', function() {

239
theme_nin/sass/_following.sass

@ -1,239 +0,0 @@ @@ -1,239 +0,0 @@
.following
width: 100%!important
.following-list li
text-align: center
@extend .clear-fix
float: left
width: 30%
padding: 13px
+box-sizing(border-box)
float: left
margin: 0 2% 2% 0
.following .mini-profile
margin-bottom: 10px
.following .mini-profile-info
position: relative
.following .mini-profile-photo
margin: 0 auto 10px auto
display: block
width: 64px
height: 64px
overflow: hidden
background: $main-background-color
.following .mini-profile-view
display: inline
color: rgba(0, 0, 0, 0.5)
font-size: 12px
position: absolute
top: 32px
left: 65px
z-index: 1
.following .mini-profile-name
font-weight: 900
font-size: 1em
line-height: 1em
padding: 0
text-decoration: none
display: block
color: inherit
display: inline
.following .mini-screen-name
color: inherit
display: block
margin-bottom: 10px
.following button
display: inline-block
margin: 5px 0
&.unfollow
background-color: $main-color-light
&.public-following
background-color: $main-color-color
.mini-profile-actions
position: absolute
width: auto
top: 0
right: -16px
display: inline-block
span
cursor: pointer!important
@extend button
border-top-right-radius: 0!important
border-bottom-right-radius: 0!important
@extend .extend-icon
@extend .icon-plus
&:before
margin: 0
padding: 0
line-height: 1em
font-size: 10px
ul
$action-padding-height: 8px
height: 0
overflow: hidden
position: absolute
top: 2em
right: -2em
transition: height .4s linear
transition: padding-top .1s linear
background: $main-color-dark
z-index: 3
&:hover
ul
$action-li-height : 12px
$action-padding-height: 8px
padding: $action-padding-height
height: $action-li-height*4 + $action-padding-height*2*4
ul li
text-align: left
margin: 0
background: $main-color-dark
$action-li-height : 12px
$action-padding-height: 8px
white-space: nowrap
color: $main-color-light
font-size: $action-li-height
line-height: $action-li-height
cursor: pointer
display: block
float: none
width: auto
padding: $action-padding-height
&:hover ul li:hover
color: $main-color-color
.following .who-follow
height: auto
background-color: rgba(69, 71, 77, 0.1)
overflow: hidden
font-size: 12px
.following .show-more-followers
color: #f11
font-weight: bold
cursor: pointer
float: right
.following .mini-follower-link
display: inline-block
margin-right: 10px
&:before
content: " \2027"
.following a.open-profile-modal
display: inline
text-align: center
color: $dark-grey
&:hover
color: $main-color-light
.following .post-area-new
padding-bottom: 4px
textarea
resize: none
width: 445px
display: block
transition: all .3s linear
-webkit-transition: height 0.3s linear
-moz-transition: height 0.3s linear
-o-transition: height 0.3s linear
-ms-transition: height 0.3s linear
height: 28px
border-radius: 3px
border: solid 1px rgba(0, 0, 0, 0.3)
margin-left: 55px
margin-bottom: 10px
padding: 4px
font-size: 13px
.following .mini-profile .post-area-new
padding: 9px
textarea
margin-left: 0
width: 100%
.following .post-area-new.open textarea
height: 80px
border: solid 1px rgba(227, 79, 66, 0.5)
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3)
.following textarea.splited-post
box-shadow: none!important
height: 28px
.following .splited-post-counter
color: rgba(0, 0, 0, 0.3)
font-weight: bold
&:before
content: '\2026'
.following .post-area-extras
overflow: hidden
height: 0
text-align: right
.following .post-submit
background: #45474d
color: rgba(255, 255, 255, 0.8)
border: none
padding: 5px 10px
cursor: pointer
display: inline-block
margin-top: 4px
.following .post-area-new.open > .post-area-extras
height: 35px
transition: all .6s linear
.following .post-area-remaining
font-size: 13px
&.warn
color: #ff0000
.following .post .show-more
font-size: 13px
font-weight: bold
margin-left: 60px
color: rgba(0, 0, 0, 0.5)
&:before
content: '💭'
.swarm-status
display: none!important
.mini-following-info
width: 45px
height: 45px
text-align: center
background: $bloc-background-color
margin: 1%
float: left
&:after
@extend .clear-fix
.mini-screen-name, .mini-following-name
display: none
.mini-profile-photo
height: 45px
width: 45px
border-radius: 0

126
tmobile.html

@ -76,6 +76,16 @@ @@ -76,6 +76,16 @@
.content {padding:15px 20px 20px 20px;}
.footer {position:fixed;z-index:10;bottom:0;width:100%}
.post-textarea-edit-bar {
font-weight: lighter;
font-size: 12px;
margin: 2px 0;
}
.post-area-new .post-textarea-edit-bar > * {
margin: 2px 4px;
}
.post-info-time {
font-weight: lighter;
font-size: 12px;
@ -131,6 +141,19 @@ @@ -131,6 +141,19 @@
font-size: 9px;
float: right;
}
.direct-messages-list .post-info {
position: absolute;
top: 4px;
left: 72px;
width: 90%;
}
.direct-messages-list .post-text {
position: absolute;
top: 32px;
left: 72px;
}
</style>
<div id="index" data-role="page">
@ -467,37 +490,7 @@ @@ -467,37 +490,7 @@
<h1 class="rtitle">Following</h1>
</div>
<div class="content" data-role="content">
<ul class="following-list" data-role="listview">
<li id="following-user-template" style="display: none;">
<div class="mini-profile-info" data-screen-name="">
<a href="#" class="open-profile-modal">
<img class="mini-profile-photo avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<span class="mini-profile-name">Fulano da Silva</span>
<span>&nbsp;</span>
<span class="mini-screen-name">@
<b class="following-screen-name"></b>
</span>
</a>
<div>
<a data-role="button" data-mini="true" class="unfollow">Unfollow</a>
<a data-role="button" data-mini="true" class="direct-messages-with-user" href="#dmchat">Direct Message</a>
<!-- <a data-role="button" data-mini="true" class="public-following">Public</button> -->
</div>
<div>
<span class="swarm-status" style="display: none;"></span>
</div>
</div>
</li>
</ul>
<div class="not-following-any" style="display:none;">
<h3>
<div> Not following any users! </div>
<div> Use "Search" button to find and follow some.</div>
</h3>
</div>
</div>
<div class="content" data-role="content"></div>
<div class="footer" data-role="footer" data-position="fixed" data-tap-toggle="false">
<a href="#home" data-role="button">Home</a>
@ -619,8 +612,7 @@ @@ -619,8 +612,7 @@
</div>
<div class="content" data-role="content">
<ul class="direct-messages-thread" data-role="listview">
</ul>
<ul class="direct-messages-list" data-role="listview"></ul>
</div>
<div class="footer" data-role="footer" data-position="fixed" data-tap-toggle="false">
@ -637,8 +629,7 @@ @@ -637,8 +629,7 @@
</div>
<div class="content" data-role="content">
<ul class="direct-messages-list" data-role="listview">
</ul>
<ul class="direct-messages-thread" data-role="listview"></ul>
<div class="dm-form" style="padding:15px 20px 20px 20px;">
<form class="post-area-new open">
@ -775,6 +766,14 @@ @@ -775,6 +766,14 @@
</div>
</div>
<div id="template-post-textarea-edit-bar">
<div class="post-textarea-edit-bar"></div>
</div>
<div id="template-shorten-uri">
<a class="shorten-uri">shorten URL</a>
</div>
<li id="post-template-post" class="module post" data-time="">
<img class="avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<div class="post-data" data-userpost="" data-content_to_rt="" data-content_to_sigrt=""
@ -809,7 +808,7 @@ @@ -809,7 +808,7 @@
</div> <!-- post-data -->
</li> <!-- post-template -->
<div id="post-rt-reference-template">
<div id="template-post-rt-reference">
<div class="post-rt-reference">
<div class="post-photo"><img class="avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo" /></div>
<div class="post-info">
@ -821,7 +820,7 @@ @@ -821,7 +820,7 @@
</div>
</div>
<div id="post-rt-by-template">
<div id="template-post-rt-by">
<div class="post-rt-sign">
<span class="prep">twisted again by</span><a class="open-profile-modal"></a>
</div>
@ -836,25 +835,26 @@ @@ -836,25 +835,26 @@
<a id="external-page-link-template" rel="nofollow" target="_blank"></a>
<!-- template for user links in message (open profile modal) -->
<a id="hashtag-link-template" class="open-hashtag-modal"></a>
<div id="template-link-shortened">
<a class="link-shortened" rel="nofollow" target="_blank"></a>
</div>
<!-- template para ir dentro de avatar-row -->
<a id="avatar-row-template" class="open-profile-modal" href="">
<img class="avatar size24" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
</a>
<!-- template for dm-snippet (dm threads list) -->
<li id="dm-snippet-template" class="module post message" data-icon="arrow-r">
<a class="dm-chat-link post-photo" href="#dmchat">
<img class="avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<h4 class="post-info">
<span class="post-info-name open-profile-modal"></span>
<span class="post-info-tag">@</span>
<a class="post-info-time ui-li-aside"><span></span></a>
</h4>
<!-- o texto do post (restrição de caracteres?) -->
<p class="post-text"></p>
</a>
</li>
<div id="template-direct-messages-list-item">
<li class="module post message" data-icon="arrow-r">
<div class="post-photo"><img class="avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/></div>
<div class="post-info">
<a class="post-info-name"></a>
<span class="post-info-tag">@</span>
<a class="post-info-time ui-li-aside"><span></span></a>
</div>
<p class="post-text"></p>
</li>
</div>
<!-- template for each dm (chat window) -->
<li id="dm-chat-template" class="module post message">
@ -865,6 +865,32 @@ @@ -865,6 +865,32 @@
<p class="post-text no-ellipsis"></p>
</li>
<div id="template-following-list">
<ul class="following-list" data-role="listview"></ul>
</div>
<div id="template-following-peer">
<li>
<div class="mini-profile-info">
<a href="#" class="open-profile-modal">
<img class="mini-profile-photo avatar" src="img/grayed_avatar_placeholder_24.png" alt="user-photo"/>
<span class="mini-profile-name">Fulano da Silva</span>
<span>&nbsp;</span>
<span class="mini-screen-name">@
<b class="following-screen-name"></b>
</span>
</a>
<div>
<a data-role="button" data-mini="true" class="unfollow">Unfollow</a>
<a data-role="button" data-mini="true" class="direct-messages-with-user" href="#dmchat">Direct Message</a>
<!-- <a data-role="button" data-mini="true" class="public-following">Public</button> -->
</div>
<div>
<span class="swarm-status" style="display: none;"></span>
</div>
</div>
</li>
</div>
</div> <!-- templates -->

Loading…
Cancel
Save