Bläddra i källkod

Implement notification sound for incoming messages

Indiana Dschones 8 år sedan
förälder
incheckning
bde6349058

+ 5 - 4
public/i18n/de.json

@@ -165,9 +165,9 @@
         "ERROR_OCCURRED": "Es ist ein Fehler aufgetreten.",
         "FILE_TOO_LARGE": "Aktuell können keine Dateien grösser als 15 MiB über Threema Web versendet werden",
         "TEXT_TOO_LONG": "Diese Nachricht ist zu lang und kann nicht gesendet werden (Maximale Länge {max} Zeichen).",
-        "NOTIFICATION_PERMISSION_DENIED" : "Berechtigung nicht erteilt. Sie müssen die Berechtigungen für Threema Web manuell erteilen.",
-        "NOTIFICATION_PERMISSION_DENIED_LEARN_MORE" : "Mehr erfahren.",
-        "NOTIFICATION_API_NOT_AVAILABLE" : "Ihr Browser unterstützt keine Desktopbenachrichtigungen."
+        "NOTIFICATION_PERMISSION_DENIED": "Sie müssen die Benachrichtigungsberechtigung für Threema Web manuell erteilen, um Desktopbenachrichtigungen erhalten zu können.",
+        "NOTIFICATION_PERMISSION_DENIED_LEARN_MORE": "Mehr erfahren.",
+        "NOTIFICATION_API_NOT_AVAILABLE": "Ihr Browser unterstützt keine Desktopbenachrichtigungen."
     },
     "mimeTypes": {
         "android_apk": "Android-Paket",
@@ -205,7 +205,8 @@
         "notifications": {
             "NOTIFICATIONS": "Benachrichtigungen",
             "SHOW_NOTIFICATIONS": "Desktopbenachrichtigungen anzeigen",
-            "SHOW_PREVIEW": "Nachrichteninhalt in Benachrichtigungen anzeigen"
+            "SHOW_PREVIEW": "Nachrichteninhalt in Benachrichtigungen anzeigen",
+            "PLAY_SOUND": "Ton abspielen"
         }
     }
 }

+ 7 - 6
public/i18n/en.json

@@ -166,9 +166,9 @@
         "ERROR_OCCURRED": "An error occurred.",
         "FILE_TOO_LARGE": "Currently files larger than 15 MiB cannot be sent through Threema Web",
         "TEXT_TOO_LONG": "This message is too long and cannot be sent (Max length {max} characters).",
-        "NOTIFICATION_PERMISSION_DENIED" : "Permission denied. You have to grant the permission for Threema Web manually.",
-        "NOTIFICATION_PERMISSION_DENIED_LEARN_MORE" : "Learn more.",
-        "NOTIFICATION_API_NOT_AVAILABLE" : "Your browser does not support desktop notifications."
+        "NOTIFICATION_PERMISSION_DENIED": "You have to grant the notification permission for Threema Web manually in order to receive desktop notifications.",
+        "NOTIFICATION_PERMISSION_DENIED_LEARN_MORE": "Learn more.",
+        "NOTIFICATION_API_NOT_AVAILABLE": "Your browser does not support desktop notifications."
     },
     "mimeTypes": {
         "android_apk": "Android package",
@@ -204,9 +204,10 @@
     "settings": {
         "SETTINGS":"Settings",
         "notifications": {
-            "NOTIFICATIONS" : "Notifications",
-            "SHOW_NOTIFICATIONS" : "Show desktop notifications",
-            "SHOW_PREVIEW" : "Show message contents in notifications"
+            "NOTIFICATIONS": "Notifications",
+            "SHOW_NOTIFICATIONS": "Show desktop notifications",
+            "SHOW_PREVIEW": "Show message contents in notifications",
+            "PLAY_SOUND": "Play sound"
         }
     }
 }

+ 12 - 5
src/partials/dialog.settings.html

@@ -14,8 +14,8 @@
                 <section>
                     <md-subheader class="md-accent"><span translate>settings.notifications.NOTIFICATIONS</span>
                     </md-subheader>
-                    <md-list flex ng-if="ctrl.notificationApiAvailable && ctrl.notificationPermission !== false">
-                        <md-list-item>
+                    <md-list flex>
+                        <md-list-item ng-if="ctrl.notificationApiAvailable && ctrl.notificationPermission !== false">
                             <md-checkbox
                                     ng-disabled="!ctrl.notificationApiAvailable || ctrl.notificationPermission === false"
                                     ng-model="ctrl.desktopNotifications"
@@ -24,7 +24,7 @@
                                 <span translate>settings.notifications.SHOW_NOTIFICATIONS</span>
                             </md-checkbox>
                         </md-list-item>
-                        <md-list-item ng-if="ctrl.desktopNotifications">
+                        <md-list-item ng-if="ctrl.desktopNotifications && ctrl.notificationApiAvailable && ctrl.notificationPermission !== false">
                             <md-checkbox
                                     ng-disabled="!ctrl.desktopNotifications"
                                     ng-model="ctrl.notificationPreview"
@@ -33,8 +33,15 @@
                                 <span translate>settings.notifications.SHOW_PREVIEW</span>
                             </md-checkbox>
                         </md-list-item>
+                        <md-list-item>
+                            <md-checkbox
+                                    ng-model="ctrl.notificationSound"
+                                    ng-change="ctrl.setWantsSound(ctrl.notificationSound)"
+                                    aria-label="Play notification sound">
+                                <span translate>settings.notifications.PLAY_SOUND</span>
+                            </md-checkbox>
+                        </md-list-item>
                     </md-list>
-
                     <div ng-if="!ctrl.notificationApiAvailable" class="status status-no">
                         <i class="material-icons md-24">error</i>
                         <span translate>error.NOTIFICATION_API_NOT_AVAILABLE</span>
@@ -43,7 +50,7 @@
                         <i class="material-icons md-24">error</i> <span translate>error.NOTIFICATION_PERMISSION_DENIED</span>
                         <a href="https://threema.ch/de/faq/web_notifications"
                            target="_blank" rel="noopener noreferrer">
-                            <span translate>error.NOTIFICATION_PERMISSION_DENIED_LEARN_MORE</span>
+                            <p translate>error.NOTIFICATION_PERMISSION_DENIED_LEARN_MORE</p>
                         </a>
                     </div>
                 </section>

+ 6 - 0
src/partials/messenger.ts

@@ -106,6 +106,7 @@ class SettingsController {
     private notificationApiAvailable: boolean;
     private notificationPermission: boolean;
     private notificationPreview: boolean;
+    private notificationSound: boolean;
 
     constructor($mdDialog: ng.material.IDialogService,
                 $window: ng.IWindowService,
@@ -120,6 +121,7 @@ class SettingsController {
         this.notificationApiAvailable = notificationService.isNotificationApiAvailable();
         this.notificationPermission = notificationService.getNotificationPermission();
         this.notificationPreview = notificationService.getWantsPreview();
+        this.notificationSound = notificationService.getWantsSound();
     }
 
     public cancel(): void {
@@ -147,6 +149,10 @@ class SettingsController {
         this.notificationService.setWantsPreview(notificationPreview);
     }
 
+    public setWantsSound(notificationSound: boolean) {
+        this.notificationService.setWantsSound(notificationSound);
+    }
+
 }
 
 class ConversationController {

+ 6 - 0
src/sass/components/_dialogs.scss

@@ -22,6 +22,12 @@ md-dialog {
     md-dialog-content {
         line-height: 1.3em;
     }
+    .md-subheader-inner {
+        padding-left: 0;
+    }
+    .status {
+        padding-left: 16px;
+    }
 }
 
 md-dialog.send-file-dialog {

+ 0 - 4
src/sass/layout/_main.scss

@@ -329,10 +329,6 @@ md-toast.md-center {
     background-color: transparent;
 }
 
-.md-subheader-inner {
-    padding-left: 0;
-}
-
 md-list-item .md-list-item-inner > md-checkbox .md-label {
     display: inline-block;
     white-space: inherit;

+ 42 - 1
src/services/notification.ts

@@ -21,6 +21,8 @@ export class NotificationService {
 
     private static SETTINGS_NOTIFICATIONS = 'notifications';
     private static SETTINGS_NOTIFICATION_PREVIEW = 'notificationPreview';
+    private static SETTINGS_NOTIFICATION_SOUND = 'notificationSound';
+    private static NOTIFICATION_SOUND = 'public/sounds/notification.mp3';
 
     private $log: ng.ILogService;
     private $window: ng.IWindowService;
@@ -37,6 +39,8 @@ export class NotificationService {
     private notificationAPIAvailable: boolean = null;
     // Whether the user wants notification preview
     private notificationPreview: boolean = null;
+    // Whether the user wants notification sound
+    private notificationSound: boolean = null;
 
     // Cache notifications
     private notificationCache: any = {};
@@ -132,6 +136,7 @@ export class NotificationService {
         this.$log.debug(this.logTag, 'Fetching settings...');
         let notifications = this.retrieveSetting(NotificationService.SETTINGS_NOTIFICATIONS);
         let preview = this.retrieveSetting(NotificationService.SETTINGS_NOTIFICATION_PREVIEW);
+        let sound = this.retrieveSetting(NotificationService.SETTINGS_NOTIFICATION_SOUND);
         if (notifications === 'true') {
             this.$log.debug(this.logTag, 'Desktop notifications:', notifications);
             this.desktopNotifications = true;
@@ -148,12 +153,23 @@ export class NotificationService {
             this.requestNotificationPermission();
         }
         if (preview === 'false') {
+            this.$log.debug(this.logTag, 'Notification preview:', preview);
             this.notificationPreview = false;
         } else {
             // set the flag true if true/nothing or sth. else is in local storage (default setting)
+            this.$log.debug(this.logTag, 'Notification preview:', preview, 'Using default value (true)');
             this.notificationPreview = true;
             this.storeSetting(NotificationService.SETTINGS_NOTIFICATION_PREVIEW, 'true');
         }
+        if (sound === 'true') {
+            this.$log.debug(this.logTag, 'Notification sound:', sound);
+            this.notificationSound = true;
+        } else {
+            // set the flag false if false/nothing or sth. else is in local storage (default setting)
+            this.$log.debug(this.logTag, 'Notification sound:', sound, 'Using default value (false)');
+            this.notificationSound = false;
+            this.storeSetting(NotificationService.SETTINGS_NOTIFICATION_SOUND, 'false');
+        }
     }
 
     /**
@@ -180,6 +196,14 @@ export class NotificationService {
         return this.notificationPreview;
     }
 
+    /**
+     * Returns if the user wants sound when a new message arrives
+     * @returns {boolean}
+     */
+    public getWantsSound(): boolean {
+        return this.notificationSound;
+    }
+
     /**
      * Returns if the notification api is available
      * @returns {boolean}
@@ -209,7 +233,17 @@ export class NotificationService {
     public setWantsPreview(wantsPreview: boolean): void {
         this.$log.debug(this.logTag, 'Requesting preview preference change to', wantsPreview);
         this.notificationPreview = wantsPreview;
-        this.storeSetting(NotificationService.SETTINGS_NOTIFICATION_PREVIEW, wantsPreview.toString());
+        this.storeSetting(NotificationService.SETTINGS_NOTIFICATION_PREVIEW, wantsPreview ? 'true' : 'false');
+    }
+
+    /**
+     * Sets if the user wants sound when a new message arrives
+     * @param wantsSound
+     */
+    public setWantsSound(wantsSound: boolean): void {
+        this.$log.debug(this.logTag, 'Requesting sound preference change to', wantsSound);
+        this.notificationSound = wantsSound;
+        this.storeSetting(NotificationService.SETTINGS_NOTIFICATION_SOUND, wantsSound ? 'true' : 'false');
     }
 
     /**
@@ -243,6 +277,13 @@ export class NotificationService {
      */
     public showNotification(tag: string, title: string, body: string,
                             avatar: string = '/img/threema-64x64.png', clickCallback: any): boolean {
+
+        // Play sound on new message if the user wants to
+        if (this.notificationSound) {
+            const audio = new Audio(NotificationService.NOTIFICATION_SOUND);
+            audio.play();
+        }
+
         // Only show notifications if user granted permission to do so
         if (this.notificationPermission !== true || this.desktopNotifications !== true) {
             return false;