Browse Source

Supported smart notifications

master
Igor Zhukov 9 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']) @@ -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.send.enter = settings[2] ? '' : '1';
$scope.send.enter = settings[1] ? '' : '1';
if (settings[1]) {
$scope.notify.volume = 0;
} else if (settings[3] !== false) {
$scope.notify.volume = settings[3] > 0 && settings[3] <= 1.0 ? settings[3] : 0;
if (settings[2] !== false) {
$scope.notify.volume = settings[2] > 0 && settings[2] <= 1.0 ? settings[2] : 0;
} else {
$scope.notify.volume = 0.5;
}
$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 () {
return 1 + Math.ceil(($scope.notify.volume - 0.1) / 0.33);
@ -2952,7 +2950,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2952,7 +2950,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.$watch('notify.volume', function (newValue, oldValue) {
if (newValue !== oldValue) {
Storage.set({notify_volume: newValue});
Storage.remove('notify_nosound');
$rootScope.$broadcast('settings_changed');
NotificationsManager.clear();
if (testSoundPromise) {
@ -2972,6 +2970,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2972,6 +2970,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} else {
Storage.set({notify_nodesktop: true});
}
$rootScope.$broadcast('settings_changed');
}
$scope.togglePreview = function () {
@ -2982,6 +2981,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2982,6 +2981,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} else {
Storage.set({notify_nopreview: true});
}
$rootScope.$broadcast('settings_changed');
}
$scope.toggleVibrate = function () {
@ -2992,6 +2992,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2992,6 +2992,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
} else {
Storage.set({notify_novibrate: true});
}
$rootScope.$broadcast('settings_changed');
}
$scope.toggleCtrlEnter = function (newValue) {

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

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

229
app/js/services.js

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

3
app/partials/desktop/reply_message.html

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

Loading…
Cancel
Save