Browse Source

Add NotificationService.getAppNotificationSettings

Stay DRY
Danilo Bargen 7 years ago
parent
commit
9f3866b01f
7 changed files with 226 additions and 33 deletions
  1. 1 0
      karma.conf.js
  2. 6 19
      src/filters.ts
  3. 44 0
      src/services/notification.ts
  4. 15 1
      src/threema.d.ts
  5. 31 13
      tests/filters.js
  6. 128 0
      tests/service/notification.js
  7. 1 0
      tests/testsuite.html

+ 1 - 0
karma.conf.js

@@ -21,6 +21,7 @@ module.exports = function(config) {
             'tests/service/string.js',
             'tests/service/browser.js',
             'tests/service/keystore.js',
+            'tests/service/notification.js',
             'tests/helpers.js',
         ],
         customLaunchers: {

+ 6 - 19
src/filters.ts

@@ -17,6 +17,7 @@
 
 import {escapeRegExp, filter} from './helpers';
 import {MimeService} from './services/mime';
+import {NotificationService} from './services/notification';
 import {WebClientService} from './services/webclient';
 
 angular.module('3ema.filters', [])
@@ -404,27 +405,13 @@ angular.module('3ema.filters', [])
  * This will return either 'on', 'off' or 'mention'.
  * The 'until' mode will be processed depending on the expiration timestamp.
  */
-.filter('dndModeSimplified', [function() {
+.filter('dndModeSimplified', ['NotificationService', function(notificationService: NotificationService) {
     return (conversation: threema.Conversation) => {
-        if (!conversation.notifications) {
-            return 'off';
-        }
-        const dnd = conversation.notifications.dnd;
-        switch (dnd.mode) {
-            case threema.NotificationDndMode.On:
-                return 'on';
-            case threema.NotificationDndMode.Mention:
-                return 'mention';
-            case threema.NotificationDndMode.Off:
-                return 'off';
-            case threema.NotificationDndMode.Until:
-                if (!dnd.until || dnd.until <= 0) {
-                    return 'off';
-                }
-                const until: Date = new Date(dnd.until);
-                const now: Date = new Date();
-                return until > now ? 'on' : 'off';
+        const simplified = notificationService.getAppNotificationSettings(conversation);
+        if (simplified.dnd.enabled) {
+            return simplified.dnd.mentionOnly ? 'mention' : 'on';
         }
+        return 'off';
     };
 }])
 

+ 44 - 0
src/services/notification.ts

@@ -252,6 +252,50 @@ export class NotificationService {
         return this.settingsService.retrieveUntrustedKeyValuePair(key);
     }
 
+    /**
+     * Parse the conversation notification settings and return a simplified version.
+     */
+    public getAppNotificationSettings(conversation: threema.Conversation): threema.SimplifiedNotificationSettings {
+        if (!conversation.notifications) {
+            return {
+                sound: {muted: false},
+                dnd: {enabled: false, mentionOnly: false},
+            };
+        }
+
+        const sound = conversation.notifications.sound;
+        const dnd = conversation.notifications.dnd;
+
+        const simpleSound = {
+            muted: !(sound.mode === threema.NotificationSoundMode.Default),
+        };
+
+        const simpleDnd = {
+            enabled: dnd.mode === threema.NotificationDndMode.On,
+            mentionOnly: (dnd.mentionOnly === undefined || dnd.mentionOnly === null) ? false : dnd.mentionOnly,
+        };
+
+        if (dnd.mode === threema.NotificationDndMode.Until) {
+            if (!dnd.until || dnd.until <= 0) {
+                simpleDnd.enabled = false;
+            } else {
+                const until: Date = new Date(dnd.until);
+                const now: Date = new Date();
+                simpleDnd.enabled = until > now;
+            }
+        }
+
+        // Mention only does not make sense if DND is not enabled at all.
+        if (!simpleDnd.enabled) {
+            simpleDnd.mentionOnly = false;
+        }
+
+        return {
+            sound: simpleSound,
+            dnd: simpleDnd,
+        };
+    }
+
     /**
      * Notify the user via Desktop Notification API.
      *

+ 15 - 1
src/threema.d.ts

@@ -343,16 +343,30 @@ declare namespace threema {
 
     interface NotificationDnd {
         mode: NotificationDndMode;
+        mentionOnly?: boolean;
         until?: number;
     }
 
     const enum NotificationDndMode {
         Off = 'off',
         On = 'on',
-        Mention = 'mention',
         Until = 'until',
     }
 
+    /**
+     * A form of the notification settings where things like the "until" mode
+     * have been processed already.
+     */
+    interface SimplifiedNotificationSettings {
+        sound: {
+            muted: boolean,
+        };
+        dnd: {
+            enabled: boolean,
+            mentionOnly: boolean,
+        };
+    }
+
     /**
      * Connection state in the welcome dialog.
      *

+ 31 - 13
tests/filters.js

@@ -47,13 +47,13 @@ describe('Filters', function() {
     };
 
     beforeEach(function() {
-
-        // Load 3ema.filters module
+        module('3ema.services');
         module('3ema.filters');
 
-        module(function ($provide) {
+        module(function($provide) {
             $provide.value('WebClientService', webClientServiceMock);
             $provide.value('$translate', translationMock);
+            $provide.constant('$state', null);
         });
 
         // Inject the $filter function
@@ -304,42 +304,42 @@ describe('Filters', function() {
         it('dnd enabled', () => {
             expect(process(
                 {mode: 'on'},
-                {mode: 'default'},
+                {mode: 'default'}
             )).toEqual('on');
         });
 
         it('dnd enabled (no sound)', () => {
             expect(process(
                 {mode: 'on'},
-                {mode: 'muted'},
+                {mode: 'muted'}
             )).toEqual('on');
         });
 
         it('dnd disabled', () => {
             expect(process(
                 {mode: 'off'},
-                {mode: 'default'},
+                {mode: 'default'}
             )).toEqual('off');
         });
 
         it('dnd disabled (no sound)', () => {
             expect(process(
                 {mode: 'off'},
-                {mode: 'muted'},
+                {mode: 'muted'}
             )).toEqual('off');
         });
 
         it('mention only', () => {
             expect(process(
-                {mode: 'mention'},
-                {mode: 'default'},
+                {mode: 'on', mentionOnly: true},
+                {mode: 'default'}
             )).toEqual('mention');
         });
 
         it('mention only (no sound)', () => {
             expect(process(
-                {mode: 'mention'},
-                {mode: 'muted'},
+                {mode: 'on', mentionOnly: true},
+                {mode: 'muted'}
             )).toEqual('mention');
         });
 
@@ -348,7 +348,7 @@ describe('Filters', function() {
             jasmine.clock().mockDate(new Date(2018, 9, 9, 20, 42));
             expect(process(
                 {mode: 'until', until: +(new Date(2018, 9, 9, 20, 50))},
-                {mode: 'default'},
+                {mode: 'default'}
             )).toEqual('on');
         });
 
@@ -357,7 +357,25 @@ describe('Filters', function() {
             jasmine.clock().mockDate(new Date(2018, 9, 9, 20, 42));
             expect(process(
                 {mode: 'until', until: +(new Date(2018, 9, 9, 19, 50))},
-                {mode: 'default'},
+                {mode: 'default'}
+            )).toEqual('off');
+        });
+
+        it('until (mention only, not expired)', () => {
+            jasmine.clock().install();
+            jasmine.clock().mockDate(new Date(2018, 9, 9, 20, 42));
+            expect(process(
+                {mode: 'until', until: +(new Date(2018, 9, 9, 20, 50)), mentionOnly: true},
+                {mode: 'default'}
+            )).toEqual('mention');
+        });
+
+        it('until (mention only, expired)', () => {
+            jasmine.clock().install();
+            jasmine.clock().mockDate(new Date(2018, 9, 9, 20, 42));
+            expect(process(
+                {mode: 'until', until: +(new Date(2018, 9, 9, 19, 50)), mentionOnly: true},
+                {mode: 'default'}
             )).toEqual('off');
         });
     });

+ 128 - 0
tests/service/notification.js

@@ -0,0 +1,128 @@
+describe('NotificationService', function() {
+
+    let $service;
+
+    // Ignoring page reload request
+    beforeAll(() => window.onbeforeunload = () => null);
+
+    beforeEach(function() {
+        module(($provide) => {
+            $provide.constant('$state', null);
+        });
+
+        module('3ema.services');
+
+        // Inject the service
+        inject(function(NotificationService) {
+            $service = NotificationService;
+        });
+
+    });
+
+    describe('getAppNotificationSettings', function () {
+        let process = (dnd, sound) => {
+            return $service.getAppNotificationSettings({
+                notifications: {dnd: dnd, sound: sound},
+            })
+        };
+
+        it('dnd enabled', () => {
+            const res = process(
+                {mode: 'on'},
+                {mode: 'default'}
+            );
+            expect(res.sound.muted).toEqual(false);
+            expect(res.dnd.enabled).toEqual(true);
+            expect(res.dnd.mentionOnly).toEqual(false);
+        });
+
+        it('dnd enabled (no sound)', () => {
+            const res = process(
+                {mode: 'on'},
+                {mode: 'muted'}
+            );
+            expect(res.sound.muted).toEqual(true);
+            expect(res.dnd.enabled).toEqual(true);
+            expect(res.dnd.mentionOnly).toEqual(false);
+        });
+
+        it('dnd disabled', () => {
+            const res = process(
+                {mode: 'off'},
+                {mode: 'default'}
+            );
+            expect(res.sound.muted).toEqual(false);
+            expect(res.dnd.enabled).toEqual(false);
+            expect(res.dnd.mentionOnly).toEqual(false);
+        });
+
+        it('dnd disabled (no sound)', () => {
+            const res = process(
+                {mode: 'off'},
+                {mode: 'muted'}
+            );
+            expect(res.sound.muted).toEqual(true);
+            expect(res.dnd.enabled).toEqual(false);
+            expect(res.dnd.mentionOnly).toEqual(false);
+        });
+
+        it('mention only', () => {
+            const res = process(
+                {mode: 'on', mentionOnly: true},
+                {mode: 'default'}
+            );
+            expect(res.sound.muted).toEqual(false);
+            expect(res.dnd.enabled).toEqual(true);
+            expect(res.dnd.mentionOnly).toEqual(true);
+        });
+
+        it('until (not expired)', () => {
+            jasmine.clock().install();
+            jasmine.clock().mockDate(new Date(2018, 9, 9, 20, 42));
+            const res = process(
+                {mode: 'until', until: +(new Date(2018, 9, 9, 20, 50))},
+                {mode: 'default'}
+            );
+            expect(res.sound.muted).toEqual(false);
+            expect(res.dnd.enabled).toEqual(true);
+            expect(res.dnd.mentionOnly).toEqual(false);
+        });
+
+        it('until (expired)', () => {
+            jasmine.clock().install();
+            jasmine.clock().mockDate(new Date(2018, 9, 9, 20, 42));
+            const res = process(
+                {mode: 'until', until: +(new Date(2018, 9, 9, 19, 50))},
+                {mode: 'default'}
+            );
+            expect(res.sound.muted).toEqual(false);
+            expect(res.dnd.enabled).toEqual(false);
+            expect(res.dnd.mentionOnly).toEqual(false);
+        });
+
+        it('until (mention only, not expired)', () => {
+            jasmine.clock().install();
+            jasmine.clock().mockDate(new Date(2018, 9, 9, 20, 42));
+            const res = process(
+                {mode: 'until', until: +(new Date(2018, 9, 9, 20, 50)), mentionOnly: true},
+                {mode: 'default'}
+            );
+            expect(res.sound.muted).toEqual(false);
+            expect(res.dnd.enabled).toEqual(true);
+            expect(res.dnd.mentionOnly).toEqual(true);
+        });
+
+        it('until (mention only, expired)', () => {
+            jasmine.clock().install();
+            jasmine.clock().mockDate(new Date(2018, 9, 9, 20, 42));
+            const res = process(
+                {mode: 'until', until: +(new Date(2018, 9, 9, 19, 50)), mentionOnly: true},
+                {mode: 'default'}
+            );
+            expect(res.sound.muted).toEqual(false);
+            expect(res.dnd.enabled).toEqual(false);
+            expect(res.dnd.mentionOnly).toEqual(false);
+        });
+    });
+
+});

+ 1 - 0
tests/testsuite.html

@@ -32,6 +32,7 @@
         <script src="service/string.js"></script>
         <script src="service/browser.js"></script>
         <script src="service/keystore.js"></script>
+        <script src="service/notification.js"></script>
         <script src="helpers.js"></script>
     </head>
     <body>