|
@@ -17,9 +17,10 @@
|
|
|
|
|
|
import * as twemoji from 'twemoji';
|
|
|
|
|
|
-import {extractText, isActionTrigger, logAdapter, replaceWhitespace} from '../helpers';
|
|
|
+import {extractText, hasValue, isActionTrigger, logAdapter, replaceWhitespace} from '../helpers';
|
|
|
import {emojify, 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, isTextNode} from '../typeguards';
|
|
@@ -31,6 +32,7 @@ export default [
|
|
|
'BrowserService',
|
|
|
'StringService',
|
|
|
'TimeoutService',
|
|
|
+ 'ReceiverService',
|
|
|
'$timeout',
|
|
|
'$translate',
|
|
|
'$mdDialog',
|
|
@@ -40,6 +42,7 @@ export default [
|
|
|
function(browserService: BrowserService,
|
|
|
stringService: StringService,
|
|
|
timeoutService: TimeoutService,
|
|
|
+ receiverService: ReceiverService,
|
|
|
$timeout: ng.ITimeoutService,
|
|
|
$translate: ng.translate.ITranslateService,
|
|
|
$mdDialog: ng.material.IDialogService,
|
|
@@ -64,8 +67,10 @@ export default [
|
|
|
// Callback that is called when uploading files
|
|
|
onUploading: '=',
|
|
|
maxTextLength: '=',
|
|
|
+
|
|
|
+ receiver: '<receiver',
|
|
|
},
|
|
|
- link(scope: any, element) {
|
|
|
+ link: function(scope: any, element) {
|
|
|
// Logging
|
|
|
const logTag = '[Directives.ComposeArea]';
|
|
|
|
|
@@ -100,6 +105,45 @@ export default [
|
|
|
toChar?: number,
|
|
|
} = null;
|
|
|
|
|
|
+ let chatBlocked = false;
|
|
|
+
|
|
|
+ // Function to update blocking state
|
|
|
+ function setChatBlocked(blocked: boolean) {
|
|
|
+ chatBlocked = blocked;
|
|
|
+ $log.debug(logTag, 'Receiver blocked:', blocked);
|
|
|
+ if (blocked) {
|
|
|
+ sendTrigger.removeClass(TRIGGER_ENABLED_CSS_CLASS);
|
|
|
+ emojiTrigger.removeClass(TRIGGER_ENABLED_CSS_CLASS);
|
|
|
+ fileTrigger.removeClass(TRIGGER_ENABLED_CSS_CLASS);
|
|
|
+ composeDiv.attr('contenteditable', false);
|
|
|
+ if (emojiKeyboard.hasClass('active')) {
|
|
|
+ hideEmojiPicker();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (composeAreaIsEmpty()) {
|
|
|
+ sendTrigger.removeClass(TRIGGER_ENABLED_CSS_CLASS);
|
|
|
+ } else {
|
|
|
+ sendTrigger.addClass(TRIGGER_ENABLED_CSS_CLASS);
|
|
|
+ }
|
|
|
+ emojiTrigger.addClass(TRIGGER_ENABLED_CSS_CLASS);
|
|
|
+ fileTrigger.addClass(TRIGGER_ENABLED_CSS_CLASS);
|
|
|
+ composeDiv.attr('contenteditable', true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Initialize blocking state
|
|
|
+ setChatBlocked(receiverService.isBlocked(scope.receiver));
|
|
|
+
|
|
|
+ // Watch `isBlocked` flag for changes
|
|
|
+ scope.$watch(
|
|
|
+ (_scope) => receiverService.isBlocked(_scope.receiver),
|
|
|
+ (isBlocked: boolean, wasBlocked: boolean) => {
|
|
|
+ if (isBlocked !== wasBlocked) {
|
|
|
+ setChatBlocked(isBlocked);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
/**
|
|
|
* Stop propagation of click events and hold htmlElement of the emojipicker
|
|
|
*/
|
|
@@ -134,6 +178,7 @@ export default [
|
|
|
|
|
|
// Typing events
|
|
|
let stopTypingTimer: ng.IPromise<void> = null;
|
|
|
+
|
|
|
function stopTyping() {
|
|
|
// We can only stop typing of the timer is set (meaning
|
|
|
// that we started typing earlier)
|
|
@@ -146,6 +191,7 @@ export default [
|
|
|
scope.stopTyping();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
function startTyping() {
|
|
|
if (stopTypingTimer === null) {
|
|
|
// If the timer wasn't set previously, we just
|
|
@@ -314,7 +360,7 @@ export default [
|
|
|
const next = (file: File, res: ArrayBuffer | null, error: any) => {
|
|
|
buffers.set(file, res);
|
|
|
if (buffers.size >= fileCounter) {
|
|
|
- resolve(buffers);
|
|
|
+ resolve(buffers);
|
|
|
}
|
|
|
};
|
|
|
for (let n = 0; n < fileCounter; n++) {
|
|
@@ -502,6 +548,10 @@ export default [
|
|
|
// Emoji trigger is clicked
|
|
|
function onEmojiTrigger(ev: UIEvent): void {
|
|
|
ev.stopPropagation();
|
|
|
+ if (chatBlocked) {
|
|
|
+ hideEmojiPicker();
|
|
|
+ return;
|
|
|
+ }
|
|
|
// Toggle visibility of picker
|
|
|
if (emojiKeyboard.hasClass('active')) {
|
|
|
hideEmojiPicker();
|
|
@@ -635,6 +685,9 @@ export default [
|
|
|
function onFileTrigger(ev: UIEvent): void {
|
|
|
ev.preventDefault();
|
|
|
ev.stopPropagation();
|
|
|
+ if (chatBlocked) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
const input = element[0].querySelector('.file-input') as HTMLInputElement;
|
|
|
input.click();
|
|
|
}
|
|
@@ -642,6 +695,9 @@ export default [
|
|
|
function onSendTrigger(ev: UIEvent): boolean {
|
|
|
ev.preventDefault();
|
|
|
ev.stopPropagation();
|
|
|
+ if (chatBlocked) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
return sendText();
|
|
|
}
|
|
|
|
|
@@ -668,7 +724,7 @@ export default [
|
|
|
}
|
|
|
|
|
|
// return the html code position of the container element
|
|
|
- function getPositions(offset: number, container: Node): {html: number, text: number} {
|
|
|
+ function getPositions(offset: number, container: Node): { html: number, text: number } {
|
|
|
let pos = null;
|
|
|
let textPos = null;
|
|
|
|
|
@@ -684,7 +740,7 @@ export default [
|
|
|
pos = 0;
|
|
|
textPos = 0;
|
|
|
} else {
|
|
|
- selectedElement = container.previousSibling;
|
|
|
+ selectedElement = container.previousSibling;
|
|
|
pos = offset;
|
|
|
textPos = offset;
|
|
|
}
|
|
@@ -817,7 +873,7 @@ export default [
|
|
|
if (args.query && args.mention) {
|
|
|
// Insert resulting HTML
|
|
|
insertMention(args.mention, caretPosition ? caretPosition.to - args.query.length : null,
|
|
|
- caretPosition ? caretPosition.to : null);
|
|
|
+ caretPosition ? caretPosition.to : null);
|
|
|
}
|
|
|
}));
|
|
|
|