Browse Source

Merge pull request #221 from slr/tasty-notifications

initial commit of desktop notifications
master
miguelfreitas 10 years ago
parent
commit
f2ab004be0
  1. 1
      following.html
  2. 2
      home.html
  3. 41
      js/interface_common.js
  4. 143
      js/interface_localization.js
  5. 4
      js/mobile_abstract.js
  6. 194
      js/notify.js
  7. 11
      js/options.js
  8. 2
      js/twister_actions.js
  9. 2
      js/twister_following.js
  10. 38
      js/twister_newmsgs.js
  11. 8
      js/twister_timeline.js
  12. 1
      login.html
  13. 1
      network.html
  14. 13
      options.html
  15. 1
      profile-edit.html
  16. 2
      theme_nin/css/style.css
  17. 2
      theme_nin/sass/_tabs.sass

1
following.html

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
<script src="js/jquery.jsonrpcclient.js"></script>
<script src="js/jquery.storageapi.js"></script>
<script src="js/options.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>

2
home.html

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
<script src="js/jquery.jsonrpcclient.js"></script>
<script src="js/jquery.storageapi.js"></script>
<script src="js/options.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>
@ -26,6 +27,7 @@ @@ -26,6 +27,7 @@
<script src="js/interface_common.js"></script>
<script src="js/interface_home.js"></script>
<script src="js/jquery.textcomplete.js"></script>
<script>
$(function(){setTimeout(mensAutocomplete, 800);})
changeStyle();

41
js/interface_common.js

@ -200,6 +200,16 @@ function updateHashtagModal(postboard,hashtag,timeoutArgs) { @@ -200,6 +200,16 @@ function updateHashtagModal(postboard,hashtag,timeoutArgs) {
var resource = $hashtagModalClass.attr("data-resource");
requestHashtag(postboard,hashtag,resource,timeoutArgs);
if( _hashtagPendingPostsUpdated ) {
showDesktopNotification(false, polyglot.t('You got')+' '+polyglot.t("new_posts", _hashtagPendingPostsUpdated)+' '+polyglot.t('in search result')+'.', false,'twister_notification_new_posts_modal', function() {
$(".postboard-news").hide();
displayHashtagPending($(".hashtag-modal .postboard-posts"));
}, false)
_hashtagPendingPostsUpdated = 0;
}
// use extended timeout parameters on modal refresh (requires twister_core >= 0.9.14).
// our first query above should be faster (with default timeoutArgs of twisterd),
// then we may possibly collect more posts on our second try by waiting more.
@ -809,6 +819,36 @@ function replyTextKeypress(e) { @@ -809,6 +819,36 @@ function replyTextKeypress(e) {
}
}
function showDesktopNotification(notifyTitle, notifyBody, notifyIcon, notifyTag, actionOnClick, actionOnPermDenied) {
function doNotification(notifyTitle, notifyBody, notifyIcon, notifyTag, actionOnClick) {
if (!notifyTitle) {
notifyTitle = polyglot.t('notify_desktop_title');
}
if (!notifyIcon) {
notifyIcon = '../img/twister_mini.png';
}
if (!notifyTag) {
notifyTag = 'twister_notification';
}
var desktopNotification = new Notify(notifyTitle, {
body: notifyBody,
icon: notifyIcon,
tag: notifyTag,
timeout: _desktopNotificationTimeout,
notifyClick: actionOnClick,
notifyError: function() { alert(polyglot.t('notify_desktop_error')) }
});
desktopNotification.show();
}
if (Notify.needsPermission) {
Notify.requestPermission(false, actionOnPermDenied);
} else {
doNotification(notifyTitle, notifyBody, notifyIcon, notifyTag, actionOnClick);
}
}
/*
* unicode convertion list
* k: original string to be replaced
@ -1299,7 +1339,6 @@ var postSubmit = function(e, oldLastPostId) @@ -1299,7 +1339,6 @@ var postSubmit = function(e, oldLastPostId)
var tweetForm = $this.parents("form");
var remainingCount = tweetForm.find(".post-area-remaining");
remainingCount.text(140);
$replyText.attr("placeholder", "Your message was sent!");
if ($this.parents('.modal-wrapper').length) {
closeModal($this);

143
js/interface_localization.js

@ -91,9 +91,18 @@ if(preferredLanguage == "en"){ @@ -91,9 +91,18 @@ if(preferredLanguage == "en"){
"Network status": "Network status",
"New direct message...": "New direct message...",
"New Post...": "New Post...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} new post |||| %{smart_count} new posts",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Not available", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Number of blocks in block chain: ",
"Number of CPUs to use": "Number of CPUs to use ",
"Only alphanumeric and underscore allowed.": "Only alphanumeric and underscore allowed.",
@ -184,6 +193,8 @@ if(preferredLanguage == "en"){ @@ -184,6 +193,8 @@ if(preferredLanguage == "en"){
"Ignore": "Ignore",
"Theme": "Theme",
"Keys": "Keys",
"Notifications": "Notifications",
"Desktop notifications": "Desktop notifications",
"Sound notifications": "Sound notifications",
"Send key": "Send key",
"Posts display": "Posts display",
@ -321,9 +332,18 @@ if(preferredLanguage == "es"){ @@ -321,9 +332,18 @@ if(preferredLanguage == "es"){
"Network status": "Estado de la red",
"New direct message...": "Nuevo mensaje directo...",
"New Post...": "Nuevo Post...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} nuevo post |||| %{smart_count} nuevos posts",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "Nadie", // used to promote a post without attaching the user
"Not available": "No disponible", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Número de bloques en la cadena de bloques: ",
"Number of CPUs to use": "Número de CPUs para utilizar ",
"Only alphanumeric and underscore allowed.": "Sólo alfanuméricos y subrayados permitido.",
@ -414,6 +434,8 @@ if(preferredLanguage == "es"){ @@ -414,6 +434,8 @@ if(preferredLanguage == "es"){
"Ignore": "Ignorar",
"Theme": "Tema",
"Keys": "Teclas",
"Notifications": "Notificaciones",
"Desktop notifications": "Notificaciones de Escritorio",
"Sound notifications": "Notificaciones de Sonido",
"Send key": "Send key",
"Posts display": "Posts display",
@ -549,9 +571,18 @@ if(preferredLanguage == "uk"){ @@ -549,9 +571,18 @@ if(preferredLanguage == "uk"){
"Network status": "Статус мережі",
"New direct message...": "Нове особисте повідомлення...",
"New Post...": "Нове повідомлення...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} нове повідомлення |||| %{smart_count} нових повідомлень",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Не доступне", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Кількість блоків у ланцюгу: ",
"Number of CPUs to use": "Кількість CPUs до використання ",
"Only alphanumeric and underscore allowed.": "Тільки літеро-численні сиволи та нижнє підкреслення дозволені.",
@ -641,6 +672,8 @@ if(preferredLanguage == "uk"){ @@ -641,6 +672,8 @@ if(preferredLanguage == "uk"){
"Ignore": "Ignore",
"Theme": "Theme",
"Keys": "Keys",
"Notifications": "Notifications",
"Desktop notifications": "Desktop notifications",
"Sound notifications": "Sound notifications",
"Send key": "Send key",
"Posts display": "Posts display",
@ -775,9 +808,18 @@ if(preferredLanguage == "zh"){ @@ -775,9 +808,18 @@ if(preferredLanguage == "zh"){
"Network status": "网络状态",
"New direct message...": "新的即时信息...",
"New Post...": "新推文...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} 新推文",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "用户名不可用", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "块链中的块数:",
"Number of CPUs to use": "使用CPU数目 ",
"Only alphanumeric and underscore allowed.": "只允许字母和下划线",
@ -867,6 +909,8 @@ if(preferredLanguage == "zh"){ @@ -867,6 +909,8 @@ if(preferredLanguage == "zh"){
"Ignore": "Ignore",
"Theme": "Theme",
"Keys": "Keys",
"Notifications": "Notifications",
"Desktop notifications": "Desktop notifications",
"Sound notifications": "Sound notifications",
"Send key": "Send key",
"Posts display": "Posts display",
@ -1001,9 +1045,18 @@ if(preferredLanguage == "nl"){ @@ -1001,9 +1045,18 @@ if(preferredLanguage == "nl"){
"Network status": "Netwerkstatus",
"New direct message...": "Nieuw privébericht...",
"New Post...": "Nieuw bericht...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} nieuw bericht |||| %{smart_count} nieuwe berichten",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Niet beschikbaar", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Aantal blocks in block chain: ",
"Number of CPUs to use": "Aantal CPUs om te gebruiken ",
"Only alphanumeric and underscore allowed.": "Alleen alphanumeriek en underscore toegestaan.",
@ -1094,6 +1147,8 @@ if(preferredLanguage == "nl"){ @@ -1094,6 +1147,8 @@ if(preferredLanguage == "nl"){
"Ignore": "Ignore",
"Theme": "Theme",
"Keys": "Keys",
"Notifications": "Notifications",
"Desktop notifications": "Desktop notifications",
"Sound notifications": "Sound notifications",
"Send key": "Send key",
"Posts display": "Posts display",
@ -1228,9 +1283,18 @@ if(preferredLanguage == "it"){ @@ -1228,9 +1283,18 @@ if(preferredLanguage == "it"){
"Network status": "Status della rete",
"New direct message...": "Nuovo messaggio diretto...",
"New Post...": "Nuovo messaggio...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} nuovo messaggio |||| %{smart_count} nuovi messaggi",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "nessuno", // used to promote a post without attaching the user
"Not available": "Non disponibile", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Numero di blocchi nella catena: ",
"Number of CPUs to use": "Numero di processori da usare:",
"Only alphanumeric and underscore allowed.": "Sono permessi solo caratteri alfanumerici e '_'",
@ -1318,6 +1382,8 @@ if(preferredLanguage == "it"){ @@ -1318,6 +1382,8 @@ if(preferredLanguage == "it"){
"Ignore": "Ignore",
"Theme": "Theme",
"Keys": "Keys",
"Notifications": "Notifications",
"Desktop notifications": "Desktop notifications",
"Sound notifications": "Sound notifications",
"Send key": "Send key",
"Posts display": "Posts display",
@ -1453,9 +1519,18 @@ if(preferredLanguage == "fr"){ @@ -1453,9 +1519,18 @@ if(preferredLanguage == "fr"){
"Network status": "État du réseau",
"New direct message...": "Nouveau message privé...",
"New Post...": "Nouveau billets...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} nouveau billet |||| %{smart_count} nouveaux billets",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Non disponible", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Nombre de blocs dans la chaîne de blocs: ",
"Number of CPUs to use": "Nombre de processeurs à utiliser",
"Only alphanumeric and underscore allowed.": "Seuls les caractères alphanumériques et la barre de soulignement sont permis.",
@ -1546,6 +1621,8 @@ if(preferredLanguage == "fr"){ @@ -1546,6 +1621,8 @@ if(preferredLanguage == "fr"){
"Ignore": "Ignore",
"Theme": "Theme",
"Keys": "Keys",
"Notifications": "Notifications",
"Desktop notifications": "Desktop notifications",
"Sound notifications": "Sound notifications",
"Send key": "Send key",
"Posts display": "Posts display",
@ -1684,9 +1761,18 @@ if(preferredLanguage == "ru"){ @@ -1684,9 +1761,18 @@ if(preferredLanguage == "ru"){
"Network status": "Состояние сети",
"New direct message...": "Новое личное сообщение...",
"New Post...": "Новый пост...",
"You got": "У вас там",
"in postboard": "в ленте",
"in search result": "в результатах поиска",
"new_posts": "%{smart_count} новый пост |||| %{smart_count} новых постов",
"new_mentions": "%{smart_count} новое упоминание |||| %{smart_count} новых упоминаний",
"new_direct_messages": "%{smart_count} новое личное сообщение |||| %{smart_count} новых личных сообщений",
"nobody": "Анонимно", // used to promote a post without attaching the user
"Not available": "Недоступно",
"notify_desktop_error": "Твистер не может выполнить уведомление: произошла неизвестная ошибка.",
"notify_desktop_perm_denied": "Твистер не может выполниь уведомление: разрешение не получено.\n\nЧтобы получать уведомления, разрешите их для этого домена в настройках вашего браузера.",
"notify_desktop_test": "Лягушка сказала: 'если не буду квакать — лопну'. Вы нужны нам, берегите себя.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Количество блоков в цепочке: ",
"Number of CPUs to use": "Сколько использовать ядер процессора",
"Only alphanumeric and underscore allowed.": "Разрешены только латинские буквы, цифры и подчеркивания.",
@ -1777,6 +1863,8 @@ if(preferredLanguage == "ru"){ @@ -1777,6 +1863,8 @@ if(preferredLanguage == "ru"){
"Ignore": "Игнорировать",
"Theme": "Тема",
"Keys": "Клавиши",
"Notifications": "Уведомления",
"Desktop notifications": "Уведомления рабочего стола",
"Sound notifications": "Звуковые уведомления",
"Send key": "Отправка сообщения",
"Posts display": "Отображение сообщений",
@ -1916,9 +2004,18 @@ if(preferredLanguage == "de"){ @@ -1916,9 +2004,18 @@ if(preferredLanguage == "de"){
"Network status": "Netzwerkstatus",
"New direct message...": "Neue Direktnachricht...",
"New Post...": "Neuer Post...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} neuer Post |||| %{smart_count} neue Posts",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Nicht verfügbar", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Anzahl der Blöcke in der Block-Chain: ",
"Number of CPUs to use": "Anzahl der zu benutzenden CPU's ",
"Only alphanumeric and underscore allowed.": "Nur Buchstaben, Zahlen und Unterstrich erlaubt.",
@ -2010,6 +2107,8 @@ if(preferredLanguage == "de"){ @@ -2010,6 +2107,8 @@ if(preferredLanguage == "de"){
"Ignore": "Ignorieren",
"Theme": "Theme",
"Keys": "Keys",
"Notifications": "Benachrichtigungen",
"Desktop notifications": "Desktophinweisen",
"Sound notifications": "Audioeinstellungen",
"Send key": "Send key",
"Posts display": "Posts display",
@ -2144,9 +2243,18 @@ if(preferredLanguage == "ja"){ @@ -2144,9 +2243,18 @@ if(preferredLanguage == "ja"){
"Network status": "ネットワークステータス",
"New direct message...": "ダイレクトメッセージ...",
"New Post...": "投稿する",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} 新投稿 |||| %{smart_count} 新投稿",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "ナナシ", // used to promote a post without attaching the user
"Not available": "使用中", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "全ブロック数: ",
"Number of CPUs to use": "利用するCPUの数",
"Only alphanumeric and underscore allowed.": "アルファベットとアンダースコア(_)が利用可能です",
@ -2234,6 +2342,8 @@ if(preferredLanguage == "ja"){ @@ -2234,6 +2342,8 @@ if(preferredLanguage == "ja"){
"Ignore": "Ignore",
"Theme": "Theme",
"Keys": "Keys",
"Notifications": "Notifications",
"Desktop notifications": "Desktop notifications",
"Sound notifications": "Sound notifications",
"Send key": "Send key",
"Posts display": "Posts display",
@ -2369,9 +2479,18 @@ if(preferredLanguage == "pt-BR"){ @@ -2369,9 +2479,18 @@ if(preferredLanguage == "pt-BR"){
"Network status": "Estado da rede",
"New direct message...": "Nova mensagem direta...",
"New Post...": "Nova Postagem...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} nova postagem |||| %{smart_count} novas postagens",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "nobody", // used to promote a post without attaching the user
"Not available": "Indisponível", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Número de blocos: ",
"Number of CPUs to use": "Número de CPUs a serem utilizados ",
"Only alphanumeric and underscore allowed.": "Permitido apenas caracteres alfanuméricos e underscore '_'.",
@ -2464,6 +2583,8 @@ if(preferredLanguage == "pt-BR"){ @@ -2464,6 +2583,8 @@ if(preferredLanguage == "pt-BR"){
"Ignore": "Ignore",
"Theme": "Theme",
"Keys": "Keys",
"Notifications": "Notifications",
"Desktop notifications": "Desktop notifications",
"Sound notifications": "Sound notifications",
"Send key": "Send key",
"Posts display": "Posts display",
@ -2598,9 +2719,18 @@ if(preferredLanguage == "tr"){ @@ -2598,9 +2719,18 @@ if(preferredLanguage == "tr"){
"Network status": "Ağ durumu",
"New direct message...": "Yeni direk mesaj...",
"New Post...": "Yeni gönderi...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} yeni gönederi |||| %{smart_count} yeni gönderi",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct messages",
"nobody": "hiçkimse", // used to promote a post without attaching the user
"Not available": "Kullanılamaz", // username is not available
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Blok zincirindeki blok sayısı: ",
"Number of CPUs to use": "Kullanılacak CPU sayısı ",
"Only alphanumeric and underscore allowed.": "Sadece harf ve alt çizgi kullanılabilir.",
@ -2681,6 +2811,8 @@ if(preferredLanguage == "tr"){ @@ -2681,6 +2811,8 @@ if(preferredLanguage == "tr"){
"Ignore": "Görmezden gel",
"Theme": "Tema",
"Keys": "Tuşlar",
"Notifications": "Uyarılar",
"Desktop notifications": "Masaüstü uyarılar",
"Sound notifications": "Sesli uyarılar",
"Send key": "Gönderme tuşu",
"Posts display": "Gönderiler",
@ -2824,9 +2956,18 @@ if(preferredLanguage == "cs"){ @@ -2824,9 +2956,18 @@ if(preferredLanguage == "cs"){
"Network status": "Stav sítě",
"New direct message...": "Nová přímá zpráva...",
"New Post...": "Nový příspěvek...",
"You got": "You got",
"in postboard": "in postboard",
"in search result": "in search result",
"new_posts": "%{smart_count} nový příspěvek |||| %{smart_count} nové příspěvky |||| %{smart_count} nových příspěvků",
"new_mentions": "%{smart_count} new mention |||| %{smart_count} new mentions",
"new_direct_messages": "%{smart_count} new direct message |||| %{smart_count} new direct 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
"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. Now you are welcome too.",
"notify_desktop_title": "Watch out, it's twister over here!",
"Number of blocks in block chain:": "Počet bloků v blockchainu: ",
"Number of CPUs to use": "Kolik jader procesoru použít? ",
"Only alphanumeric and underscore allowed.": "Povolena jsou jen písmena, čísla a podtržítko.",
@ -2915,6 +3056,8 @@ if(preferredLanguage == "cs"){ @@ -2915,6 +3056,8 @@ if(preferredLanguage == "cs"){
"Ignore": "Ignorovat",
"Theme": "Styl grafiky",
"Keys": "Klávesy",
"Notifications": "Upozornění",
"Desktop notifications": "Upozornění na ploše",
"Sound notifications": "Zvuková upozornění",
"Send key": "Klávesa pro odeslání",
"Posts display": "Zobrazení příspěvků",

4
js/mobile_abstract.js

@ -102,6 +102,10 @@ var MAL = function() @@ -102,6 +102,10 @@ var MAL = function()
newTweetsBar.fadeIn("slow");
newTweetsBarMenu.text(String(newPosts));
newTweetsBarMenu.addClass("show");
showDesktopNotification(false, polyglot.t('You got')+' '+polyglot.t("new_posts", newPosts)+' '+polyglot.t('in postboard')+'.', false,'twister_notification_new_posts', function() {
requestTimelineUpdate("latest",postsPerRefresh,followingUsers,promotedPostsOnly);
}, false)
} else {
newTweetsBar.hide();
newTweetsBar.text("");

194
js/notify.js

@ -0,0 +1,194 @@ @@ -0,0 +1,194 @@
/*
* Author: Alex Gibson
* https://github.com/alexgibson/notify.js
* License: MIT license
*/
(function(global, factory) {
if (typeof define === 'function' && define.amd) {
// AMD environment
define(function() {
return factory(global, global.document);
});
} else if (typeof module !== 'undefined' && module.exports) {
// CommonJS environment
module.exports = factory(global, global.document);
} else {
// Browser environment
global.Notify = factory(global, global.document);
}
} (typeof window !== 'undefined' ? window : this, function (w, d) {
'use strict';
function isFunction (item) {
return typeof item === 'function';
}
function Notify(title, options) {
if (typeof title !== 'string') {
throw new Error('Notify(): first arg (title) must be a string.');
}
this.title = title;
this.options = {
icon: '',
body: '',
tag: '',
notifyShow: null,
notifyClose: null,
notifyClick: null,
notifyError: null,
timeout: null
};
this.permission = null;
if (!Notify.isSupported) {
return;
}
//User defined options for notification content
if (typeof options === 'object') {
for (var i in options) {
if (options.hasOwnProperty(i)) {
this.options[i] = options[i];
}
}
//callback when notification is displayed
if (isFunction(this.options.notifyShow)) {
this.onShowCallback = this.options.notifyShow;
}
//callback when notification is closed
if (isFunction(this.options.notifyClose)) {
this.onCloseCallback = this.options.notifyClose;
}
//callback when notification is clicked
if (isFunction(this.options.notifyClick)) {
this.onClickCallback = this.options.notifyClick;
}
//callback when notification throws error
if (isFunction(this.options.notifyError)) {
this.onErrorCallback = this.options.notifyError;
}
}
}
// true if the browser supports HTML5 Notification
Notify.isSupported = 'Notification' in w;
// true if the permission is not granted
Notify.needsPermission = !(Notify.isSupported && Notification.permission === 'granted');
// returns current permission level ('granted', 'default', 'denied' or null)
Notify.permissionLevel = (Notify.isSupported ? Notification.permission : null);
// asks the user for permission to display notifications. Then calls the callback functions is supplied.
Notify.requestPermission = function (onPermissionGrantedCallback, onPermissionDeniedCallback) {
if (!Notify.isSupported) {
return;
}
w.Notification.requestPermission(function (perm) {
switch (perm) {
case 'granted':
Notify.needsPermission = false;
if (isFunction(onPermissionGrantedCallback)) {
onPermissionGrantedCallback();
}
break;
case 'denied':
if (isFunction(onPermissionDeniedCallback)) {
onPermissionDeniedCallback();
}
break;
}
});
};
Notify.prototype.show = function () {
if (!Notify.isSupported) {
return;
}
this.myNotify = new Notification(this.title, {
'body': this.options.body,
'tag' : this.options.tag,
'icon' : this.options.icon
});
if (this.options.timeout && !isNaN(this.options.timeout)) {
setTimeout(this.close.bind(this), this.options.timeout * 1000);
}
this.myNotify.addEventListener('show', this, false);
this.myNotify.addEventListener('error', this, false);
this.myNotify.addEventListener('close', this, false);
this.myNotify.addEventListener('click', this, false);
};
Notify.prototype.onShowNotification = function (e) {
if (this.onShowCallback) {
this.onShowCallback(e);
}
};
Notify.prototype.onCloseNotification = function (e) {
if (this.onCloseCallback) {
this.onCloseCallback(e);
}
this.destroy();
};
Notify.prototype.onClickNotification = function (e) {
if (this.onClickCallback) {
this.onClickCallback(e);
}
};
Notify.prototype.onErrorNotification = function (e) {
if (this.onErrorCallback) {
this.onErrorCallback(e);
}
this.destroy();
};
Notify.prototype.destroy = function () {
this.myNotify.removeEventListener('show', this, false);
this.myNotify.removeEventListener('error', this, false);
this.myNotify.removeEventListener('close', this, false);
this.myNotify.removeEventListener('click', this, false);
};
Notify.prototype.close = function () {
this.myNotify.close();
};
Notify.prototype.handleEvent = function (e) {
switch (e.type) {
case 'show':
this.onShowNotification(e);
break;
case 'close':
this.onCloseNotification(e);
break;
case 'click':
this.onClickNotification(e);
break;
case 'error':
this.onErrorNotification(e);
break;
}
};
return Notify;
}));

11
js/options.js

@ -2,6 +2,8 @@ $(function() { @@ -2,6 +2,8 @@ $(function() {
});
var _desktopNotificationTimeout = 10; // it should be an option
var TwisterOptions = function()
{
this.getOption = function(optionName, defaultValue) {
@ -88,6 +90,12 @@ var TwisterOptions = function() @@ -88,6 +90,12 @@ var TwisterOptions = function()
player[0].play();
}
this.notificationDesktopTest = function() {
$('#notifications-desktop-test').on('click', function() {
showDesktopNotification(false, polyglot.t('notify_desktop_test'), false,'twister_notification_test', false, function() { alert(polyglot.t('notify_desktop_perm_denied')) })
})
}
this.keysSendDefault = "ctrlenter";
this.keysSend = function() {
$('#keysOpt select')[0].value = $.Options.getOption('keysSend',this.keysSendDefault);
@ -338,6 +346,7 @@ var TwisterOptions = function() @@ -338,6 +346,7 @@ var TwisterOptions = function()
this.InitOptions = function() {
this.soundNotifOptions();
this.volumeControl();
this.notificationDesktopTest();
this.keysSend();
this.setLang();
this.setTheme();
@ -365,7 +374,7 @@ function localizeLabels() @@ -365,7 +374,7 @@ function localizeLabels()
{
$("label[for=tab_language]").text(polyglot.t("Language"));
$("label[for=t-2]").text(polyglot.t("Theme"));
$("label[for=t-3]").text(polyglot.t("Sound"));
$("label[for=t-3]").text(polyglot.t("Notifications"));
$("label[for=t-4]").text(polyglot.t("Keys"));
$("label[for=t-5]").text(polyglot.t("Postboard"));
$("label[for=t-6]").text(polyglot.t("Users"));

2
js/twister_actions.js

@ -14,6 +14,7 @@ var maxExpandPost = 8; @@ -14,6 +14,7 @@ var maxExpandPost = 8;
var maxExpandPostTop = 4;
var _hashtagProcessedMap = {};
var _hashtagPendingPosts = [];
var _hashtagPendingPostsUpdated = 0;
var autoUpdateHashtag = false;
// ----------------
@ -335,6 +336,7 @@ function processHashtag(postboard, hashtag, data) { @@ -335,6 +336,7 @@ function processHashtag(postboard, hashtag, data) {
if( !(key in _hashtagProcessedMap) ) {
_hashtagProcessedMap[key] = true;
_hashtagPendingPosts.push(data[i]);
_hashtagPendingPostsUpdated++;
}
}

2
js/twister_following.js

@ -586,7 +586,7 @@ function userSearchKeypress(event) { @@ -586,7 +586,7 @@ function userSearchKeypress(event) {
searchResults.slideUp( "fast" );
if ( event.which == 13 )
openHashtagModalFromSearch(partialName.substr(1));
window.location.hash = '#hashtag?hashtag=' + encodeURIComponent(partialName.substr(1));
return;
}

38
js/twister_newmsgs.js

@ -11,6 +11,8 @@ var _lastMentionTime = 0; @@ -11,6 +11,8 @@ var _lastMentionTime = 0;
var _newMentions = 0;
var _lastLocalMentionId = -1;
var PURGE_OLD_MENTIONS_TIMEOUT = 3600 * 24 * 30; // one month
var _newMentionsUpdated = false;
var _newDMsUpdated = false;
// process a mention received to check if it is really new
function processMention(user, mentionTime, data) {
@ -19,12 +21,11 @@ function processMention(user, mentionTime, data) { @@ -19,12 +21,11 @@ function processMention(user, mentionTime, data) {
if( mentionTime > curTime + 3600 * 2 ) {
console.log("mention from the future will be ignored");
} else {
var newMentionsUpdated = false;
if( !(key in _knownMentions) ) {
// mention must be somewhat recent compared to last known one to be considered new
if( mentionTime + 3600 * 24 * 3 > _lastMentionTime ) {
_newMentions++;
newMentionsUpdated = true;
_newMentionsUpdated = true;
_lastMentionTime = Math.max(mentionTime,_lastMentionTime);
data["isNew"] = true;
}
@ -32,9 +33,6 @@ function processMention(user, mentionTime, data) { @@ -32,9 +33,6 @@ function processMention(user, mentionTime, data) {
purgeOldMentions();
saveMentionsToStorage();
}
if( newMentionsUpdated ) {
$.MAL.soundNotifyMentions();
}
}
}
@ -96,6 +94,29 @@ function requestMentionsCount() { @@ -96,6 +94,29 @@ function requestMentionsCount() {
}
}, {},
[10000,2000,3]); // use extended timeout parameters (requires twister_core >= 0.9.14)
if( _newMentionsUpdated ) {
_newMentionsUpdated = false;
$.MAL.soundNotifyMentions();
showDesktopNotification(false, polyglot.t('You got')+' '+polyglot.t('new_mentions', _newMentions)+'.', false,'twister_notification_new_mentions', openMentionsModal, false)
}
// was moved here from requestDMsCount() because that is not ticking right
// we would place it with other notifications into separate notification center
if( _newDMsUpdated ) {
_newDMsUpdated = false;
var newDMs = getNewDMsCount();
if ( newDMs ) {
$.MAL.soundNotifyDM();
showDesktopNotification(false, polyglot.t('You got')+' '+polyglot.t('new_direct_messages', newDMs)+'.', false, 'twister_notification_new_DMs', function() {
window.location.hash = '#directmessages';
}, false)
}
}
}
function resetMentionsCount() {
@ -154,23 +175,22 @@ function requestDMsCount() { @@ -154,23 +175,22 @@ function requestDMsCount() {
twisterRpc("getdirectmsgs", [defaultScreenName, 1, followList],
function(req, dmUsers) {
var updated = false;
for( var u in dmUsers ) {
if( dmUsers.hasOwnProperty(u) ) {
var dmData = dmUsers[u][0];
if( (u in _lastDMIdPerUser) && (u in _newDMsPerUser) ) {
if( dmData.id != _lastDMIdPerUser[u] ) {
_newDMsPerUser[u] += (dmData.id - _lastDMIdPerUser[u]);
updated = true;
_newDMsUpdated = true;
}
} else {
_newDMsPerUser[u] = dmData.id+1;
updated = true;
_newDMsUpdated = true;
}
_lastDMIdPerUser[u] = dmData.id;
}
}
if( updated ) {
if( _newDMsUpdated ) {
saveDMsToStorage();
$.MAL.updateNewDMsUI(getNewDMsCount());
}

8
js/twister_timeline.js

@ -279,13 +279,13 @@ function processLastHave(userHaves) @@ -279,13 +279,13 @@ function processLastHave(userHaves)
function processNewPostsConfirmation(expected, posts)
{
//we don't want to produce alert for the posts that won't be displayed
var p2h = 0;
var pnp = 0;
for( var i = posts.length-1; i >= 0; i-- ) {
if (willBeHidden(posts[i])) {
p2h++;
if (willBeHidden(posts[i]) || posts[i]['userpost']['n'] === defaultScreenName) {
pnp++;
}
}
_newPostsPending += posts.length - p2h;
_newPostsPending += posts.length - pnp;
if( _newPostsPending ) {
$.MAL.reportNewPosts(_newPostsPending);
}

1
login.html

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
<script src="js/jquery.jsonrpcclient.js"></script>
<script src="js/jquery.storageapi.js"></script>
<script src="js/options.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/twister_network.js"></script>

1
network.html

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
<script src="js/jquery.jsonrpcclient.js"></script>
<script src="js/jquery.storageapi.js"></script>
<script src="js/options.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/twister_user.js"></script>

13
options.html

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
<script src="js/jquery.jsonrpcclient.js"></script>
<script src="js/jquery.storageapi.js"></script>
<script src="js/options.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/twister_network.js"></script>
@ -18,6 +19,7 @@ @@ -18,6 +19,7 @@
<script src="js/interface_login.js"></script>
<script src="js/polyglot.min.js"></script>
<script src="js/interface_localization.js"></script>
<script>$(function(){
initInterfaceCommon();
$.Options.InitOptions();})
@ -54,7 +56,7 @@ @@ -54,7 +56,7 @@
<input id="t-2" name="option_tab" type="radio" class="selectable_theme theme_nin"/>
<label for="t-2" class="tabs selectable_theme theme_nin">Theme</label>
<input id="t-3" name="option_tab" type="radio" class="selectable_theme theme_nin"/>
<label for="t-3" class="tabs selectable_theme theme_nin">Sound</label>
<label for="t-3" class="tabs selectable_theme theme_nin">Notifications</label>
<input id="t-4" name="option_tab" type="radio" class="selectable_theme theme_nin"/>
<label for="t-4" class="tabs selectable_theme theme_nin">Keys</label>
<input id="t-5" name="option_tab" type="radio" class="selectable_theme theme_nin"/>
@ -108,8 +110,7 @@ @@ -108,8 +110,7 @@
</div>
</div>
<div class="sounds">
<div class="notifications">
<div class="module">
<p class="label"> Sound notifications </p>
<div>
@ -141,6 +142,12 @@ @@ -141,6 +142,12 @@
<audio id="player"></audio>
</div>
</div>
<div class="module">
<p class="label"> Desktop notifications </p>
<div>
<button id="notifications-desktop-test">Test</button>
</div>
</div>
</div>
<div class="keys">

1
profile-edit.html

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
<script src="js/jquery.jsonrpcclient.js"></script>
<script src="js/jquery.storageapi.js"></script>
<script src="js/options.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>

2
theme_nin/css/style.css

@ -1704,7 +1704,7 @@ button.disabled:hover, .mini-profile-actions span.disabled:hover, a.button.disab @@ -1704,7 +1704,7 @@ button.disabled:hover, .mini-profile-actions span.disabled:hover, a.button.disab
visibility: hidden;
}
/* line 39, ../sass/_tabs.sass */
.options input#tab_language:checked ~ .tab-content .language, .options input#t-2:checked ~ .tab-content .theme, .options input#t-3:checked ~ .tab-content .sounds, .options input#t-4:checked ~ .tab-content .keys, .options input#t-5:checked ~ .tab-content .postboard-display, .options input#t-6:checked ~ .tab-content .users {
.options input#tab_language:checked ~ .tab-content .language, .options input#t-2:checked ~ .tab-content .theme, .options input#t-3:checked ~ .tab-content .notifications, .options input#t-4:checked ~ .tab-content .keys, .options input#t-5:checked ~ .tab-content .postboard-display, .options input#t-6:checked ~ .tab-content .users {
position: relative;
z-index: 10;
opacity: 1;

2
theme_nin/sass/_tabs.sass

@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
input
&#tab_language:checked ~ .tab-content .language,
&#t-2:checked ~ .tab-content .theme,
&#t-3:checked ~ .tab-content .sounds,
&#t-3:checked ~ .tab-content .notifications,
&#t-4:checked ~ .tab-content .keys,
&#t-5:checked ~ .tab-content .postboard-display,
&#t-6:checked ~ .tab-content .users

Loading…
Cancel
Save