Просмотр исходного кода

Refactor ThreemaAction directve, add support for compose action

Danilo Bargen 8 лет назад
Родитель
Сommit
9dc22cd3cd

+ 8 - 5
src/directives/compose_area.ts

@@ -48,8 +48,8 @@ export default [
                 stopTyping: '=',
                 onTyping: '=',
 
-                // Reference to drafts variable
-                draft: '=',
+                // Reference to initial text and draft
+                initialData: '=',
 
                 // Callback that is called when uploading files
                 onUploading: '=',
@@ -72,9 +72,12 @@ export default [
                 const fileTrigger: any = angular.element(element[0].querySelector('i.file-trigger'));
                 const fileInput: any = angular.element(element[0].querySelector('input.file-input'));
 
-                // Restore drafts
-                if (scope.draft !== undefined) {
-                    composeDiv[0].innerText = scope.draft;
+                // Set initial text
+                if (scope.initialData.initialText) {
+                    composeDiv[0].innerText = scope.initialData.initialText;
+                    scope.initialData.initialText = '';
+                } else if (scope.initialData.draft !== undefined) {
+                    composeDiv[0].innerText = scope.initialData.draft;
                 }
 
                 let caretPosition: {from?: number, to?: number} = null;

+ 1 - 1
src/directives/contact_badge.ts

@@ -46,7 +46,7 @@ export default [
                 this.click = () => {
                     if (this.linked !== undefined
                         && this.linked === true) {
-                        $state.go('messenger.home.conversation', {type: 'contact', id: this.identity});
+                        $state.go('messenger.home.conversation', {type: 'contact', id: this.identity, initParams: null});
                     }
                 };
 

+ 1 - 0
src/directives/distribution_list_badge.ts

@@ -34,6 +34,7 @@ export default [
                     $state.go('messenger.home.conversation', {
                         type: 'distributionList',
                         id: this.distributionListReceiver.id,
+                        initParams: null,
                     });
                 };
             }],

+ 5 - 1
src/directives/group_badge.ts

@@ -49,7 +49,11 @@ export default [
                     }
                 }
                 this.click = () => {
-                    $state.go('messenger.home.conversation', { type: 'group', id: this.groupReceiver.id });
+                    $state.go('messenger.home.conversation', {
+                        type: 'group',
+                        id: this.groupReceiver.id,
+                        initParams: null,
+                    });
                 };
             }],
             template: `

+ 1 - 1
src/directives/message.html

@@ -9,7 +9,7 @@
             eee-type="'contact'"
             eee-receiver="ctrl.contact"
             eee-resolution="ctrl.resolution"
-            ui-sref="messenger.home.conversation({ type: 'contact', id: ctrl.contact.id })"></eee-avatar>
+            ui-sref="messenger.home.conversation({ type: 'contact', id: ctrl.contact.id, initParams: null })"></eee-avatar>
 
     <div class="bubble-triangle"></div>
     <section class="message-body" ng-class="ctrl.message.type + '-message-body'">

+ 61 - 19
src/directives/threema_action.ts

@@ -14,11 +14,59 @@
  * You should have received a copy of the GNU Affero General Public License
  * along with Threema Web. If not, see <http://www.gnu.org/licenses/>.
  */
+import {UriService} from '../services/uri';
 
 export default [
     '$timeout',
     '$state',
-    function($timeout, $state: ng.ui.IStateService) {
+    'UriService',
+    function($timeout, $state: ng.ui.IStateService, uriService: UriService) {
+
+        const validateThreemaId = (id: string): boolean => {
+            return id !== undefined && id !== null && /^[0-9A-Z]{8}/.test(id);
+        };
+
+        const addAction = (params) => {
+            return function(e: Event) {
+                if (!validateThreemaId(params.id)) {
+                    return false;
+                }
+                $state.go('messenger.home.create', {
+                    type: 'contact',
+                    initParams: {
+                        identity: params.id,
+                    },
+                });
+            };
+        };
+
+        const composeAction = (params) => {
+            return function(e: Event) {
+                if (!validateThreemaId(params.id)) {
+                    return false;
+                }
+                const text = params.text || '';
+                $state.go('messenger.home.conversation', {
+                    type: 'contact',
+                    id: params.id,
+                    initParams: {
+                        text: text,
+                    },
+                });
+            };
+        };
+
+        const getThreemaActionHandler = (name: string) => {
+            switch (name) {
+                case 'add':
+                    return addAction;
+                case 'compose':
+                    return composeAction;
+                default:
+                    return null;
+            }
+        };
+
         return {
             restrict: 'A',
             scope: {},
@@ -26,26 +74,20 @@ export default [
                 $timeout(() => {
                     // tslint:disable-next-line: prefer-for-of (see #98)
                     for (let i = 0; i < el[0].childNodes.length; i++) {
-                        const node = el[0].childNodes[i];
+                        const node: HTMLElement = el[0].childNodes[i];
 
                         if (node.nodeType === Node.ELEMENT_NODE
-                            && (node as Element).tagName.toLowerCase() === 'a') {
-
-                            let link = (node as Element).innerHTML;
-
-                            if (link !== undefined) {
-                                let addRegex = /\bthreema:\/\/add\?id=([\w\*]{8})\b/gi;
-
-                                if (link.match(addRegex)) {
-                                    let threemaId = link.replace(addRegex, '$1');
-                                    (node as Element).addEventListener('click', function(e) {
-                                        $state.go('messenger.home.create', {
-                                            type: 'contact',
-                                            initParams: {
-                                                identity: threemaId,
-                                            },
-                                        });
-                                    });
+                            && node.tagName.toLowerCase() === 'a') {
+
+                            const link = (node as HTMLElement).innerText;
+                            if (link !== undefined && link.startsWith('threema://')) {
+                                const matches = (/\bthreema:\/\/([a-z]+)\?([^\s]+)\b/gi).exec(link);
+                                if (matches !== null) {
+                                    const handler = getThreemaActionHandler(matches[1]);
+                                    const params = uriService.parseQueryParams(matches[2]);
+                                    if (handler !== null && params !== null) {
+                                        node.addEventListener('click', handler(params));
+                                    }
                                 }
                             }
                         }

+ 1 - 1
src/partials/messenger.conversation.html

@@ -82,7 +82,7 @@
         <div class="chat-input">
             <compose-area
                     submit="ctrl.submit"
-                    draft="ctrl.draft"
+                    initial-data="ctrl.initialData"
                     on-typing="ctrl.onTyping"
                     start-typing="ctrl.startTyping"
                     stop-typing="ctrl.stopTyping"

+ 2 - 2
src/partials/messenger.navigation.html

@@ -64,7 +64,7 @@
         <li ng-repeat="conversation in ctrl.conversations() | filter:ctrl.searchConversation"
             ng-class="{'unread': conversation.unreadCount > 0,
                 'active': ctrl.isActive(conversation)}"
-            ui-sref="messenger.home.conversation({ type: conversation.type, id: conversation.id })"
+            ui-sref="messenger.home.conversation({ type: conversation.type, id: conversation.id, initParams: null })"
             class="conversation" ng-if="ctrl.isVisible(conversation)">
 
             <section class="avatar-box">
@@ -102,7 +102,7 @@
     <p class="empty" ng-if="ctrl.contacts().length === 0" translate>messenger.NO_CONTACTS_FOUND</p>
     <ul>
         <li ng-repeat="contact in ctrl.contacts() | isNotMe | filter:ctrl.searchContact"
-            ui-sref="messenger.home.conversation({ type: 'contact', id: contact.id })"
+            ui-sref="messenger.home.conversation({ type: 'contact', id: contact.id, initParams: null })"
             class="contact"
             ng-class="{'inactive': contact.state == 'INACTIVE'}">
 

+ 21 - 6
src/partials/messenger.ts

@@ -190,7 +190,10 @@ class ConversationController {
     private hasMore = true;
     private latestRefMsgId: number = null;
     private messages: threema.Message[];
-    private draft: string;
+    public initialData: threema.InitialConversationData = {
+        draft: '',
+        initialText: '',
+    };
     private $translate: ng.translate.ITranslateService;
     private locked = false;
     public maxTextLength: number;
@@ -207,7 +210,7 @@ class ConversationController {
         '$mdDialog', '$mdToast', '$location', '$translate',
         'WebClientService', 'StateService', 'ReceiverService', 'MimeService',
     ];
-    constructor($stateParams,
+    constructor($stateParams: threema.ConversationStateParams,
                 $state: ng.ui.IStateService,
                 $timeout: ng.ITimeoutService,
                 $log: ng.ILogService,
@@ -267,7 +270,7 @@ class ConversationController {
 
         // Set receiver and type
         try {
-            this.receiver = webClientService.receivers.getData($stateParams);
+            this.receiver = webClientService.receivers.getData({type: $stateParams.type, id: $stateParams.id});
             this.type = $stateParams.type;
 
             if (this.receiver.type === undefined) {
@@ -299,7 +302,10 @@ class ConversationController {
                     },
                 );
 
-                this.draft = webClientService.getDraft(this.receiver);
+                this.initialData = {
+                    draft: webClientService.getDraft(this.receiver),
+                    initialText: $stateParams.initParams ? $stateParams.initParams.text : '',
+                };
 
                 if (this.receiver.type === 'contact') {
                     this.isTyping = () => this.webClientService.isTyping(this.receiver as threema.ContactReceiver);
@@ -960,14 +966,22 @@ class ReceiverDetailController {
     }
 
     public chat(): void {
-        this.$state.go('messenger.home.conversation', this.receiver);
+        this.$state.go('messenger.home.conversation', {
+            type: this.receiver.type,
+            id: this.receiver.id,
+            initParams: null,
+        });
     }
 
     public edit(): void {
         if (!this.controllerModel.canEdit()) {
             return;
         }
-        this.$state.go('messenger.home.edit', this.receiver);
+        this.$state.go('messenger.home.edit', {
+            type: this.receiver.type,
+            id: this.receiver.id,
+            initParams: null,
+        });
     }
 
     public goBack(): void {
@@ -1190,6 +1204,7 @@ angular.module('3ema.messenger', ['ngMaterial'])
             templateUrl: 'partials/messenger.conversation.html',
             controller: 'ConversationController',
             controllerAs: 'ctrl',
+            params: {initParams: null},
         })
 
         .state('messenger.home.detail', {

+ 2 - 2
src/services/uri.ts

@@ -26,10 +26,10 @@ export class UriService {
         if (!(typeof query === 'string' || query instanceof String)) {
             return null;
         }
-        if (query.length == 0) {
+        if (query.length === 0) {
             return {};
         }
-        const objStr = '{"' + decodeURI(query).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}';
+        const objStr = '{"' + decodeURI(query).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}';
         return JSON.parse(objStr);
     }
 

+ 5 - 1
src/services/webclient.ts

@@ -2048,7 +2048,11 @@ export class WebClientService {
                 const tag = conversation.type + '-' + conversation.id;
                 const avatar = (sender.avatar && sender.avatar.low) ? sender.avatar.low : null;
                 this.notificationService.showNotification(tag, title, body, avatar, () => {
-                    this.$state.go('messenger.home.conversation', conversation);
+                    this.$state.go('messenger.home.conversation', {
+                        type: conversation.type,
+                        id: conversation.id,
+                        initParams: null,
+                    });
                 });
             });
     }

+ 17 - 3
src/threema.d.ts

@@ -139,6 +139,9 @@ declare namespace threema {
         canChangeMembers?: boolean;
     }
 
+    /**
+     * The base class for a receiver. Only type and id.
+     */
     interface BaseReceiver {
         id: string;
         type: ReceiverType;
@@ -308,8 +311,14 @@ declare namespace threema {
     }
 
     interface CreateReceiverStateParams extends ng.ui.IStateParamsService {
-        type: string;
-        initParams: null | {identity: null};
+        type: ReceiverType;
+        initParams: null | {identity: string | null};
+    }
+
+    interface ConversationStateParams extends ng.ui.IStateParamsService {
+        type: ReceiverType;
+        id: string;
+        initParams: null | {text: string | null};
     }
 
     interface Quote {
@@ -383,6 +392,11 @@ declare namespace threema {
         PUSH_URL: string;
     }
 
+    interface InitialConversationData {
+        draft: string;
+        initialText: string;
+    }
+
     interface BrowserMinVersions {
         FF: number;
         CHROME: number;
@@ -412,7 +426,7 @@ declare namespace threema {
             groups: Map<string, GroupReceiver>;
             distributionLists: Map<string, DistributionListReceiver>;
             get(receiverType: ReceiverType): Receiver | Map<string, Receiver>;
-            getData(receiver: Receiver): Receiver | null;
+            getData(receiver: BaseReceiver): Receiver | null;
             set(data: ReceiverData): void;
             setMe(data: MeReceiver): void;
             setContacts(data: ContactReceiver[]): void;

+ 1 - 1
src/threema/container.ts

@@ -93,7 +93,7 @@ angular.module('3ema.container', [])
         /**
          * Get the receiver matching a certain template.
          */
-        public getData(receiver: threema.Receiver): threema.Receiver | null {
+        public getData(receiver: threema.BaseReceiver): threema.Receiver | null {
             if (receiver.type === 'me') {
                 return this.me.id === receiver.id ? this.me : undefined;
             } else {