Browse Source

Chat input control button

master
morethanwords 3 years ago
parent
commit
cc8b18ccbe
  1. 15
      src/components/chat/bubbles.ts
  2. 6
      src/components/chat/chat.ts
  3. 2
      src/components/chat/contextMenu.ts
  4. 161
      src/components/chat/input.ts
  5. 53
      src/components/chat/selection.ts
  6. 5
      src/lib/appManagers/appImManager.ts
  7. 211
      src/scss/partials/_chat.scss

15
src/components/chat/bubbles.ts

@ -479,7 +479,7 @@ export default class ChatBubbles {
handleHorizontalSwipe({ handleHorizontalSwipe({
element: this.bubblesContainer, element: this.bubblesContainer,
verifyTouchTarget: (e) => { verifyTouchTarget: (e) => {
if(this.chat.selection.isSelecting || !this.appMessagesManager.canSendToPeer(this.peerId, this.chat.threadId)) { if(this.chat.selection.isSelecting || !this.chat.canSend()) {
return false; return false;
} }
@ -551,7 +551,7 @@ export default class ChatBubbles {
if(!IS_MOBILE && this.chat.type !== 'pinned') { if(!IS_MOBILE && this.chat.type !== 'pinned') {
this.listenerSetter.add(this.bubblesContainer)('dblclick', (e) => { this.listenerSetter.add(this.bubblesContainer)('dblclick', (e) => {
if(this.chat.selection.isSelecting || if(this.chat.selection.isSelecting ||
!this.appMessagesManager.canSendToPeer(this.peerId, this.chat.threadId)) { !this.chat.canSend()) {
return; return;
} }
@ -645,11 +645,11 @@ export default class ChatBubbles {
this.listenerSetter.add(rootScope)('chat_update', (chatId) => { this.listenerSetter.add(rootScope)('chat_update', (chatId) => {
if(this.peerId === chatId.toPeerId(true)) { if(this.peerId === chatId.toPeerId(true)) {
const hadRights = this.chatInner.classList.contains('has-rights'); const hadRights = this.chatInner.classList.contains('has-rights');
const hasRights = this.appMessagesManager.canSendToPeer(this.peerId, this.chat.threadId); const hasRights = this.chat.canSend();
if(hadRights !== hasRights) { if(hadRights !== hasRights) {
this.finishPeerChange(); this.finishPeerChange();
this.chat.input.updateMessageInput(); this.chat.input.finishPeerChange();
} }
} }
}); });
@ -2258,9 +2258,8 @@ export default class ChatBubbles {
} }
public finishPeerChange() { public finishPeerChange() {
const peerId = this.peerId; const isChannel = this.appPeersManager.isChannel(this.peerId);
const isChannel = this.appPeersManager.isChannel(peerId); const canWrite = this.chat.canSend();
const canWrite = this.appMessagesManager.canSendToPeer(peerId, this.chat.threadId);
this.chatInner.classList.toggle('has-rights', canWrite); this.chatInner.classList.toggle('has-rights', canWrite);
this.bubblesContainer.classList.toggle('is-chat-input-hidden', !canWrite); this.bubblesContainer.classList.toggle('is-chat-input-hidden', !canWrite);
@ -3886,7 +3885,7 @@ export default class ChatBubbles {
this.renderEmptyPlaceholder('noScheduledMessages', bubble, message, elements); this.renderEmptyPlaceholder('noScheduledMessages', bubble, message, elements);
} else if(rootScope.myId === this.peerId) { } else if(rootScope.myId === this.peerId) {
this.renderEmptyPlaceholder('saved', bubble, message, elements); this.renderEmptyPlaceholder('saved', bubble, message, elements);
} else if(this.appPeersManager.isUser(this.peerId) && !isBot && this.appMessagesManager.canSendToPeer(this.peerId) && this.chat.type === 'chat') { } else if(this.appPeersManager.isUser(this.peerId) && !isBot && this.chat.canSend() && this.chat.type === 'chat') {
this.renderEmptyPlaceholder('greeting', bubble, message, elements); this.renderEmptyPlaceholder('greeting', bubble, message, elements);
} else { } else {
this.renderEmptyPlaceholder('noMessages', bubble, message, elements); this.renderEmptyPlaceholder('noMessages', bubble, message, elements);

6
src/components/chat/chat.ts

@ -5,7 +5,7 @@
*/ */
import type { AppNotificationsManager } from "../../lib/appManagers/appNotificationsManager"; import type { AppNotificationsManager } from "../../lib/appManagers/appNotificationsManager";
import type { AppChatsManager } from "../../lib/appManagers/appChatsManager"; import type { AppChatsManager, ChatRights } from "../../lib/appManagers/appChatsManager";
import type { AppDocsManager } from "../../lib/appManagers/appDocsManager"; import type { AppDocsManager } from "../../lib/appManagers/appDocsManager";
import type { AppImManager } from "../../lib/appManagers/appImManager"; import type { AppImManager } from "../../lib/appManagers/appImManager";
import type { AppInlineBotsManager } from "../../lib/appManagers/appInlineBotsManager"; import type { AppInlineBotsManager } from "../../lib/appManagers/appInlineBotsManager";
@ -416,4 +416,8 @@ export default class Chat extends EventListenerBase<{
tab.open(this.peerId, this.threadId, this.bubbles.onDatePick, query); tab.open(this.peerId, this.threadId, this.bubbles.onDatePick, query);
} }
} }
public canSend(action?: ChatRights) {
return this.appMessagesManager.canSendToPeer(this.peerId, this.threadId, action);
}
} }

2
src/components/chat/contextMenu.ts

@ -193,7 +193,7 @@ export default class ChatContextMenu {
icon: 'reply', icon: 'reply',
text: 'Reply', text: 'Reply',
onClick: this.onReplyClick, onClick: this.onReplyClick,
verify: () => this.appMessagesManager.canSendToPeer(this.peerId, this.chat.threadId) && verify: () => this.chat.canSend() &&
!this.message.pFlags.is_outgoing && !this.message.pFlags.is_outgoing &&
!!this.chat.input.messageInput && !!this.chat.input.messageInput &&
this.chat.type !== 'scheduled'/* , this.chat.type !== 'scheduled'/* ,

161
src/components/chat/input.ts

@ -105,7 +105,7 @@ export default class ChatInput {
private lastTimeType = 0; private lastTimeType = 0;
public chatInput: HTMLElement; public chatInput: HTMLElement;
private inputContainer: HTMLElement; public inputContainer: HTMLElement;
public rowsWrapper: HTMLDivElement; public rowsWrapper: HTMLDivElement;
private newMessageWrapper: HTMLDivElement; private newMessageWrapper: HTMLDivElement;
private btnToggleEmoticons: HTMLButtonElement; private btnToggleEmoticons: HTMLButtonElement;
@ -146,6 +146,7 @@ export default class ChatInput {
private noWebPage: true; private noWebPage: true;
public scheduleDate: number; public scheduleDate: number;
public sendSilent: true; public sendSilent: true;
public startParam: string;
private recorder: any; private recorder: any;
public recording = false; public recording = false;
@ -198,8 +199,17 @@ export default class ChatInput {
private previousQuery: string; private previousQuery: string;
private releaseMediaPlayback: () => void; private releaseMediaPlayback: () => void;
botStartBtn: HTMLButtonElement;
fakeBotStartBtn: HTMLElement; private botStartBtn: HTMLButtonElement;
omgContainer: HTMLDivElement;
private fakeBotStartBtn: HTMLElement;
private rowsWrapperWrapper: HTMLDivElement;
private botStartContainer: HTMLElement;
fakeSelectionWrapper: HTMLDivElement;
private fakeWrapperTo: HTMLElement;
// private activeContainer: HTMLElement;
constructor(private chat: Chat, constructor(private chat: Chat,
private appMessagesManager: AppMessagesManager, private appMessagesManager: AppMessagesManager,
@ -227,19 +237,24 @@ export default class ChatInput {
this.inputContainer = document.createElement('div'); this.inputContainer = document.createElement('div');
this.inputContainer.classList.add('chat-input-container'); this.inputContainer.classList.add('chat-input-container');
this.rowsWrapperWrapper = document.createElement('div');
this.rowsWrapperWrapper.classList.add('rows-wrapper-wrapper');
this.rowsWrapper = document.createElement('div'); this.rowsWrapper = document.createElement('div');
this.rowsWrapper.classList.add('rows-wrapper', 'chat-input-wrapper'); this.rowsWrapper.classList.add('rows-wrapper', 'chat-input-wrapper');
this.rowsWrapperWrapper.append(this.rowsWrapper);
const tail = generateTail(); const tail = generateTail();
this.rowsWrapper.append(tail); this.rowsWrapper.append(tail);
const fakeRowsWrapper = this.fakeRowsWrapper = document.createElement('div'); const fakeRowsWrapper = this.fakeRowsWrapper = document.createElement('div');
fakeRowsWrapper.classList.add('fake-wrapper', 'fake-rows-wrapper'); fakeRowsWrapper.classList.add('fake-wrapper', 'fake-rows-wrapper');
const fakeSelectionWrapper = document.createElement('div'); const fakeSelectionWrapper = this.fakeSelectionWrapper = document.createElement('div');
fakeSelectionWrapper.classList.add('fake-wrapper', 'fake-selection-wrapper'); fakeSelectionWrapper.classList.add('fake-wrapper', 'fake-selection-wrapper');
this.inputContainer.append(this.rowsWrapper, fakeRowsWrapper, fakeSelectionWrapper); this.inputContainer.append(this.rowsWrapperWrapper, fakeRowsWrapper, fakeSelectionWrapper);
this.chatInput.append(this.inputContainer); this.chatInput.append(this.inputContainer);
this.goDownBtn = ButtonCorner({icon: 'arrow_down', className: 'bubbles-corner-button bubbles-go-down hide'}); this.goDownBtn = ButtonCorner({icon: 'arrow_down', className: 'bubbles-corner-button bubbles-go-down hide'});
@ -510,7 +525,7 @@ export default class ChatInput {
this.willAttachType = 'media'; this.willAttachType = 'media';
this.fileInput.click(); this.fileInput.click();
}, },
verify: (peerId, threadId) => this.appMessagesManager.canSendToPeer(peerId, threadId, 'send_media') verify: () => this.chat.canSend('send_media')
}, { }, {
icon: 'document', icon: 'document',
text: 'Chat.Input.Attach.Document', text: 'Chat.Input.Attach.Document',
@ -520,14 +535,14 @@ export default class ChatInput {
this.willAttachType = 'document'; this.willAttachType = 'document';
this.fileInput.click(); this.fileInput.click();
}, },
verify: (peerId, threadId) => this.appMessagesManager.canSendToPeer(peerId, threadId, 'send_media') verify: () => this.chat.canSend('send_media')
}, { }, {
icon: 'poll', icon: 'poll',
text: 'Poll', text: 'Poll',
onClick: () => { onClick: () => {
new PopupCreatePoll(this.chat).show(); new PopupCreatePoll(this.chat).show();
}, },
verify: (peerId, threadId) => peerId.isAnyChat() && this.appMessagesManager.canSendToPeer(peerId, threadId, 'send_polls') verify: (peerId) => peerId.isAnyChat() && this.chat.canSend('send_polls')
}]; }];
this.attachMenu = ButtonMenuToggle({noRipple: true, listenerSetter: this.listenerSetter}, 'top-left', this.attachMenuButtons); this.attachMenu = ButtonMenuToggle({noRipple: true, listenerSetter: this.listenerSetter}, 'top-left', this.attachMenuButtons);
@ -776,35 +791,26 @@ export default class ChatInput {
this.saveDraftDebounced = debounce(() => this.saveDraft(), 2500, false, true); this.saveDraftDebounced = debounce(() => this.saveDraft(), 2500, false, true);
/* this.constructCenteredContainer((container, fakeContainer) => { this.botStartBtn = Button('btn-primary btn-transparent text-bold chat-input-control-button');
this.botStartBtn = Button('btn-primary btn-transparent text-bold'); this.botStartBtn.append(i18n('BotStart'));
container.append(this.botStartBtn);
this.fakeBotStartBtn = this.botStartBtn.cloneNode(true) as HTMLElement; const c = this.botStartContainer = document.createElement('div');
fakeContainer.append(this.fakeBotStartBtn); c.classList.add('chat-input-control', 'chat-input-wrapper');
c.append(this.botStartBtn);
this.inputContainer.append(c);
this.botStartBtn.append(i18n('BotStart')); // this.botStartContainer.classList.add('hide');
this.fakeBotStartBtn.append(i18n('BotStart')); // this.startParam = '123';
}); */
} }
private constructCenteredContainer(fill: (container: HTMLElement, fakeContainer: HTMLElement) => void) { private constructPinnedContainer() {
const container = document.createElement('div'); const container = document.createElement('div');
container.classList.add('input-centered-container', 'rows-wrapper', 'is-centered', 'chat-input-wrapper'); container.classList.add('pinned-container');
const fakeContainer = container.cloneNode(true) as HTMLElement;
fakeContainer.classList.add('fake-wrapper', 'fake-input-centered-container');
fill(container, fakeContainer);
this.inputContainer.append(container, fakeContainer);
return container; return container;
} }
public constructPinnedHelpers() { public constructPinnedHelpers() {
const container = document.createElement('div'); const container = this.constructPinnedContainer();
container.classList.add('pinned-container');
this.pinnedControlBtn = Button('btn-primary btn-transparent text-bold pinned-container-button', {icon: 'unpin'}); this.pinnedControlBtn = Button('btn-primary btn-transparent text-bold pinned-container-button', {icon: 'unpin'});
container.append(this.pinnedControlBtn); container.append(this.pinnedControlBtn);
@ -833,6 +839,95 @@ export default class ChatInput {
this.rowsWrapper.classList.add('is-centered'); this.rowsWrapper.classList.add('is-centered');
} }
public center() {
const neededFakeContainer = this.getNeededFakeContainer();
if(!neededFakeContainer && !this.inputContainer.classList.contains('is-centering')) {
return;
}
/* if(neededFakeContainer === this.botStartContainer && this.fakeWrapperTo === this.fakeSelectionWrapper) {
this.inputContainer.classList.remove('is-centering');
void this.rowsWrapper.offsetLeft; // reflow
// this.inputContainer.classList.add('is-centering');
// void this.rowsWrapper.offsetLeft; // reflow
} */
const fakeSelectionWrapper = neededFakeContainer || this.fakeWrapperTo;
const forwards = !!neededFakeContainer;
const oldFakeWrapperTo = this.fakeWrapperTo;
let transform = '', borderRadius = '', needTranslateX: number;
// if(forwards) {]
const fakeSelectionRect = fakeSelectionWrapper.getBoundingClientRect();
const fakeRowsRect = this.fakeRowsWrapper.getBoundingClientRect();
const widthFrom = fakeRowsRect.width;
const widthTo = fakeSelectionRect.width;
if(widthFrom !== widthTo) {
const scale = (widthTo/* - 8 */) / widthFrom;
const initTranslateX = (widthFrom - widthTo) / 2;
needTranslateX = fakeSelectionRect.left - fakeRowsRect.left - initTranslateX;
if(forwards) {
transform = `translateX(${needTranslateX}px) scaleX(${scale})`;
// transform = `translateX(0px) scaleX(${scale})`;
if(scale < 1) {
const br = 12;
borderRadius = '' + (br + br * (1 - scale)) + 'px';
}
}
//scale = widthTo / widthFrom;
}
// }
this.fakeWrapperTo = neededFakeContainer;
const duration = 200;
SetTransition(this.inputContainer, 'is-centering', forwards, duration);
SetTransition(this.rowsWrapperWrapper, 'is-centering-to-control', !!(forwards && neededFakeContainer && neededFakeContainer.classList.contains('chat-input-control')), duration);
this.rowsWrapper.style.transform = transform;
this.rowsWrapper.style.borderRadius = borderRadius;
return {
transform,
borderRadius,
needTranslateX: oldFakeWrapperTo && (
(
neededFakeContainer &&
neededFakeContainer.classList.contains('chat-input-control') &&
oldFakeWrapperTo === this.fakeSelectionWrapper
) || oldFakeWrapperTo.classList.contains('chat-input-control')
) ? needTranslateX * -.5 : needTranslateX,
widthFrom,
widthTo
};
}
public getNeededFakeContainer() {
if(this.chat.selection.isSelecting) {
return this.fakeSelectionWrapper;
} else if(this.startParam || !this.chat.canSend()) {
return this.botStartContainer;
}
}
// public getActiveContainer() {
// if(this.chat.selection.isSelecting) {
// return this.chat
// }
// return this.startParam !== undefined ? this.botStartContainer : this.rowsWrapper;
// }
// public setActiveContainer() {
// const container = this.activeContainer;
// const newContainer = this.getActiveContainer();
// if(newContainer === container) {
// return;
// }
// }
private onCancelRecordClick = (e?: Event) => { private onCancelRecordClick = (e?: Event) => {
if(e) { if(e) {
cancelEvent(e); cancelEvent(e);
@ -1030,6 +1125,8 @@ export default class ChatInput {
sendMenu.setPeerId(peerId); sendMenu.setPeerId(peerId);
} }
this.center();
if(this.messageInput) { if(this.messageInput) {
this.updateMessageInput(); this.updateMessageInput();
} else if(this.pinnedControlBtn) { } else if(this.pinnedControlBtn) {
@ -1046,7 +1143,7 @@ export default class ChatInput {
public updateMessageInput() { public updateMessageInput() {
const {chatInput, attachMenu, messageInput} = this; const {chatInput, attachMenu, messageInput} = this;
const {peerId, threadId} = this.chat; const {peerId, threadId} = this.chat;
const canWrite = this.appMessagesManager.canSendToPeer(peerId, threadId); const canWrite = this.chat.canSend();
chatInput.classList.add('no-transition'); chatInput.classList.add('no-transition');
chatInput.classList.toggle('is-hidden', !canWrite); chatInput.classList.toggle('is-hidden', !canWrite);
void chatInput.offsetLeft; // reflow void chatInput.offsetLeft; // reflow
@ -1589,7 +1686,7 @@ export default class ChatInput {
if(this.stickersHelper && if(this.stickersHelper &&
rootScope.settings.stickers.suggest && rootScope.settings.stickers.suggest &&
this.appMessagesManager.canSendToPeer(this.chat.peerId, this.chat.threadId, 'send_stickers') && this.chat.canSend('send_stickers') &&
entity?._ === 'messageEntityEmoji' && entity.length === value.length && !entity.offset) { entity?._ === 'messageEntityEmoji' && entity.length === value.length && !entity.offset) {
foundHelper = this.stickersHelper; foundHelper = this.stickersHelper;
this.stickersHelper.checkEmoticon(value); this.stickersHelper.checkEmoticon(value);
@ -1675,7 +1772,7 @@ export default class ChatInput {
this.sendMessage(); this.sendMessage();
} }
} else { } else {
if(this.chat.peerId.isAnyChat() && !this.appMessagesManager.canSendToPeer(this.chat.peerId, this.chat.threadId, 'send_media')) { if(this.chat.peerId.isAnyChat() && !this.chat.canSend('send_media')) {
toast(POSTING_MEDIA_NOT_ALLOWED); toast(POSTING_MEDIA_NOT_ALLOWED);
return; return;
} }
@ -2031,7 +2128,7 @@ export default class ChatInput {
document = this.appDocsManager.getDoc(document); document = this.appDocsManager.getDoc(document);
const flag = document.type === 'sticker' ? 'send_stickers' : (document.type === 'gif' ? 'send_gifs' : 'send_media'); const flag = document.type === 'sticker' ? 'send_stickers' : (document.type === 'gif' ? 'send_gifs' : 'send_media');
if(this.chat.peerId.isAnyChat() && !this.appMessagesManager.canSendToPeer(this.chat.peerId, this.chat.threadId, flag)) { if(this.chat.peerId.isAnyChat() && !this.chat.canSend(flag)) {
toast(POSTING_MEDIA_NOT_ALLOWED); toast(POSTING_MEDIA_NOT_ALLOWED);
return false; return false;
} }

53
src/components/chat/selection.ts

@ -819,36 +819,8 @@ export default class ChatSelection extends AppSelection {
} }
protected onToggleSelection = (forwards: boolean) => { protected onToggleSelection = (forwards: boolean) => {
let transform = '', borderRadius = '', needTranslateX: number; const {needTranslateX, widthFrom, widthTo} = this.chat.input.center();
// if(forwards) {
const p = this.input.rowsWrapper.parentElement;
const fakeSelectionWrapper = p.querySelector('.fake-selection-wrapper');
const fakeRowsWrapper = p.querySelector('.fake-rows-wrapper');
const fakeSelectionRect = fakeSelectionWrapper.getBoundingClientRect();
const fakeRowsRect = fakeRowsWrapper.getBoundingClientRect();
const widthFrom = fakeRowsRect.width;
const widthTo = fakeSelectionRect.width;
if(widthFrom !== widthTo) {
const scale = (widthTo/* - 8 */) / widthFrom;
const initTranslateX = (widthFrom - widthTo) / 2;
needTranslateX = fakeSelectionRect.left - fakeRowsRect.left - initTranslateX;
if(forwards) {
transform = `translateX(${needTranslateX}px) scaleX(${scale})`;
if(scale < 1) {
const br = 12;
borderRadius = '' + (br + br * (1 - scale)) + 'px';
}
}
//scale = widthTo / widthFrom;
}
// }
SetTransition(this.input.rowsWrapper, 'is-centering', forwards, 200);
this.input.rowsWrapper.style.transform = transform;
this.input.rowsWrapper.style.borderRadius = borderRadius;
SetTransition(this.listenElement, 'is-selecting', forwards, 200, () => { SetTransition(this.listenElement, 'is-selecting', forwards, 200, () => {
if(!this.isSelecting) { if(!this.isSelecting) {
this.selectionInputWrapper.remove(); this.selectionInputWrapper.remove();
@ -870,11 +842,15 @@ export default class ChatSelection extends AppSelection {
//const chatInput = this.appImManager.chatInput; //const chatInput = this.appImManager.chatInput;
const translateButtonsX = widthFrom < widthTo ? undefined : needTranslateX * 2;
if(this.isSelecting) { if(this.isSelecting) {
if(!this.selectionContainer) { if(!this.selectionContainer) {
this.selectionInputWrapper = document.createElement('div'); this.selectionInputWrapper = document.createElement('div');
this.selectionInputWrapper.classList.add('chat-input-wrapper', 'selection-wrapper'); this.selectionInputWrapper.classList.add('chat-input-wrapper', 'selection-wrapper');
// const background = document.createElement('div');
// background.classList.add('chat-input-wrapper-background');
this.selectionContainer = document.createElement('div'); this.selectionContainer = document.createElement('div');
this.selectionContainer.classList.add('selection-container'); this.selectionContainer.classList.add('selection-container');
@ -928,22 +904,27 @@ export default class ChatSelection extends AppSelection {
this.selectionDeleteBtn this.selectionDeleteBtn
].filter(Boolean)) ].filter(Boolean))
left.style.transform = `translateX(-${needTranslateX * 2}px)`; if(translateButtonsX !== undefined) {
right.style.transform = `translateX(${needTranslateX * 2}px)`; left.style.transform = `translateX(${-translateButtonsX}px)`;
right.style.transform = `translateX(${translateButtonsX}px)`;
}
this.selectionContainer.append(left, right); this.selectionContainer.append(left, right);
// background.style.opacity = '0';
this.selectionInputWrapper.style.opacity = '0'; this.selectionInputWrapper.style.opacity = '0';
this.selectionInputWrapper.append(this.selectionContainer); this.selectionInputWrapper.append(/* background, */this.selectionContainer);
this.input.rowsWrapper.parentElement.append(this.selectionInputWrapper); this.input.inputContainer.append(this.selectionInputWrapper);
void this.selectionInputWrapper.offsetLeft; // reflow void this.selectionInputWrapper.offsetLeft; // reflow
// background.style.opacity = '';
this.selectionInputWrapper.style.opacity = ''; this.selectionInputWrapper.style.opacity = '';
left.style.transform = ''; left.style.transform = '';
right.style.transform = ''; right.style.transform = '';
} }
} else if(this.selectionLeft) { } else if(this.selectionLeft && translateButtonsX !== undefined) {
this.selectionLeft.style.transform = `translateX(-${needTranslateX * 2}px)`; this.selectionLeft.style.transform = `translateX(-${translateButtonsX}px)`;
this.selectionRight.style.transform = `translateX(${needTranslateX * 2}px)`; this.selectionRight.style.transform = `translateX(${translateButtonsX}px)`;
} }
}; };

5
src/lib/appManagers/appImManager.ts

@ -1199,8 +1199,9 @@ export class AppImManager {
} }
private canDrag() { private canDrag() {
const peerId = this.chat?.peerId; const chat = this.chat;
return !(!peerId || rootScope.isOverlayActive || !appMessagesManager.canSendToPeer(peerId, this.chat.threadId, 'send_media')); const peerId = chat?.peerId;
return !(!peerId || rootScope.isOverlayActive || !chat.canSend('send_media'));
} }
private onDocumentPaste = (e: ClipboardEvent | DragEvent, attachType?: 'media' | 'document') => { private onDocumentPaste = (e: ClipboardEvent | DragEvent, attachType?: 'media' | 'document') => {

211
src/scss/partials/_chat.scss

@ -7,6 +7,11 @@
$btn-send-margin: .5rem; $btn-send-margin: .5rem;
$chat-helper-size: 36px; $chat-helper-size: 36px;
$input-transition-time: .2s;
$input-half-transition-time: #{$input-transition-time / 2};
$background-transition-time: 0.05s;
$background-transition-total-time: #{$input-transition-time - $background-transition-time};
/* #bubble-contextmenu > div { /* #bubble-contextmenu > div {
padding: 0 5.25 0 1rem; padding: 0 5.25 0 1rem;
@ -79,7 +84,8 @@ $chat-helper-size: 36px;
--padding-horizontal: var(--chat-input-padding); --padding-horizontal: var(--chat-input-padding);
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
justify-content: space-between; justify-content: center;
// justify-content: space-between;
max-width: var(--messages-container-width); max-width: var(--messages-container-width);
margin: 0 auto; margin: 0 auto;
width: 100%; width: 100%;
@ -92,6 +98,40 @@ $chat-helper-size: 36px;
width: var(--chat-input-size); width: var(--chat-input-size);
height: var(--chat-input-size); height: var(--chat-input-size);
} }
&.is-centering {
.new-message-wrapper {
pointer-events: none;
}
}
&.is-centering:not(.backwards) {
.new-message-wrapper, .pinned-container {
opacity: 0;
}
.rows-wrapper {
max-height: var(--chat-input-size);
// opacity: 0;
// transition: transform .2s, width .2s, max-height .2s, border-radius .1s, opacity 0s .2s;
//box-shadow: none;
&:before {
opacity: 0;
transition: opacity $background-transition-time $background-transition-total-time;
}
}
.reply-wrapper {
height: 0 !important;
opacity: 0;
pointer-events: none;
}
.btn-send {
transform: scale(0);
}
}
} }
/* @include respond-to(handhelds) { /* @include respond-to(handhelds) {
@ -136,7 +176,7 @@ $chat-helper-size: 36px;
} }
@include animation-level(2) { @include animation-level(2) {
transition: height .1s; transition: height $input-half-transition-time;
} }
@media only screen and (max-height: 30rem) { @media only screen and (max-height: 30rem) {
@ -171,7 +211,7 @@ $chat-helper-size: 36px;
.btn-record-cancel { .btn-record-cancel {
visibility: hidden; visibility: hidden;
opacity: 0; opacity: 0;
transition: visibility 0s .1s, opacity .1s 0s; transition: visibility 0s $input-half-transition-time, opacity $input-half-transition-time 0s;
padding: 0; padding: 0;
z-index: 3; z-index: 3;
position: absolute; position: absolute;
@ -346,10 +386,10 @@ $chat-helper-size: 36px;
position: absolute; position: absolute;
top: -94px; top: -94px;
left: -94px; left: -94px;
transition: transform .03s ease-in-out, visibility .1s; transition: transform .03s ease-in-out, visibility $input-half-transition-time;
visibility: hidden; visibility: hidden;
body.animation-level-0 & { @include animation-level(0) {
transition: none !important; transition: none !important;
} }
@ -377,7 +417,7 @@ $chat-helper-size: 36px;
.btn-record-cancel { .btn-record-cancel {
opacity: 1; opacity: 1;
visibility: visible; visibility: visible;
transition: visibility 0s .1s, opacity .1s .1s; transition: visibility 0s $input-half-transition-time, opacity $input-half-transition-time $input-half-transition-time;
} }
// unlock // unlock
@ -387,6 +427,7 @@ $chat-helper-size: 36px;
.rows-wrapper { .rows-wrapper {
width: calc(100% - (var(--chat-input-size) * 2 + #{$btn-send-margin * 2})); width: calc(100% - (var(--chat-input-size) * 2 + #{$btn-send-margin * 2}));
// transform: translateX(calc((var(--chat-input-size) + 0.5rem) / -1)) scaleX(1);
} }
.attach-file { .attach-file {
@ -414,7 +455,7 @@ $chat-helper-size: 36px;
opacity: 1; opacity: 1;
@include animation-level(2) { @include animation-level(2) {
transition: opacity .1s 0s; transition: opacity $input-half-transition-time 0s;
} }
} }
@ -432,45 +473,40 @@ $chat-helper-size: 36px;
} }
} }
.bubbles.is-selecting ~ & {
.new-message-wrapper {
pointer-events: none;
}
}
.bubbles.is-selecting:not(.backwards) ~ & { .bubbles.is-selecting:not(.backwards) ~ & {
.new-message-wrapper, .pinned-container {
opacity: 0;
}
.selection-wrapper { .selection-wrapper {
opacity: 1; opacity: 1;
.chat-input-wrapper-background {
// visibility: visible;
// transition: visibility 0s 3s;
opacity: 1;
transition: opacity $background-transition-time $background-transition-total-time;
}
} }
.rows-wrapper { .rows-wrapper {
max-height: var(--chat-input-size); &:before {
//box-shadow: none; opacity: 1;
transition: opacity 0s 0s;
} }
.reply-wrapper {
height: 0 !important;
opacity: 0;
pointer-events: none;
} }
.btn-send {
transform: scale(0);
} }
/* .bubbles.is-selecting:not(.backwards):not(.animating) ~ & {
.selection-wrapper:before {
visibility: visible;
} }
} */
.bubbles.is-selecting.backwards ~ & { .bubbles.is-selecting.backwards ~ & {
@include animation-level(2) { @include animation-level(2) {
.new-message-wrapper, .pinned-container { .new-message-wrapper, .pinned-container {
transition: opacity .1s .1s; transition: opacity $input-half-transition-time $input-half-transition-time;
} }
.selection-wrapper { .selection-wrapper {
transition: opacity .1s 0s; transition: opacity $input-half-transition-time 0s;
} }
} }
} }
@ -715,27 +751,63 @@ $chat-helper-size: 36px;
width: calc(100% - (var(--chat-input-size) + #{$btn-send-margin})); width: calc(100% - (var(--chat-input-size) + #{$btn-send-margin}));
max-width: calc(100% - (var(--chat-input-size) + #{$btn-send-margin})); max-width: calc(100% - (var(--chat-input-size) + #{$btn-send-margin}));
justify-content: center; justify-content: center;
background-color: var(--surface-color); // background-color: var(--surface-color);
border-radius: 12px; border-radius: 12px;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
//box-shadow: 0 1px 2px 0 rgba(16, 35, 47, .07); //box-shadow: 0 1px 2px 0 rgba(16, 35, 47, .07);
box-shadow: 0px 1px 8px 1px rgba(0, 0, 0, .18); // box-shadow: 0px 1px 8px 1px rgba(0, 0, 0, .18);
min-height: var(--chat-input-size); min-height: var(--chat-input-size);
max-height: 30rem; max-height: 30rem;
flex: 0 0 auto; flex: 0 0 auto;
position: relative; position: relative;
z-index: 3; z-index: 3;
transition: width .1s; transition: width $input-half-transition-time;
body.animation-level-0 & { &:before,
transition: none; .chat-input-wrapper-background {
content: " ";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border-radius: inherit;
box-shadow: 0px 1px 8px 1px rgb(0 0 0 / 18%);
background-color: #fff;
background-color: var(--surface-color);
opacity: 1;
transition: opacity $background-transition-time 0s;
@include animation-level(0) {
transition: none !important;
}
}
@include animation-level(0) {
transition: none !important;
} }
} }
.input-centered-container { .chat-input-control {
--padding-vertical: .3125rem;
--padding-horizontal: var(--chat-input-inner-padding);
--padding: var(--padding-vertical) var(--padding-horizontal);
position: absolute; position: absolute;
margin: 0 auto; margin: 0 auto;
width: auto; width: auto;
height: var(--chat-input-size);
padding: var(--padding);
background-color: var(--surface-color);
border-radius: $border-radius-big;
z-index: 3;
&:before {
opacity: 0;
}
}
.chat-input-control-button {
height: 100%;
} }
.selection-wrapper, .fake-selection-wrapper { .selection-wrapper, .fake-selection-wrapper {
@ -747,12 +819,32 @@ $chat-helper-size: 36px;
max-width: calc(100% - (var(--chat-input-padding) * 2)); max-width: calc(100% - (var(--chat-input-padding) * 2));
} }
.selection-wrapper,
.chat-input-control {
transition: opacity $input-half-transition-time .075s;
opacity: 0;
@include animation-level(0) {
transition: none !important;
}
}
.selection-wrapper { .selection-wrapper {
border-radius: $border-radius-big; border-radius: $border-radius-big;
//z-index: 2; // z-index: 2;
box-shadow: none; // box-shadow: none;
transition: opacity .1s .075s; background-color: var(--surface-color);
opacity: 0;
&:before {
content: none;
}
// .chat-input-wrapper-background {
// transition: visibility 0s 3s;
// opacity: 0;
// transition: opacity 0s 3s;
// box-shadow: 0px 1px 8px 1px rgb(0 0 0);
// }
.selection-container { .selection-container {
display: flex; display: flex;
@ -775,7 +867,7 @@ $chat-helper-size: 36px;
@include animation-level(2) { @include animation-level(2) {
transform: translateX(0); transform: translateX(0);
transition: transform .2s; transition: transform $input-transition-time;
} }
} }
@ -868,12 +960,40 @@ $chat-helper-size: 36px;
} }
} }
.rows-wrapper-wrapper {
width: 100%;
display: flex;
&.is-centering-to-control:not(.backwards) ~ .chat-input-control {
opacity: 1;
&:before {
opacity: 1;
transition: opacity $background-transition-time $background-transition-total-time;
}
}
&.is-centering-to-control.backwards ~ .chat-input-control {
transition: opacity $input-half-transition-time 0s;
}
}
.rows-wrapper { .rows-wrapper {
transform: scaleX(1); transform: scaleX(1);
transition: transform .2s, width .2s, max-height .2s, border-radius .1s; // transform: translateX(calc((var(--chat-input-size) + 0.5rem) / -2)) scaleX(1);
transition: transform $input-transition-time, width $input-transition-time, max-height $input-transition-time, border-radius $input-half-transition-time/* , opacity 0s 0s */;
// background-color: transparent;
// opacity: 1;
// box-shadow: none;
@include animation-level(0) {
transition: none !important;
}
&.is-centered { &.is-centered {
margin: 0 auto; margin: 0 auto;
// width: 100%;
// max-width: 100%;
& ~ .fake-rows-wrapper { & ~ .fake-rows-wrapper {
left: 50%; left: 50%;
@ -882,18 +1002,21 @@ $chat-helper-size: 36px;
} }
.bubble-tail { .bubble-tail {
transition: transform .1s; opacity: 1;
transition: transform $input-half-transition-time, opacity .025s 0s;
@include animation-level(0) { @include animation-level(0) {
transition: none; transition: none !important;
} }
} }
&.is-centering:not(.backwards), &.is-centered { .chat-input-container.is-centering:not(.backwards) &, &.is-centered {
border-bottom-right-radius: 12px; border-bottom-right-radius: 12px;
.bubble-tail { .bubble-tail {
transition: transform $input-half-transition-time, opacity .025s .075s;
transform: scaleX(-1) translateX(#{.5625rem * 2}); transform: scaleX(-1) translateX(#{.5625rem * 2});
opacity: 0;
} }
} }

Loading…
Cancel
Save