瀏覽代碼

ComposeArea: Refactorings

Danilo Bargen 6 年之前
父節點
當前提交
9da4088bd0
共有 1 個文件被更改,包括 49 次插入77 次删除
  1. 49 77
      src/directives/compose_area.ts

+ 49 - 77
src/directives/compose_area.ts

@@ -16,15 +16,14 @@
  */
 
 import {ComposeArea} from '@threema/compose-area';
-import * as twemoji from 'twemoji';
 
-import {hasValue, isActionTrigger, logAdapter, replaceWhitespace} from '../helpers';
-import {emojify, emojifyNew, shortnameToUnicode} from '../helpers/emoji';
+import {isActionTrigger} from '../helpers';
+import {emojifyNew, shortnameToUnicode} from '../helpers/emoji';
 import {BrowserService} from '../services/browser';
 import {ReceiverService} from '../services/receiver';
 import {StringService} from '../services/string';
 import {TimeoutService} from '../services/timeout';
-import {isElementNode, isEmojiInfo, isTextNode} from '../typeguards';
+import {isEmojiInfo} from '../typeguards';
 
 /**
  * The compose area where messages are written.
@@ -76,7 +75,7 @@ export default [
 
                 receiver: '<receiver',
             },
-            link: function(scope: any, element) {
+            link: function(scope: any, wrapper: JQLite) {
                 // Logging
                 const logTag = '[Directives.ComposeArea]';
 
@@ -85,13 +84,13 @@ export default [
                 const TRIGGER_ACTIVE_CSS_CLASS = 'is-active';
 
                 // Elements
-                const wrapper: any = element;
-                const composeDiv: any = angular.element(element[0].querySelector('div.compose'));
-                const emojiTrigger: any = angular.element(element[0].querySelector('i.emoji-trigger'));
-                const emojiKeyboard: any = angular.element(element[0].querySelector('.emoji-keyboard'));
-                const sendTrigger: any = angular.element(element[0].querySelector('i.send-trigger'));
-                const fileTrigger: any = angular.element(element[0].querySelector('i.file-trigger'));
-                const fileInput: any = angular.element(element[0].querySelector('input.file-input'));
+                const select = (selector) => angular.element(wrapper[0].querySelector(selector));
+                const composeDiv = select('div.compose') as JQuery<HTMLElement>;
+                const emojiTrigger = select('i.emoji-trigger') as JQuery<HTMLElement>;
+                const emojiKeyboard = select('.emoji-keyboard') as JQuery<HTMLElement>;
+                const sendTrigger = select('i.send-trigger') as JQuery<HTMLElement>;
+                const fileTrigger = select('i.file-trigger') as JQuery<HTMLElement>;
+                const fileInput = select('input.file-input') as JQuery<HTMLInputElement>;
 
                 // Initialize compose area lib
                 const composeArea = ComposeArea.bind_to(composeDiv[0], CONFIG.DEBUG ? 'debug' : 'warn');
@@ -117,7 +116,7 @@ export default [
                         sendTrigger.removeClass(TRIGGER_ENABLED_CSS_CLASS);
                         emojiTrigger.removeClass(TRIGGER_ENABLED_CSS_CLASS);
                         fileTrigger.removeClass(TRIGGER_ENABLED_CSS_CLASS);
-                        composeDiv.attr('contenteditable', false);
+                        composeDiv.attr('contenteditable', 'false');
                         if (emojiKeyboard.hasClass('active')) {
                             hideEmojiPicker();
                         }
@@ -129,7 +128,7 @@ export default [
                         }
                         emojiTrigger.addClass(TRIGGER_ENABLED_CSS_CLASS);
                         fileTrigger.addClass(TRIGGER_ENABLED_CSS_CLASS);
-                        composeDiv.attr('contenteditable', true);
+                        composeDiv.attr('contenteditable', 'true');
                     }
                 }
 
@@ -146,38 +145,6 @@ export default [
                     },
                 );
 
-                /**
-                 * Stop propagation of click events and hold htmlElement of the emojipicker
-                 */
-                const EmojiPickerContainer = (function() {
-                    let instance;
-
-                    function click(e) {
-                        e.stopPropagation();
-                    }
-
-                    return {
-                        get: function() {
-                            if (instance === undefined) {
-                                instance = {
-                                    htmlElement: wrapper[0].querySelector('div.twemoji-picker'),
-                                };
-                                // append stop propagation
-                                angular.element(instance.htmlElement).on('click', click);
-
-                            }
-                            return instance;
-                        },
-                        destroy: function() {
-                            if (instance !== undefined) {
-                                // remove stop propagation
-                                angular.element(instance.htmlElement).off('click', click);
-                                instance = undefined;
-                            }
-                        },
-                    };
-                })();
-
                 // Typing events
                 let stopTypingTimer: ng.IPromise<void> = null;
 
@@ -283,11 +250,11 @@ export default [
 
                 let isComposing = false;
 
-                function onCompositionStart(ev: KeyboardEvent): void {
+                function onCompositionStart(ev: CompositionEvent): void {
                     isComposing = true;
                 }
 
-                function onCompositionEnd(ev: KeyboardEvent): void {
+                function onCompositionEnd(ev: CompositionEvent): void {
                     isComposing = false;
                 }
 
@@ -503,19 +470,19 @@ export default [
 
                 // Show emoji picker element
                 function showEmojiPicker() {
-                    const emojiPicker: HTMLElement = EmojiPickerContainer.get().htmlElement;
+                    const emojiPicker = wrapper[0].querySelector('div.twemoji-picker');
 
                     // Show
                     emojiKeyboard.addClass('active');
                     emojiTrigger.addClass(TRIGGER_ACTIVE_CSS_CLASS);
 
                     // Find some selectors
-                    const allEmoji: any = angular.element(emojiPicker.querySelectorAll('.content .em'));
-                    const allEmojiTabs: any = angular.element(emojiPicker.querySelectorAll('.tab label img'));
+                    const allEmoji = angular.element(emojiPicker.querySelectorAll('.content .em'));
+                    const allEmojiTabs = angular.element(emojiPicker.querySelectorAll('.tab label img'));
 
                     // Add event handlers
-                    allEmoji.on('click', onEmojiChosen);
-                    allEmojiTabs.on('keydown', onEmojiTabSelected);
+                    allEmoji.on('click', onEmojiChosen as any);
+                    allEmojiTabs.on('keydown', onEmojiTabSelected as any);
 
                     // Focus compose area again
                     $timeout(() => composeArea.focus());
@@ -523,24 +490,23 @@ export default [
 
                 // Hide emoji picker element
                 function hideEmojiPicker() {
-                    const emojiPicker: HTMLElement = EmojiPickerContainer.get().htmlElement;
+                    const emojiPicker = wrapper[0].querySelector('div.twemoji-picker');
 
                     // Hide
                     emojiKeyboard.removeClass('active');
                     emojiTrigger.removeClass(TRIGGER_ACTIVE_CSS_CLASS);
 
                     // Find some selectors
-                    const allEmoji: any = angular.element(emojiPicker.querySelectorAll('.content .em'));
-                    const allEmojiTabs: any = angular.element(emojiPicker.querySelectorAll('.tab label img'));
+                    const allEmoji = angular.element(emojiPicker.querySelectorAll('.content .em'));
+                    const allEmojiTabs = angular.element(emojiPicker.querySelectorAll('.tab label img'));
 
                     // Remove event handlers
-                    allEmoji.off('click', onEmojiChosen);
-                    allEmojiTabs.off('keydown', onEmojiTabSelected);
-                    EmojiPickerContainer.destroy();
+                    allEmoji.off('click', onEmojiChosen as any);
+                    allEmojiTabs.off('keydown', onEmojiTabSelected as any);
                 }
 
                 // Emoji trigger is clicked
-                function onEmojiTrigger(ev: UIEvent): void {
+                function onEmojiTrigger(ev: KeyboardEvent): void {
                     ev.stopPropagation();
                     if (chatBlocked) {
                         hideEmojiPicker();
@@ -557,14 +523,14 @@ export default [
                 // Emoji is chosen
                 function onEmojiChosen(ev: MouseEvent): void {
                     ev.stopPropagation();
-                    insertSingleEmojiString(this.textContent);
+                    insertSingleEmojiString((ev.target as Element).textContent);
                 }
 
                 // Emoji tab is selected
                 function onEmojiTabSelected(ev: KeyboardEvent): void {
                     if (ev.key === ' ' || ev.key === 'Enter') {
                         // Warning: Hacky
-                        this.parentElement.previousElementSibling.checked = true;
+                        (ev.target as any).parentElement.previousElementSibling.checked = true;
                     }
                 }
 
@@ -632,7 +598,7 @@ export default [
                     if (chatBlocked) {
                         return;
                     }
-                    const input = element[0].querySelector('.file-input') as HTMLInputElement;
+                    const input = wrapper[0].querySelector('.file-input') as HTMLInputElement;
                     input.click();
                 }
 
@@ -661,10 +627,10 @@ export default [
                 }
 
                 // Handle typing events
-                composeDiv.on('compositionstart', onCompositionStart);
-                composeDiv.on('compositionend', onCompositionEnd);
-                composeDiv.on('keydown', onKeyDown);
-                composeDiv.on('keyup', onKeyUp);
+                composeDiv.on('compositionstart', onCompositionStart as any);
+                composeDiv.on('compositionend', onCompositionEnd as any);
+                composeDiv.on('keydown', onKeyDown as any);
+                composeDiv.on('keyup', onKeyUp as any);
 
                 // Handle selection change
                 document.addEventListener('selectionchange', () => {
@@ -672,21 +638,25 @@ export default [
                 });
 
                 // Handle paste event
-                composeDiv.on('paste', onPaste);
+                composeDiv.on('paste', onPaste as any);
 
                 // Handle click on emoji trigger
-                emojiTrigger.on('click', onEmojiTrigger);
-                emojiTrigger.on('keypress', (ev: KeyboardEvent) => {
+                emojiTrigger.on('click', onEmojiTrigger as any);
+                emojiTrigger[0].addEventListener('keypress', (ev: KeyboardEvent) => {
                     if (isActionTrigger(ev)) {
-                        onEmojiTrigger(ev);
+                        $rootScope.$apply(() => {
+                            onEmojiTrigger(ev);
+                        });
                     }
                 });
 
                 // Handle click on file trigger
-                fileTrigger.on('click', onFileTrigger);
-                fileTrigger.on('keypress', (ev: KeyboardEvent) => {
+                fileTrigger.on('click', onFileTrigger as any);
+                fileTrigger[0].addEventListener('keypress', (ev: any) => {
                     if (isActionTrigger(ev)) {
-                        onFileTrigger(ev);
+                        $rootScope.$apply(() => {
+                            onFileTrigger(ev);
+                        });
                     }
                 });
 
@@ -694,10 +664,12 @@ export default [
                 fileInput.on('change', onFileSelected);
 
                 // Handle click on send trigger
-                sendTrigger.on('click', onSendTrigger);
-                sendTrigger.on('keypress', (ev: KeyboardEvent) => {
+                sendTrigger.on('click', onSendTrigger as any);
+                sendTrigger[0].addEventListener('keypress', (ev: any) => {
                     if (isActionTrigger(ev)) {
-                        onSendTrigger(ev);
+                        $rootScope.$apply(() => {
+                            onSendTrigger(ev);
+                        });
                     }
                 });