Browse Source

Supported smart notifications

master
Igor Zhukov 10 years ago
parent
commit
d2feac1f53
  1. 19
      app/js/controllers.js
  2. 1
      app/js/locales/en-us.json
  3. 229
      app/js/services.js
  4. 3
      app/partials/desktop/reply_message.html

19
app/js/controllers.js

@ -2919,22 +2919,20 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}); });
}; };
Storage.get('notify_nodesktop', 'notify_nosound', 'send_ctrlenter', 'notify_volume', 'notify_novibrate', 'notify_nopreview').then(function (settings) { Storage.get('notify_nodesktop', 'send_ctrlenter', 'notify_volume', 'notify_novibrate', 'notify_nopreview').then(function (settings) {
$scope.notify.desktop = !settings[0]; $scope.notify.desktop = !settings[0];
$scope.send.enter = settings[2] ? '' : '1'; $scope.send.enter = settings[1] ? '' : '1';
if (settings[1]) { if (settings[2] !== false) {
$scope.notify.volume = 0; $scope.notify.volume = settings[2] > 0 && settings[2] <= 1.0 ? settings[2] : 0;
} else if (settings[3] !== false) {
$scope.notify.volume = settings[3] > 0 && settings[3] <= 1.0 ? settings[3] : 0;
} else { } else {
$scope.notify.volume = 0.5; $scope.notify.volume = 0.5;
} }
$scope.notify.canVibrate = NotificationsManager.getVibrateSupport(); $scope.notify.canVibrate = NotificationsManager.getVibrateSupport();
$scope.notify.vibrate = !settings[4]; $scope.notify.vibrate = !settings[3];
$scope.notify.preview = !settings[5]; $scope.notify.preview = !settings[4];
$scope.notify.volumeOf4 = function () { $scope.notify.volumeOf4 = function () {
return 1 + Math.ceil(($scope.notify.volume - 0.1) / 0.33); return 1 + Math.ceil(($scope.notify.volume - 0.1) / 0.33);
@ -2952,7 +2950,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$watch('notify.volume', function (newValue, oldValue) { $scope.$watch('notify.volume', function (newValue, oldValue) {
if (newValue !== oldValue) { if (newValue !== oldValue) {
Storage.set({notify_volume: newValue}); Storage.set({notify_volume: newValue});
Storage.remove('notify_nosound'); $rootScope.$broadcast('settings_changed');
NotificationsManager.clear(); NotificationsManager.clear();
if (testSoundPromise) { if (testSoundPromise) {
@ -2972,6 +2970,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} else { } else {
Storage.set({notify_nodesktop: true}); Storage.set({notify_nodesktop: true});
} }
$rootScope.$broadcast('settings_changed');
} }
$scope.togglePreview = function () { $scope.togglePreview = function () {
@ -2982,6 +2981,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} else { } else {
Storage.set({notify_nopreview: true}); Storage.set({notify_nopreview: true});
} }
$rootScope.$broadcast('settings_changed');
} }
$scope.toggleVibrate = function () { $scope.toggleVibrate = function () {
@ -2992,6 +2992,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} else { } else {
Storage.set({notify_novibrate: true}); Storage.set({notify_novibrate: true});
} }
$rootScope.$broadcast('settings_changed');
} }
$scope.toggleCtrlEnter = function (newValue) { $scope.toggleCtrlEnter = function (newValue) {

1
app/js/locales/en-us.json

@ -255,6 +255,7 @@
"conversation_kicked_user_message": "removed user", "conversation_kicked_user_message": "removed user",
"conversation_joined_by_link": "joined group", "conversation_joined_by_link": "joined group",
"conversation_message_sent": "sent you a message", "conversation_message_sent": "sent you a message",
"conversation_forwarded_X_messages": "{'one': 'forwarded {} message', 'other': 'forwarded {} messages'}",
"conversation_unknown_user": "Somebody", "conversation_unknown_user": "Somebody",
"conversation_unknown_chat": "Unknown chat", "conversation_unknown_chat": "Unknown chat",

229
app/js/services.js

@ -840,6 +840,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
midnightOffseted = new Date(), midnightOffseted = new Date(),
midnightOffset; midnightOffset;
Storage.get('server_time_offset').then(function (to) {
if (to) {
serverTimeOffset = to;
}
});
var maxSeenID = false; var maxSeenID = false;
if (Config.Modes.packed) { if (Config.Modes.packed) {
@ -848,13 +853,9 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}); });
} }
Storage.get('server_time_offset').then(function (to) {
if (to) {
serverTimeOffset = to;
}
});
var dateOrTimeFilter = $filter('dateOrTime'); var dateOrTimeFilter = $filter('dateOrTime');
var fwdMessagesPluralize = _.pluralize('conversation_forwarded_X_messages');
midnightOffseted.setHours(0); midnightOffseted.setHours(0);
midnightOffseted.setMinutes(0); midnightOffseted.setMinutes(0);
@ -966,9 +967,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (message.unread && !message.out) { if (message.unread && !message.out) {
NotificationsManager.getPeerMuted(notifyPeer).then(function (muted) { NotificationsManager.getPeerMuted(notifyPeer).then(function (muted) {
if (!muted) { if (!muted) {
Storage.get('notify_nopreview').then(function (no_preview) { notifyAboutMessage(message);
notifyAboutMessage(message, no_preview);
});
} }
}); });
} }
@ -1375,6 +1374,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
} }
NotificationsManager.soundReset(AppPeersManager.getPeerString(peerID))
return historyStorage.readPromise; return historyStorage.readPromise;
} }
@ -2255,7 +2256,9 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
} }
function notifyAboutMessage (message, no_preview) { function notifyAboutMessage (message, options) {
options = options || {};
var peerID = getMessagePeer(message); var peerID = getMessagePeer(message);
var fromUser = AppUsersManager.getUser(message.from_id); var fromUser = AppUsersManager.getUser(message.from_id);
var fromPhoto = AppUsersManager.getUserPhoto(message.from_id, 'User'); var fromPhoto = AppUsersManager.getUserPhoto(message.from_id, 'User');
@ -2264,8 +2267,12 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
notificationMessage = false, notificationMessage = false,
notificationPhoto; notificationPhoto;
if (message.message) { var notifySettings = NotificationsManager.getNotifySettings();
if (no_preview) {
if (message.fwd_from_id && options.fwd_count) {
notificationMessage = fwdMessagesPluralize(options.fwd_count);
} else if (message.message) {
if (notifySettings.nopreview) {
notificationMessage = _('conversation_message_sent'); notificationMessage = _('conversation_message_sent');
} else { } else {
notificationMessage = RichTextProcessor.wrapPlainText(message.message); notificationMessage = RichTextProcessor.wrapPlainText(message.message);
@ -2303,6 +2310,9 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
case 'messageActionChatDeleteUser': case 'messageActionChatDeleteUser':
notificationMessage = message.action.user_id == message.from_id ? _('conversation_left_group') : _('conversation_kicked_user_message_raw'); notificationMessage = message.action.user_id == message.from_id ? _('conversation_left_group') : _('conversation_kicked_user_message_raw');
break; break;
case 'messageActionChatJoinedByLink':
notificationMessage = _('conversation_joined_by_link');
break;
} }
} }
@ -2380,6 +2390,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var newMessagesToHandle = {}; var newMessagesToHandle = {};
var newDialogsHandlePromise = false; var newDialogsHandlePromise = false;
var newDialogsToHandle = {}; var newDialogsToHandle = {};
var notificationsHandlePromise = false;
var notificationsToHandle = {};
function handleNewMessages () { function handleNewMessages () {
$timeout.cancel(newMessagesHandlePromise); $timeout.cancel(newMessagesHandlePromise);
@ -2395,6 +2407,31 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
newDialogsToHandle = {}; newDialogsToHandle = {};
} }
function handleNotifications () {
$timeout.cancel(notificationsHandlePromise);
notificationsHandlePromise = false;
var timeout = $rootScope.idle.isIDLE && StatusManager.isOtherDeviceActive() ? 30000 : 1000;
angular.forEach(notificationsToHandle, function (notifyPeerToHandle) {
notifyPeerToHandle.isMutedPromise.then(function (muted) {
var topMessage = notifyPeerToHandle.top_message;
if (muted ||
!topMessage.unread) {
return;
}
setTimeout(function () {
if (topMessage.unread) {
notifyAboutMessage(topMessage, {
fwd_count: notifyPeerToHandle.fwd_count
});
}
}, timeout);
});
});
notificationsToHandle = {};
}
$rootScope.$on('apiUpdate', function (e, update) { $rootScope.$on('apiUpdate', function (e, update) {
// if (update._ != 'updateUserStatus') { // if (update._ != 'updateUserStatus') {
// console.log('on apiUpdate', update); // console.log('on apiUpdate', update);
@ -2490,17 +2527,28 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if (inboxUnread && ($rootScope.selectedPeerID != peerID || $rootScope.idle.isIDLE)) { if (inboxUnread && ($rootScope.selectedPeerID != peerID || $rootScope.idle.isIDLE)) {
var notifyPeer = message.flags & 16 ? message.from_id : peerID; var notifyPeer = message.flags & 16 ? message.from_id : peerID;
var isMutedPromise = NotificationsManager.getPeerMuted(notifyPeer); var notifyPeerToHandle = notificationsToHandle[notifyPeer];
var timeout = $rootScope.idle.isIDLE && StatusManager.isOtherDeviceActive() ? 30000 : 1000; if (notifyPeerToHandle === undefined) {
setTimeout(function () { notifyPeerToHandle = notificationsToHandle[notifyPeer] = {
isMutedPromise.then(function (muted) { isMutedPromise: NotificationsManager.getPeerMuted(notifyPeer),
if (message.unread && !muted) { fwd_count: 0,
Storage.get('notify_nopreview').then(function (no_preview) { from_id: 0
notifyAboutMessage(message, no_preview); };
}); }
}
}) if (notifyPeerToHandle.from_id != message.from_id) {
}, timeout); notifyPeerToHandle.from_id = message.from_id;
notifyPeerToHandle.fwd_count = 0;
}
if (message.fwd_from_id) {
notifyPeerToHandle.fwd_count++;
}
notifyPeerToHandle.top_message = message;
if (!notificationsHandlePromise) {
notificationsHandlePromise = $timeout(handleNotifications, 1000);
}
} }
incrementMaxSeenID(message.id); incrementMaxSeenID(message.id);
@ -4522,6 +4570,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var notificationsShown = {}; var notificationsShown = {};
var notificationIndex = 0; var notificationIndex = 0;
var notificationsCount = 0; var notificationsCount = 0;
var soundsPlayed = {};
var vibrateSupport = !!navigator.vibrate; var vibrateSupport = !!navigator.vibrate;
var nextSoundAt = false; var nextSoundAt = false;
var prevSoundVolume = false; var prevSoundVolume = false;
@ -4534,6 +4583,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
titlePromise; titlePromise;
var prevFavicon; var prevFavicon;
var settings = {};
$rootScope.$watch('idle.isIDLE', function (newVal) { $rootScope.$watch('idle.isIDLE', function (newVal) {
if (!newVal) { if (!newVal) {
notificationsClear(); notificationsClear();
@ -4596,14 +4647,34 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
notify: notify, notify: notify,
cancel: notificationCancel, cancel: notificationCancel,
clear: notificationsClear, clear: notificationsClear,
soundReset: notificationSoundReset,
getPeerSettings: getPeerSettings, getPeerSettings: getPeerSettings,
getPeerMuted: getPeerMuted, getPeerMuted: getPeerMuted,
savePeerSettings: savePeerSettings, savePeerSettings: savePeerSettings,
updatePeerSettings: updatePeerSettings, updatePeerSettings: updatePeerSettings,
updateNotifySettings: updateNotifySettings,
getNotifySettings: getNotifySettings,
getVibrateSupport: getVibrateSupport, getVibrateSupport: getVibrateSupport,
testSound: playSound testSound: playSound
}; };
function updateNotifySettings () {
Storage.get('notify_nodesktop', 'notify_volume', 'notify_novibrate', 'notify_nopreview').then(function (updSettings) {
settings.nodesktop = updSettings[0];
settings.volume = updSettings[1] === false
? 0.5
: updSettings[1];
settings.novibrate = updSettings[2];
settings.nopreview = updSettings[3];
});
}
function getNotifySettings () {
return settings;
}
function getPeerSettings (peerID) { function getPeerSettings (peerID) {
if (peerSettings[peerID] !== undefined) { if (peerSettings[peerID] !== undefined) {
return peerSettings[peerID]; return peerSettings[peerID];
@ -4660,7 +4731,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
function start () { function start () {
updateNotifySettings();
$rootScope.$on('settings_changed', updateNotifySettings);
registerDevice(); registerDevice();
if (!notificationsUiSupport) { if (!notificationsUiSupport) {
return false; return false;
} }
@ -4695,70 +4769,75 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
notificationsCount++; notificationsCount++;
Storage.get('notify_nosound', 'notify_volume').then(function (settings) { var now = tsNow();
if (!settings[0] && settings[1] === false || settings[1] > 0) { if (settings.volume > 0 &&
playSound(settings[1] || 0.5); (
} !data.tag ||
}) !soundsPlayed[data.tag] ||
now > soundsPlayed[data.tag] + 60000
)
) {
playSound(settings.volume);
soundsPlayed[data.tag] = now;
}
if (!notificationsUiSupport || if (!notificationsUiSupport ||
'Notification' in window && Notification.permission !== 'granted') { 'Notification' in window && Notification.permission !== 'granted') {
return false; return false;
} }
Storage.get('notify_nodesktop', 'notify_novibrate').then(function (settings) { if (settings.nodesktop) {
if (settings[0]) { if (vibrateSupport && !settings.novibrate) {
if (vibrateSupport && !settings[1]) { navigator.vibrate([200, 100, 200]);
navigator.vibrate([200, 100, 200]);
return;
}
return;
}
var idx = ++notificationIndex,
key = data.key || 'k' + idx,
notification;
if ('Notification' in window) {
notification = new Notification(data.title, {
icon: data.image || '',
body: data.message || '',
tag: data.tag || ''
});
}
else if ('mozNotification' in navigator) {
notification = navigator.mozNotification.createNotification(data.title, data.message || '', data.image || '');
}
else if (notificationsMsSiteMode) {
window.external.msSiteModeClearIconOverlay();
window.external.msSiteModeSetIconOverlay('img/icons/icon16.png', data.title);
window.external.msSiteModeActivate();
notification = {
index: idx
};
}
else {
return; return;
} }
return;
}
notification.onclick = function () { var idx = ++notificationIndex,
notification.close(); key = data.key || 'k' + idx,
AppRuntimeManager.focus(); notification;
notificationsClear();
if (data.onclick) {
data.onclick();
}
};
notification.onclose = function () { if ('Notification' in window) {
delete notificationsShown[key]; notification = new Notification(data.title, {
notificationsClear(); icon: data.image || '',
body: data.message || '',
tag: data.tag || ''
});
}
else if ('mozNotification' in navigator) {
notification = navigator.mozNotification.createNotification(data.title, data.message || '', data.image || '');
}
else if (notificationsMsSiteMode) {
window.external.msSiteModeClearIconOverlay();
window.external.msSiteModeSetIconOverlay('img/icons/icon16.png', data.title);
window.external.msSiteModeActivate();
notification = {
index: idx
}; };
}
else {
return;
}
if (notification.show) { notification.onclick = function () {
notification.show(); notification.close();
AppRuntimeManager.focus();
notificationsClear();
if (data.onclick) {
data.onclick();
} }
notificationsShown[key] = notification; };
});
notification.onclose = function () {
delete notificationsShown[key];
notificationsClear();
};
if (notification.show) {
notification.show();
}
notificationsShown[key] = notification;
}; };
function playSound (volume) { function playSound (volume) {
@ -4795,6 +4874,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
} }
function notificationSoundReset (tag) {
delete soundsPlayed[tag];
}
function notificationsClear() { function notificationsClear() {
if (notificationsMsSiteMode) { if (notificationsMsSiteMode) {
window.external.msSiteModeClearIconOverlay(); window.external.msSiteModeClearIconOverlay();

3
app/partials/desktop/reply_message.html

@ -49,6 +49,9 @@
<my-i18n-param name="user"><span my-user-link="replyMessage.action.user_id"></span></my-i18n-param> <my-i18n-param name="user"><span my-user-link="replyMessage.action.user_id"></span></my-i18n-param>
</span> </span>
</span> </span>
<span ng-switch-when="messageActionChatJoinedByLink" my-i18n="conversation_joined_by_link"></span>
</span> </span>
<span class="im_reply_message_text" ng-if="replyMessage.message.length" ng-bind-html="replyMessage.richMessage"></span> <span class="im_reply_message_text" ng-if="replyMessage.message.length" ng-bind-html="replyMessage.richMessage"></span>

Loading…
Cancel
Save