فهرست منبع

Support upcoming mention feature (display only)

Silvan Engeler 7 سال پیش
والد
کامیت
c38b2edfc8
8فایلهای تغییر یافته به همراه131 افزوده شده و 5 حذف شده
  1. 2 1
      public/i18n/de.json
  2. 2 1
      public/i18n/en.json
  3. 1 1
      src/directives/message_quote.ts
  4. 1 1
      src/directives/message_text.ts
  5. 35 0
      src/filters.ts
  6. 1 0
      src/sass/app.scss
  7. 10 0
      src/sass/components/_mention.scss
  8. 79 1
      tests/filters.js

+ 2 - 1
public/i18n/de.json

@@ -160,7 +160,8 @@
         "THREEMA_BLOCKED_RECEIVER": "blockiert",
         "DELETE_THREAD": "Chat löschen",
         "DELETE_THREAD_MESSAGE": "{count, plural, one {Möchten Sie wirklich diesen Chat löschen? Die Nachrichten können nicht wiederhergestellt werden.} other {Möchten Sie wirklich # Chats löschen? Die Nachrichten können nicht wiederhergestellt werden.}}",
-        "MUTED": "Keine Benachrichtigungen"
+        "MUTED": "Keine Benachrichtigungen",
+        "ALL": "Alle"
     },
     "messageTypes": {
         "AUDIO_MESSAGE": "Sprachnachricht",

+ 2 - 1
public/i18n/en.json

@@ -160,7 +160,8 @@
         "THREEMA_BLOCKED_RECEIVER": "blocked",
         "DELETE_THREAD": "Delete chat",
         "DELETE_THREAD_MESSAGE": "{count, plural, one {Do you really want to delete this chat? You will not be able to recover the messages.} other {Do you really want to delete # chat(s)? You will not be able to recover the messages.}}",
-        "MUTED": "No notifications"
+        "MUTED": "No notifications",
+        "ALL": "All"
     },
     "messageTypes": {
         "AUDIO_MESSAGE": "Audio Message",

+ 1 - 1
src/directives/message_quote.ts

@@ -36,7 +36,7 @@ export default [
                 <div class="message-quote-content" ng-style="{'border-color': ctrl.contact().color}">
                     <span class="message-name" ng-style="{'color': ctrl.contact().color}"
                         ng-bind-html="ctrl.contact().displayName | emojify"></span>
-                    <span class="message-quote" ng-bind-html="ctrl.quote.text | escapeHtml | markify | emojify | linkify | nlToBr"></span>
+                    <span class="message-quote" ng-bind-html="ctrl.quote.text | escapeHtml | markify | emojify | linkify | mentionify | nlToBr"></span>
                 </div>
             `,
         };

+ 1 - 1
src/directives/message_text.ts

@@ -57,7 +57,7 @@ export default [
                 }
             }],
             template: `
-                <span threema-action ng-bind-html="ctrl.text | escapeHtml | markify | emojify | linkify | nlToBr: ctrl.multiLine"></span>
+                <span threema-action ng-bind-html="ctrl.text | escapeHtml | markify | emojify | mentionify | linkify | nlToBr: ctrl.multiLine"></span>
             `,
         };
     },

+ 35 - 0
src/filters.ts

@@ -126,6 +126,41 @@ angular.module('3ema.filters', [])
     };
 })
 
+/**
+ * Convert mention elements to html elements
+ */
+.filter('mentionify', ['WebClientService', '$translate',
+    function (webClientService: WebClientService, $translate) {
+        return(text) => {
+            if (text !== null && text.length > 10) {
+                let result = text.match(/@\[([\*\@a-zA-Z0-9][\@a-zA-Z0-9]{7})\]/g);
+                if (result !== null) {
+                    result = ([...new Set(result)]);
+                    // Unique
+                    for (let possibleMention of result) {
+                        let identity = possibleMention.substr(2, 8);
+                        let html;
+
+                        if (identity === '@@@@@@@@') {
+                            html = '<span class="mention all">' + $translate.instant('messenger.ALL') + '</span>';
+                        } else {
+                            const contact = webClientService.contacts.get(possibleMention.substr(2, 8));
+                            if (contact !== null) {
+                                html = '<span class="mention contact">' + contact.displayName + '</span>';
+                            }
+                        }
+
+                        if (html !== undefined) {
+                            text = text.replace(
+                                new RegExp(possibleMention.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'), 'g'),
+                                html);
+                        }
+                    }
+                }
+            }
+            return text;
+        };
+}])
 /**
  * Reverse an array.
  */

+ 1 - 0
src/sass/app.scss

@@ -43,6 +43,7 @@
 @import "components/drag_file";
 @import "components/buttons";
 @import "components/mediabox";
+@import "components/mention";
 @import "components/backbutton";
 @import "components/emoji";
 @import "components/battery";

+ 10 - 0
src/sass/components/_mention.scss

@@ -0,0 +1,10 @@
+.mention {
+    background-color: #E0E0E0;
+    padding: 2px 5px;
+    position: relative;
+    -webkit-border-radius:5px;
+    -moz-border-radius:5px;
+    border-radius:5px;
+    box-shadow: 0 1px 1px rgba(0,0,0,0.1);
+    color: black;
+}

+ 79 - 1
tests/filters.js

@@ -4,17 +4,49 @@ describe('Filters', function() {
 
     // Ignoring page reload request
     beforeAll(() => window.onbeforeunload = () => null);
+    let webClientServiceMock = {
+        contacts: {
+            get: function(id) {
+                if (id === 'AAAAAAAA') {
+                    return {
+                        displayName: 'ContactA'
+                    }
+                }
+                else if (id === 'XXXXXXXX') {
+                    return {
+                        displayName: 'ContactX'
+                    }
+                }
+                else if (id === '*AAAAAAA') {
+                    return {
+                        displayName: 'GWContactA'
+                    }
+                }
+                return null;
+            }
+        }
+    };
+
+    let translationMock = {
+        instant: function(label) {
+            return label;
+        }
+    };
 
     beforeEach(function() {
 
         // Load 3ema.filters module
         module('3ema.filters');
 
+        module(function ($provide) {
+            $provide.value('WebClientService', webClientServiceMock);
+            $provide.value('$translate', translationMock);
+        });
+
         // Inject the $filter function
         inject(function(_$filter_) {
             $filter = _$filter_;
         });
-
     });
 
     function testPatterns(filterName, cases) {
@@ -121,4 +153,50 @@ describe('Filters', function() {
 
     });
 
+    describe('mentionify', function() {
+
+
+        this.testPatterns = (cases) => testPatterns('mentionify', cases);
+
+        it('no mentions', () => {
+            this.testPatterns([
+                ['', ''],
+                ['hello my friend', 'hello my friend'],
+                ['@[AAAAAAA]', '@[AAAAAAA]'],
+                ['this is not a valid @[AAAAAAA]', 'this is not a valid @[AAAAAAA]'],
+                ['@[@@@@@@@]', '@[@@@@@@@]'],
+                ['this is not a valid @[@@@@@@@]', 'this is not a valid @[@@@@@@@]'],
+            ]);
+        });
+
+        it('mention - no contacts', () => {
+            this.testPatterns([
+                ['@[BBBBBBBB]', '@[BBBBBBBB]'],
+                ['@[*BBBBBBB]', '@[*BBBBBBB]'],
+            ]);
+        });
+
+        it('mention - contact', () => {
+            this.testPatterns([
+                ['@[AAAAAAAA]', '<span class="mention contact">ContactA</span>'],
+                ['hello @[AAAAAAAA]. @[AAAAAAAA] you are my friend', 'hello <span class="mention contact">ContactA</span>. <span class="mention contact">ContactA</span> you are my friend'],
+                ['@[AAAAAAAA] @[AAAAAAAA] @[AAAAAAAA]', '<span class="mention contact">ContactA</span> <span class="mention contact">ContactA</span> <span class="mention contact">ContactA</span>']
+            ]);
+        });
+
+        it('mention - all', () => {
+            this.testPatterns([
+                ['@[@@@@@@@@]', '<span class="mention all">messenger.ALL</span>'],
+                ['@[@@@@@@@@] your base are belong to us', '<span class="mention all">messenger.ALL</span> your base are belong to us'],
+                ['@[@@@@@@@@] @[@@@@@@@@] @[@@@@@@@@]', '<span class="mention all">messenger.ALL</span> <span class="mention all">messenger.ALL</span> <span class="mention all">messenger.ALL</span>']
+            ]);
+        });
+
+        it('mention - mixed', () => {
+            this.testPatterns([
+                ['@[@@@@@@@@] @[AAAAAAAA] @[BBBBBBBB]', '<span class="mention all">messenger.ALL</span> <span class="mention contact">ContactA</span> @[BBBBBBBB]'],
+            ]);
+        });
+    });
+
 });