Multiselect: forward and delete
Chat input helper is now clickable Popup stickers lower resolution for handhelds
This commit is contained in:
parent
f135565529
commit
baf1f78618
@ -36,13 +36,22 @@ export default class AppSelectPeers {
|
|||||||
private cachedContacts: number[];
|
private cachedContacts: number[];
|
||||||
|
|
||||||
private loadedWhat: Partial<{[k in 'dialogs' | 'archived' | 'contacts']: true}> = {};
|
private loadedWhat: Partial<{[k in 'dialogs' | 'archived' | 'contacts']: true}> = {};
|
||||||
|
|
||||||
|
private renderedPeerIDs: Set<number> = new Set();
|
||||||
|
|
||||||
constructor(private appendTo: HTMLElement, private onChange?: (length: number) => void, private peerType: PeerType[] = ['dialogs'], onFirstRender?: () => void, private renderResultsFunc?: (peerIDs: number[]) => void, private chatRightsAction?: ChatRights, private multiSelect = true) {
|
constructor(private appendTo: HTMLElement, private onChange?: (length: number) => void, private peerType: PeerType[] = ['dialogs'], onFirstRender?: () => void, private renderResultsFunc?: (peerIDs: number[]) => void, private chatRightsAction?: ChatRights, private multiSelect = true) {
|
||||||
this.container.classList.add('selector');
|
this.container.classList.add('selector');
|
||||||
|
|
||||||
if(!this.renderResultsFunc) {
|
const f = (renderResultsFunc || this.renderResults).bind(this);
|
||||||
this.renderResultsFunc = this.renderResults;
|
this.renderResultsFunc = (peerIDs: number[]) => {
|
||||||
}
|
peerIDs = peerIDs.filter(peerID => {
|
||||||
|
const notRendered = !this.renderedPeerIDs.has(peerID);
|
||||||
|
if(notRendered) this.renderedPeerIDs.add(peerID);
|
||||||
|
return notRendered;
|
||||||
|
});
|
||||||
|
|
||||||
|
return f(peerIDs);
|
||||||
|
};
|
||||||
|
|
||||||
this.input = document.createElement('input');
|
this.input = document.createElement('input');
|
||||||
this.input.classList.add('selector-search-input');
|
this.input.classList.add('selector-search-input');
|
||||||
@ -130,6 +139,7 @@ export default class AppSelectPeers {
|
|||||||
this.promise = null;
|
this.promise = null;
|
||||||
this.list.innerHTML = '';
|
this.list.innerHTML = '';
|
||||||
this.query = value;
|
this.query = value;
|
||||||
|
this.renderedPeerIDs.clear();
|
||||||
|
|
||||||
//console.log('selectPeers input:', this.query);
|
//console.log('selectPeers input:', this.query);
|
||||||
this.getMoreResults();
|
this.getMoreResults();
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||||
import appChatsManager from "../../lib/appManagers/appChatsManager";
|
import appChatsManager from "../../lib/appManagers/appChatsManager";
|
||||||
import appImManager from "../../lib/appManagers/appImManager";
|
import appImManager from "../../lib/appManagers/appImManager";
|
||||||
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
|
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
|
||||||
import appPeersManager from "../../lib/appManagers/appPeersManager";
|
import appPeersManager from "../../lib/appManagers/appPeersManager";
|
||||||
import appPollsManager, { Poll } from "../../lib/appManagers/appPollsManager";
|
import appPollsManager, { Poll } from "../../lib/appManagers/appPollsManager";
|
||||||
import $rootScope from "../../lib/rootScope";
|
import $rootScope from "../../lib/rootScope";
|
||||||
import { findUpClassName } from "../../lib/utils";
|
import { cancelEvent, cancelSelection, findUpClassName } from "../../lib/utils";
|
||||||
import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu";
|
import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu";
|
||||||
import { attachContextMenuListener, openBtnMenu, positionMenu } from "../misc";
|
import { attachContextMenuListener, openBtnMenu, positionMenu } from "../misc";
|
||||||
import { PopupButton } from "../popup";
|
import { PopupButton } from "../popup";
|
||||||
|
import PopupDeleteMessages from "../popupDeleteMessages";
|
||||||
import PopupForward from "../popupForward";
|
import PopupForward from "../popupForward";
|
||||||
import PopupPeer from "../popupPeer";
|
import PopupPeer from "../popupPeer";
|
||||||
import appSidebarRight from "../sidebarRight";
|
import appSidebarRight from "../sidebarRight";
|
||||||
@ -21,7 +23,7 @@ export default class ChatContextMenu {
|
|||||||
public msgID: number;
|
public msgID: number;
|
||||||
|
|
||||||
constructor(private attachTo: HTMLElement) {
|
constructor(private attachTo: HTMLElement) {
|
||||||
attachContextMenuListener(attachTo, (e) => {
|
const onContextMenu = (e: MouseEvent | Touch) => {
|
||||||
if(this.init) {
|
if(this.init) {
|
||||||
this.init();
|
this.init();
|
||||||
this.init = null;
|
this.init = null;
|
||||||
@ -69,7 +71,29 @@ export default class ChatContextMenu {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/////this.log('contextmenu', e, bubble, msgID, side);
|
/////this.log('contextmenu', e, bubble, msgID, side);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if(isTouchSupported) {
|
||||||
|
attachTo.addEventListener('click', (e) => {
|
||||||
|
//const good = !!findUpClassName(e.target, 'message') || !!findUpClassName(e.target, 'bubble__container');
|
||||||
|
const className = (e.target as HTMLElement).className;
|
||||||
|
const good = ['bubble', 'bubble__container', 'message', 'time', 'inner'].find(c => className.includes(c));
|
||||||
|
if(good) {
|
||||||
|
onContextMenu(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
attachContextMenuListener(attachTo, (e) => {
|
||||||
|
if(appImManager.chatSelection.isSelecting) return;
|
||||||
|
|
||||||
|
cancelSelection();
|
||||||
|
cancelEvent(e as any);
|
||||||
|
let bubble = findUpClassName(e.target, 'bubble');
|
||||||
|
if(bubble) {
|
||||||
|
appImManager.chatSelection.toggleByBubble(bubble);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else attachContextMenuListener(attachTo, onContextMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
private init = () => {
|
private init = () => {
|
||||||
@ -145,7 +169,7 @@ export default class ChatContextMenu {
|
|||||||
icon: 'delete danger',
|
icon: 'delete danger',
|
||||||
text: 'Delete',
|
text: 'Delete',
|
||||||
onClick: this.onDeleteClick,
|
onClick: this.onDeleteClick,
|
||||||
verify: () => this.peerID > 0 || appMessagesManager.getMessage(this.msgID).fromID == $rootScope.myID || appChatsManager.hasRights(-this.peerID, 'deleteRevoke')
|
verify: () => appMessagesManager.canDeleteMessage(this.msgID)
|
||||||
}];
|
}];
|
||||||
|
|
||||||
this.element = ButtonMenu(this.buttons);
|
this.element = ButtonMenu(this.buttons);
|
||||||
@ -217,58 +241,6 @@ export default class ChatContextMenu {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private onDeleteClick = () => {
|
private onDeleteClick = () => {
|
||||||
const peerID = $rootScope.selectedPeerID;
|
new PopupDeleteMessages([this.msgID]);
|
||||||
const firstName = appPeersManager.getPeerTitle(peerID, false, true);
|
|
||||||
|
|
||||||
const msgID = this.msgID;
|
|
||||||
const callback = (revoke: boolean) => {
|
|
||||||
appMessagesManager.deleteMessages([msgID], revoke);
|
|
||||||
};
|
|
||||||
|
|
||||||
let title: string, description: string, buttons: PopupButton[];
|
|
||||||
title = 'Delete Message?';
|
|
||||||
description = `Are you sure you want to delete this message?`;
|
|
||||||
|
|
||||||
if(peerID == $rootScope.myID) {
|
|
||||||
buttons = [{
|
|
||||||
text: 'DELETE',
|
|
||||||
isDanger: true,
|
|
||||||
callback: () => callback(false)
|
|
||||||
}];
|
|
||||||
} else {
|
|
||||||
buttons = [{
|
|
||||||
text: 'DELETE JUST FOR ME',
|
|
||||||
isDanger: true,
|
|
||||||
callback: () => callback(false)
|
|
||||||
}];
|
|
||||||
|
|
||||||
if(peerID > 0) {
|
|
||||||
buttons.push({
|
|
||||||
text: 'DELETE FOR ME AND ' + firstName,
|
|
||||||
isDanger: true,
|
|
||||||
callback: () => callback(true)
|
|
||||||
});
|
|
||||||
} else if(appChatsManager.hasRights(-peerID, 'deleteRevoke')) {
|
|
||||||
buttons.push({
|
|
||||||
text: 'DELETE FOR ALL',
|
|
||||||
isDanger: true,
|
|
||||||
callback: () => callback(true)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buttons.push({
|
|
||||||
text: 'CANCEL',
|
|
||||||
isCancel: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const popup = new PopupPeer('popup-delete-chat', {
|
|
||||||
peerID: peerID,
|
|
||||||
title: title,
|
|
||||||
description: description,
|
|
||||||
buttons: buttons
|
|
||||||
});
|
|
||||||
|
|
||||||
popup.show();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -11,10 +11,11 @@ import apiManager from "../../lib/mtproto/mtprotoworker";
|
|||||||
import opusDecodeController from "../../lib/opusDecodeController";
|
import opusDecodeController from "../../lib/opusDecodeController";
|
||||||
import { RichTextProcessor } from "../../lib/richtextprocessor";
|
import { RichTextProcessor } from "../../lib/richtextprocessor";
|
||||||
import $rootScope from '../../lib/rootScope';
|
import $rootScope from '../../lib/rootScope';
|
||||||
import { cancelEvent, getRichValue } from "../../lib/utils";
|
import { cancelEvent, findUpClassName, getRichValue } from "../../lib/utils";
|
||||||
import ButtonMenu, { ButtonMenuItemOptions } from '../buttonMenu';
|
import ButtonMenu, { ButtonMenuItemOptions } from '../buttonMenu';
|
||||||
import emoticonsDropdown from "../emoticonsDropdown";
|
import emoticonsDropdown from "../emoticonsDropdown";
|
||||||
import PopupCreatePoll from "../popupCreatePoll";
|
import PopupCreatePoll from "../popupCreatePoll";
|
||||||
|
import PopupForward from '../popupForward';
|
||||||
import PopupNewMedia from '../popupNewMedia';
|
import PopupNewMedia from '../popupNewMedia';
|
||||||
import { ripple } from '../ripple';
|
import { ripple } from '../ripple';
|
||||||
import Scrollable from "../scrollable";
|
import Scrollable from "../scrollable";
|
||||||
@ -205,7 +206,7 @@ export class ChatInput {
|
|||||||
if(this.lastUrl != url) return;
|
if(this.lastUrl != url) return;
|
||||||
//console.log('got webpage: ', webpage);
|
//console.log('got webpage: ', webpage);
|
||||||
|
|
||||||
this.setTopInfo('webpage', () => {}, webpage.site_name || webpage.title, webpage.description || webpage.url);
|
this.setTopInfo('webpage', () => {}, webpage.site_name || webpage.title || 'Webpage', webpage.description || webpage.url || '');
|
||||||
|
|
||||||
delete this.noWebPage;
|
delete this.noWebPage;
|
||||||
this.willSendWebPage = webpage;
|
this.willSendWebPage = webpage;
|
||||||
@ -267,7 +268,7 @@ export class ChatInput {
|
|||||||
//console.log('messageInput paste', text, entities);
|
//console.log('messageInput paste', text, entities);
|
||||||
entities = entities.filter(e => e._ == 'messageEntityEmoji' || e._ == 'messageEntityLinebreak');
|
entities = entities.filter(e => e._ == 'messageEntityEmoji' || e._ == 'messageEntityLinebreak');
|
||||||
//text = RichTextProcessor.wrapEmojiText(text);
|
//text = RichTextProcessor.wrapEmojiText(text);
|
||||||
text = RichTextProcessor.wrapRichText(text, {entities});
|
text = RichTextProcessor.wrapRichText(text, {entities, noLinks: true});
|
||||||
|
|
||||||
// console.log('messageInput paste after', text);
|
// console.log('messageInput paste after', text);
|
||||||
|
|
||||||
@ -453,7 +454,7 @@ export class ChatInput {
|
|||||||
|
|
||||||
return; */
|
return; */
|
||||||
|
|
||||||
let perf = performance.now();
|
//let perf = performance.now();
|
||||||
opusDecodeController.decode(typedArray, true).then(result => {
|
opusDecodeController.decode(typedArray, true).then(result => {
|
||||||
//console.log('WAVEFORM!:', /* waveform, */performance.now() - perf);
|
//console.log('WAVEFORM!:', /* waveform, */performance.now() - perf);
|
||||||
|
|
||||||
@ -509,6 +510,33 @@ export class ChatInput {
|
|||||||
this.clearHelper();
|
this.clearHelper();
|
||||||
this.updateSendBtn();
|
this.updateSendBtn();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let d = false;
|
||||||
|
this.replyElements.container.addEventListener('click', (e) => {
|
||||||
|
if(!findUpClassName(e.target, 'reply-wrapper')) return;
|
||||||
|
if(this.helperType == 'forward') {
|
||||||
|
if(d) return;
|
||||||
|
d = true;
|
||||||
|
|
||||||
|
const mids = this.forwardingMids.slice();
|
||||||
|
const helperFunc = this.helperFunc;
|
||||||
|
this.clearHelper();
|
||||||
|
let selected = false;
|
||||||
|
new PopupForward(mids, () => {
|
||||||
|
selected = true;
|
||||||
|
}, () => {
|
||||||
|
d = false;
|
||||||
|
|
||||||
|
if(!selected) {
|
||||||
|
helperFunc();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if(this.helperType == 'reply') {
|
||||||
|
appImManager.setPeer($rootScope.selectedPeerID, this.replyToMsgID);
|
||||||
|
} else if(this.helperType == 'edit') {
|
||||||
|
appImManager.setPeer($rootScope.selectedPeerID, this.editMsgID);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private isInputEmpty() {
|
private isInputEmpty() {
|
||||||
@ -579,8 +607,12 @@ export class ChatInput {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * wait for sendText set messageID for invokeAfterMsg
|
||||||
if(this.forwardingMids.length) {
|
if(this.forwardingMids.length) {
|
||||||
appMessagesManager.forwardMessages(appImManager.peerID, this.forwardingMids);
|
const mids = this.forwardingMids.slice();
|
||||||
|
setTimeout(() => {
|
||||||
|
appMessagesManager.forwardMessages(appImManager.peerID, mids);
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onMessageSent();
|
this.onMessageSent();
|
||||||
@ -629,7 +661,7 @@ export class ChatInput {
|
|||||||
this.setTopInfo('forward', f, title, mids.length + ' forwarded messages');
|
this.setTopInfo('forward', f, title, mids.length + ' forwarded messages');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.forwardingMids = mids;
|
this.forwardingMids = mids.slice();
|
||||||
};
|
};
|
||||||
|
|
||||||
f();
|
f();
|
||||||
@ -640,6 +672,12 @@ export class ChatInput {
|
|||||||
this.messageInput.innerText = '';
|
this.messageInput.innerText = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(type) {
|
||||||
|
this.lastUrl = '';
|
||||||
|
delete this.noWebPage;
|
||||||
|
this.willSendWebPage = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.replyToMsgID = 0;
|
this.replyToMsgID = 0;
|
||||||
this.forwardingMids.length = 0;
|
this.forwardingMids.length = 0;
|
||||||
this.editMsgID = 0;
|
this.editMsgID = 0;
|
||||||
@ -660,9 +698,13 @@ export class ChatInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.chatInput.parentElement.classList.add('is-helper-active');
|
this.chatInput.parentElement.classList.add('is-helper-active');
|
||||||
|
/* const scroll = appImManager.scrollable;
|
||||||
|
if(scroll.isScrolledDown && !scroll.scrollLocked && !appImManager.messagesQueuePromise && !appImManager.setPeerPromise) {
|
||||||
|
scroll.scrollTo(scroll.scrollHeight, 'top', true, true, 200);
|
||||||
|
} */
|
||||||
|
|
||||||
if(input !== undefined) {
|
if(input !== undefined) {
|
||||||
this.messageInput.innerHTML = input ? RichTextProcessor.wrapRichText(input) : '';
|
this.messageInput.innerHTML = input ? RichTextProcessor.wrapRichText(input, {noLinks: true}) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||||
import type { AppImManager } from "../../lib/appManagers/appImManager";
|
import type { AppImManager } from "../../lib/appManagers/appImManager";
|
||||||
import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManager";
|
import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManager";
|
||||||
import { cancelEvent, cancelSelection, findUpClassName } from "../../lib/utils";
|
import { cancelEvent, cancelSelection, findUpClassName, getSelectedText } from "../../lib/utils";
|
||||||
import Button from "../button";
|
import Button from "../button";
|
||||||
import ButtonIcon from "../buttonIcon";
|
import ButtonIcon from "../buttonIcon";
|
||||||
import CheckboxField from "../checkbox";
|
import CheckboxField from "../checkbox";
|
||||||
|
import PopupDeleteMessages from "../popupDeleteMessages";
|
||||||
import PopupForward from "../popupForward";
|
import PopupForward from "../popupForward";
|
||||||
import { toast } from "../toast";
|
import { toast } from "../toast";
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ const SetTransition = (element: HTMLElement, className: string, forwards: boolea
|
|||||||
};
|
};
|
||||||
|
|
||||||
const MAX_SELECTION_LENGTH = 100;
|
const MAX_SELECTION_LENGTH = 100;
|
||||||
const MIN_CLICK_MOVE = 32; // minimum bubble height
|
//const MIN_CLICK_MOVE = 32; // minimum bubble height
|
||||||
|
|
||||||
export default class ChatSelection {
|
export default class ChatSelection {
|
||||||
public selectedMids: Set<number> = new Set();
|
public selectedMids: Set<number> = new Set();
|
||||||
@ -42,14 +43,25 @@ export default class ChatSelection {
|
|||||||
|
|
||||||
private selectionContainer: HTMLElement;
|
private selectionContainer: HTMLElement;
|
||||||
private selectionCountEl: HTMLElement;
|
private selectionCountEl: HTMLElement;
|
||||||
|
private selectionForwardBtn: HTMLElement;
|
||||||
|
private selectionDeleteBtn: HTMLElement;
|
||||||
|
|
||||||
|
public selectedText: string;
|
||||||
|
|
||||||
constructor(private appImManager: AppImManager, private appMessagesManager: AppMessagesManager) {
|
constructor(private appImManager: AppImManager, private appMessagesManager: AppMessagesManager) {
|
||||||
if(isTouchSupported) return;
|
|
||||||
|
|
||||||
const bubblesContainer = appImManager.bubblesContainer;
|
const bubblesContainer = appImManager.bubblesContainer;
|
||||||
|
|
||||||
|
if(isTouchSupported) {
|
||||||
|
bubblesContainer.addEventListener('touchend', (e) => {
|
||||||
|
if(!this.isSelecting) return;
|
||||||
|
this.selectedText = getSelectedText();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bubblesContainer.addEventListener('mousedown', (e) => {
|
bubblesContainer.addEventListener('mousedown', (e) => {
|
||||||
//console.log('selection mousedown', e);
|
//console.log('selection mousedown', e);
|
||||||
if(e.button != 0) { // LEFT BUTTON
|
if(e.button != 0 || (!this.selectedMids.size && !(e.target as HTMLElement).classList.contains('bubble'))) { // LEFT BUTTON
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +181,28 @@ export default class ChatSelection {
|
|||||||
if(!this.selectedMids.size) return;
|
if(!this.selectedMids.size) return;
|
||||||
this.selectionCountEl.innerText = this.selectedMids.size + ' Message' + (this.selectedMids.size == 1 ? '' : 's');
|
this.selectionCountEl.innerText = this.selectedMids.size + ' Message' + (this.selectedMids.size == 1 ? '' : 's');
|
||||||
|
|
||||||
|
let cantForward = false, cantDelete = false;
|
||||||
|
for(const mid of this.selectedMids.values()) {
|
||||||
|
const message = this.appMessagesManager.getMessage(mid);
|
||||||
|
if(!cantForward) {
|
||||||
|
if(message.action) {
|
||||||
|
cantForward = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!cantDelete) {
|
||||||
|
const canDelete = this.appMessagesManager.canDeleteMessage(mid);
|
||||||
|
if(!canDelete) {
|
||||||
|
cantDelete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cantForward && cantDelete) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectionForwardBtn.toggleAttribute('disabled', cantForward);
|
||||||
|
this.selectionDeleteBtn.toggleAttribute('disabled', cantDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleSelection(toggleCheckboxes = true) {
|
public toggleSelection(toggleCheckboxes = true) {
|
||||||
@ -180,11 +214,23 @@ export default class ChatSelection {
|
|||||||
const bubblesContainer = this.appImManager.bubblesContainer;
|
const bubblesContainer = this.appImManager.bubblesContainer;
|
||||||
//bubblesContainer.classList.toggle('is-selecting', !!this.selectedMids.size);
|
//bubblesContainer.classList.toggle('is-selecting', !!this.selectedMids.size);
|
||||||
|
|
||||||
|
/* if(bubblesContainer.classList.contains('is-chat-input-hidden')) {
|
||||||
|
const scrollable = this.appImManager.scrollable;
|
||||||
|
if(scrollable.isScrolledDown) {
|
||||||
|
scrollable.scrollTo(scrollable.scrollHeight, 'top', true, true, 200);
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
SetTransition(bubblesContainer, 'is-selecting', !!this.selectedMids.size, 200, () => {
|
SetTransition(bubblesContainer, 'is-selecting', !!this.selectedMids.size, 200, () => {
|
||||||
if(!this.isSelecting) {
|
if(!this.isSelecting) {
|
||||||
this.selectionContainer.remove();
|
this.selectionContainer.remove();
|
||||||
this.selectionContainer = null;
|
this.selectionContainer = this.selectionForwardBtn = this.selectionDeleteBtn = null;
|
||||||
|
this.selectedText = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
this.appImManager.onScroll();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
//const chatInput = this.appImManager.chatInput;
|
//const chatInput = this.appImManager.chatInput;
|
||||||
@ -201,19 +247,23 @@ export default class ChatSelection {
|
|||||||
this.selectionCountEl = document.createElement('div');
|
this.selectionCountEl = document.createElement('div');
|
||||||
this.selectionCountEl.classList.add('selection-container-count');
|
this.selectionCountEl.classList.add('selection-container-count');
|
||||||
|
|
||||||
const btnForward = Button('btn-primary btn-transparent', {icon: 'forward'});
|
this.selectionForwardBtn = Button('btn-primary btn-transparent selection-container-forward', {icon: 'forward'});
|
||||||
btnForward.append('Forward');
|
this.selectionForwardBtn.append('Forward');
|
||||||
|
this.selectionForwardBtn.addEventListener('click', () => {
|
||||||
btnForward.addEventListener('click', () => {
|
|
||||||
new PopupForward([...this.selectedMids], () => {
|
new PopupForward([...this.selectedMids], () => {
|
||||||
this.cancelSelection();
|
this.cancelSelection();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const btnDelete = Button('btn-primary btn-transparent danger', {icon: 'delete'});
|
this.selectionDeleteBtn = Button('btn-primary btn-transparent danger selection-container-delete', {icon: 'delete'});
|
||||||
btnDelete.append('Delete');
|
this.selectionDeleteBtn.append('Delete');
|
||||||
|
this.selectionDeleteBtn.addEventListener('click', () => {
|
||||||
|
new PopupDeleteMessages([...this.selectedMids], () => {
|
||||||
|
this.cancelSelection();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this.selectionContainer.append(btnCancel, this.selectionCountEl, btnForward, btnDelete);
|
this.selectionContainer.append(btnCancel, this.selectionCountEl, this.selectionForwardBtn, this.selectionDeleteBtn);
|
||||||
|
|
||||||
inputMessageDiv.append(this.selectionContainer);
|
inputMessageDiv.append(this.selectionContainer);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import $rootScope from "../lib/rootScope";
|
import $rootScope from "../lib/rootScope";
|
||||||
import { cancelEvent } from "../lib/utils";
|
import { cancelEvent, findUpClassName } from "../lib/utils";
|
||||||
import AvatarElement from "./avatar";
|
|
||||||
import { ripple } from "./ripple";
|
import { ripple } from "./ripple";
|
||||||
|
|
||||||
export class PopupElement {
|
export class PopupElement {
|
||||||
@ -16,7 +15,7 @@ export class PopupElement {
|
|||||||
protected onCloseAfterTimeout: () => void;
|
protected onCloseAfterTimeout: () => void;
|
||||||
protected onEscape: () => boolean = () => true;
|
protected onEscape: () => boolean = () => true;
|
||||||
|
|
||||||
constructor(className: string, buttons?: Array<PopupButton>, options: Partial<{closable: boolean, withConfirm: string, body: boolean}> = {}) {
|
constructor(className: string, buttons?: Array<PopupButton>, options: Partial<{closable: true, overlayClosable: true, withConfirm: string, body: true}> = {}) {
|
||||||
this.element.classList.add('popup');
|
this.element.classList.add('popup');
|
||||||
this.element.className = 'popup' + (className ? ' ' + className : '');
|
this.element.className = 'popup' + (className ? ' ' + className : '');
|
||||||
this.container.classList.add('popup-container', 'z-depth-1');
|
this.container.classList.add('popup-container', 'z-depth-1');
|
||||||
@ -33,6 +32,16 @@ export class PopupElement {
|
|||||||
this.header.prepend(this.closeBtn);
|
this.header.prepend(this.closeBtn);
|
||||||
|
|
||||||
this.closeBtn.addEventListener('click', this.destroy, {once: true});
|
this.closeBtn.addEventListener('click', this.destroy, {once: true});
|
||||||
|
|
||||||
|
if(options.overlayClosable) {
|
||||||
|
const onOverlayClick = (e: MouseEvent) => {
|
||||||
|
if(!findUpClassName(e.target, 'popup-container')) {
|
||||||
|
this.closeBtn.click();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.element.addEventListener('click', onOverlayClick, {once: true});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('keydown', this._onKeyDown, {capture: true});
|
window.addEventListener('keydown', this._onKeyDown, {capture: true});
|
||||||
|
65
src/components/popupDeleteMessages.ts
Normal file
65
src/components/popupDeleteMessages.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import appChatsManager from "../lib/appManagers/appChatsManager";
|
||||||
|
import appMessagesManager from "../lib/appManagers/appMessagesManager";
|
||||||
|
import appPeersManager from "../lib/appManagers/appPeersManager";
|
||||||
|
import $rootScope from "../lib/rootScope";
|
||||||
|
import { PopupButton } from "./popup";
|
||||||
|
import PopupPeer from "./popupPeer";
|
||||||
|
|
||||||
|
export default class PopupDeleteMessages {
|
||||||
|
constructor(mids: number[], onConfirm?: () => void) {
|
||||||
|
const peerID = $rootScope.selectedPeerID;
|
||||||
|
const firstName = appPeersManager.getPeerTitle(peerID, false, true);
|
||||||
|
|
||||||
|
mids = mids.slice();
|
||||||
|
const callback = (revoke: boolean) => {
|
||||||
|
onConfirm && onConfirm();
|
||||||
|
appMessagesManager.deleteMessages(mids, revoke);
|
||||||
|
};
|
||||||
|
|
||||||
|
let title: string, description: string, buttons: PopupButton[];
|
||||||
|
title = `Delete Message${mids.length == 1 ? '' : 's'}?`;
|
||||||
|
description = `Are you sure you want to delete ${mids.length == 1 ? 'this message' : 'these messages'}?`;
|
||||||
|
|
||||||
|
if(peerID == $rootScope.myID) {
|
||||||
|
buttons = [{
|
||||||
|
text: 'DELETE',
|
||||||
|
isDanger: true,
|
||||||
|
callback: () => callback(false)
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
buttons = [{
|
||||||
|
text: 'DELETE JUST FOR ME',
|
||||||
|
isDanger: true,
|
||||||
|
callback: () => callback(false)
|
||||||
|
}];
|
||||||
|
|
||||||
|
if(peerID > 0) {
|
||||||
|
buttons.push({
|
||||||
|
text: 'DELETE FOR ME AND ' + firstName,
|
||||||
|
isDanger: true,
|
||||||
|
callback: () => callback(true)
|
||||||
|
});
|
||||||
|
} else if(appChatsManager.hasRights(-peerID, 'deleteRevoke')) {
|
||||||
|
buttons.push({
|
||||||
|
text: 'DELETE FOR ALL',
|
||||||
|
isDanger: true,
|
||||||
|
callback: () => callback(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buttons.push({
|
||||||
|
text: 'CANCEL',
|
||||||
|
isCancel: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const popup = new PopupPeer('popup-delete-chat', {
|
||||||
|
peerID: peerID,
|
||||||
|
title: title,
|
||||||
|
description: description,
|
||||||
|
buttons: buttons
|
||||||
|
});
|
||||||
|
|
||||||
|
popup.show();
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
import { isTouchSupported } from "../helpers/touchSupport";
|
||||||
import appImManager from "../lib/appManagers/appImManager";
|
import appImManager from "../lib/appManagers/appImManager";
|
||||||
import AppSelectPeers from "./appSelectPeers";
|
import AppSelectPeers from "./appSelectPeers";
|
||||||
import { PopupElement } from "./popup";
|
import { PopupElement } from "./popup";
|
||||||
@ -6,8 +7,10 @@ export default class PopupForward extends PopupElement {
|
|||||||
private selector: AppSelectPeers;
|
private selector: AppSelectPeers;
|
||||||
//private scrollable: Scrollable;
|
//private scrollable: Scrollable;
|
||||||
|
|
||||||
constructor(mids: number[], onSelect?: () => Promise<void> | void) {
|
constructor(mids: number[], onSelect?: () => Promise<void> | void, onClose?: () => void) {
|
||||||
super('popup-forward', null, {closable: true, body: true});
|
super('popup-forward', null, {closable: true, overlayClosable: true, body: true});
|
||||||
|
|
||||||
|
if(onClose) this.onClose = onClose;
|
||||||
|
|
||||||
this.selector = new AppSelectPeers(this.body, async() => {
|
this.selector = new AppSelectPeers(this.body, async() => {
|
||||||
const peerID = this.selector.getSelected()[0];
|
const peerID = this.selector.getSelected()[0];
|
||||||
@ -21,6 +24,10 @@ export default class PopupForward extends PopupElement {
|
|||||||
appImManager.chatInputC.initMessagesForward(mids.slice());
|
appImManager.chatInputC.initMessagesForward(mids.slice());
|
||||||
}, ['dialogs', 'contacts'], () => {
|
}, ['dialogs', 'contacts'], () => {
|
||||||
this.show();
|
this.show();
|
||||||
|
|
||||||
|
if(!isTouchSupported) {
|
||||||
|
this.selector.input.focus();
|
||||||
|
}
|
||||||
}, null, 'send', false);
|
}, null, 'send', false);
|
||||||
|
|
||||||
//this.scrollable = new Scrollable(this.body);
|
//this.scrollable = new Scrollable(this.body);
|
||||||
|
@ -9,6 +9,7 @@ import animationIntersector from "./animationIntersector";
|
|||||||
import { findUpClassName } from "../lib/utils";
|
import { findUpClassName } from "../lib/utils";
|
||||||
import appImManager from "../lib/appManagers/appImManager";
|
import appImManager from "../lib/appManagers/appImManager";
|
||||||
import { StickerSet } from "../layer";
|
import { StickerSet } from "../layer";
|
||||||
|
import mediaSizes from "../helpers/mediaSizes";
|
||||||
|
|
||||||
const ANIMATION_GROUP = 'STICKERS-POPUP';
|
const ANIMATION_GROUP = 'STICKERS-POPUP';
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ export default class PopupStickers extends PopupElement {
|
|||||||
id: string,
|
id: string,
|
||||||
access_hash: string
|
access_hash: string
|
||||||
}) {
|
}) {
|
||||||
super('popup-stickers', null, {closable: true, body: true});
|
super('popup-stickers', null, {closable: true, overlayClosable: true, body: true});
|
||||||
|
|
||||||
this.h6 = document.createElement('h6');
|
this.h6 = document.createElement('h6');
|
||||||
this.h6.innerText = 'Loading...';
|
this.h6.innerText = 'Loading...';
|
||||||
@ -36,21 +37,12 @@ export default class PopupStickers extends PopupElement {
|
|||||||
animationIntersector.checkAnimations(false);
|
animationIntersector.checkAnimations(false);
|
||||||
this.stickersFooter.removeEventListener('click', this.onFooterClick);
|
this.stickersFooter.removeEventListener('click', this.onFooterClick);
|
||||||
this.stickersDiv.removeEventListener('click', this.onStickersClick);
|
this.stickersDiv.removeEventListener('click', this.onStickersClick);
|
||||||
this.element.removeEventListener('click', onOverlayClick);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onCloseAfterTimeout = () => {
|
this.onCloseAfterTimeout = () => {
|
||||||
animationIntersector.checkAnimations(undefined, ANIMATION_GROUP);
|
animationIntersector.checkAnimations(undefined, ANIMATION_GROUP);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOverlayClick = (e: MouseEvent) => {
|
|
||||||
if(!findUpClassName(e.target, 'popup-container')) {
|
|
||||||
this.closeBtn.click();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.element.addEventListener('click', onOverlayClick);
|
|
||||||
|
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.classList.add('sticker-set');
|
div.classList.add('sticker-set');
|
||||||
|
|
||||||
@ -129,6 +121,8 @@ export default class PopupStickers extends PopupElement {
|
|||||||
|
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.classList.add('sticker-set-sticker');
|
div.classList.add('sticker-set-sticker');
|
||||||
|
|
||||||
|
const size = mediaSizes.active.esgSticker.width;
|
||||||
|
|
||||||
wrapSticker({
|
wrapSticker({
|
||||||
doc,
|
doc,
|
||||||
@ -137,8 +131,8 @@ export default class PopupStickers extends PopupElement {
|
|||||||
group: ANIMATION_GROUP,
|
group: ANIMATION_GROUP,
|
||||||
play: true,
|
play: true,
|
||||||
loop: true,
|
loop: true,
|
||||||
width: 80,
|
width: size,
|
||||||
height: 80
|
height: size
|
||||||
});
|
});
|
||||||
|
|
||||||
this.stickersDiv.append(div);
|
this.stickersDiv.append(div);
|
||||||
|
@ -10,7 +10,7 @@ import appMessagesManager from '../lib/appManagers/appMessagesManager';
|
|||||||
import appPhotosManager, { MyPhoto } from '../lib/appManagers/appPhotosManager';
|
import appPhotosManager, { MyPhoto } from '../lib/appManagers/appPhotosManager';
|
||||||
import LottieLoader from '../lib/lottieLoader';
|
import LottieLoader from '../lib/lottieLoader';
|
||||||
import VideoPlayer from '../lib/mediaPlayer';
|
import VideoPlayer from '../lib/mediaPlayer';
|
||||||
import { formatBytes, getEmojiToneIndex, isInDOM } from "../lib/utils";
|
import { cancelEvent, formatBytes, getEmojiToneIndex, isInDOM } from "../lib/utils";
|
||||||
import webpWorkerController from '../lib/webp/webpWorkerController';
|
import webpWorkerController from '../lib/webp/webpWorkerController';
|
||||||
import animationIntersector from './animationIntersector';
|
import animationIntersector from './animationIntersector';
|
||||||
import appMediaPlaybackController from './appMediaPlaybackController';
|
import appMediaPlaybackController from './appMediaPlaybackController';
|
||||||
@ -353,7 +353,7 @@ export function wrapDocument(doc: MyDocument, withTime = false, uploading = fals
|
|||||||
let preloader: ProgressivePreloader;
|
let preloader: ProgressivePreloader;
|
||||||
let download: DownloadBlob;
|
let download: DownloadBlob;
|
||||||
|
|
||||||
docDiv.addEventListener('click', () => {
|
docDiv.addEventListener('click', (e) => {
|
||||||
if(!download) {
|
if(!download) {
|
||||||
if(downloadDiv.classList.contains('downloading')) {
|
if(downloadDiv.classList.contains('downloading')) {
|
||||||
return; // means not ready yet
|
return; // means not ready yet
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export const isTouchSupported = ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch);
|
export const isTouchSupported = ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)/* || true */;
|
@ -440,8 +440,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="bubbles" class="scrolled-down">
|
<div id="bubbles" class="scrolled-down">
|
||||||
<div id="bubbles-inner"></div>
|
{{!-- <div id="bubbles-transform-helper"> --}}
|
||||||
<div id="bubbles-go-down" class="tgico-down btn-corner z-depth-1 rp hide"></div>
|
<div id="bubbles-inner"></div>
|
||||||
|
<div id="bubbles-go-down" class="tgico-down btn-corner z-depth-1 rp hide"></div>
|
||||||
|
{{!-- </div> --}}
|
||||||
</div>
|
</div>
|
||||||
<div id="chat-input" style="display: none;">
|
<div id="chat-input" style="display: none;">
|
||||||
<div class="chat-input-container">
|
<div class="chat-input-container">
|
||||||
|
@ -63,6 +63,7 @@ const ANIMATION_GROUP = 'chat';
|
|||||||
|
|
||||||
export class AppImManager {
|
export class AppImManager {
|
||||||
public columnEl = document.getElementById('column-center') as HTMLDivElement;
|
public columnEl = document.getElementById('column-center') as HTMLDivElement;
|
||||||
|
public backgroundEl = this.columnEl.firstElementChild as HTMLDivElement;
|
||||||
public btnJoin = this.columnEl.querySelector('.chat-join') as HTMLButtonElement;
|
public btnJoin = this.columnEl.querySelector('.chat-join') as HTMLButtonElement;
|
||||||
public btnMute = this.columnEl.querySelector('.chat-mute-button') as HTMLButtonElement;
|
public btnMute = this.columnEl.querySelector('.chat-mute-button') as HTMLButtonElement;
|
||||||
public avatarEl = document.getElementById('im-avatar') as AvatarElement;
|
public avatarEl = document.getElementById('im-avatar') as AvatarElement;
|
||||||
@ -123,7 +124,7 @@ export class AppImManager {
|
|||||||
|
|
||||||
public contextMenu = new ChatContextMenu(this.bubblesContainer);
|
public contextMenu = new ChatContextMenu(this.bubblesContainer);
|
||||||
|
|
||||||
private setPeerPromise: Promise<boolean> = null;
|
public setPeerPromise: Promise<boolean> = null;
|
||||||
|
|
||||||
public bubbleGroups = new BubbleGroups();
|
public bubbleGroups = new BubbleGroups();
|
||||||
|
|
||||||
@ -137,7 +138,7 @@ export class AppImManager {
|
|||||||
private loadedTopTimes = 0;
|
private loadedTopTimes = 0;
|
||||||
private loadedBottomTimes = 0;
|
private loadedBottomTimes = 0;
|
||||||
|
|
||||||
private messagesQueuePromise: Promise<void> = null;
|
public messagesQueuePromise: Promise<void> = null;
|
||||||
private messagesQueue: {message: any, bubble: HTMLDivElement, reverse: boolean, promises: Promise<void>[]}[] = [];
|
private messagesQueue: {message: any, bubble: HTMLDivElement, reverse: boolean, promises: Promise<void>[]}[] = [];
|
||||||
private messagesQueueOnRender: () => void = null;
|
private messagesQueueOnRender: () => void = null;
|
||||||
|
|
||||||
@ -437,9 +438,19 @@ export class AppImManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ! Trusted - due to audio autoclick
|
// ! Trusted - due to audio autoclick
|
||||||
if(this.chatSelection.isSelecting && !bubble.classList.contains('service') && e.isTrusted) {
|
if(this.chatSelection.isSelecting && e.isTrusted) {
|
||||||
|
if(bubble.classList.contains('service') && bubble.dataset.mid === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cancelEvent(e);
|
cancelEvent(e);
|
||||||
//console.log('bubble click', e);
|
//console.log('bubble click', e);
|
||||||
|
|
||||||
|
if(isTouchSupported && this.chatSelection.selectedText) {
|
||||||
|
this.chatSelection.selectedText = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.chatSelection.toggleByBubble(bubble);
|
this.chatSelection.toggleByBubble(bubble);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -526,6 +537,7 @@ export class AppImManager {
|
|||||||
new AppMediaViewer().openMedia(message, targets[idx].element, true,
|
new AppMediaViewer().openMedia(message, targets[idx].element, true,
|
||||||
targets.slice(0, idx), targets.slice(idx + 1)/* , !message.grouped_id */);
|
targets.slice(0, idx), targets.slice(idx + 1)/* , !message.grouped_id */);
|
||||||
|
|
||||||
|
cancelEvent(e);
|
||||||
//appMediaViewer.openMedia(message, target as HTMLImageElement);
|
//appMediaViewer.openMedia(message, target as HTMLImageElement);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -552,7 +564,7 @@ export class AppImManager {
|
|||||||
if(!isNaN(peerID)) {
|
if(!isNaN(peerID)) {
|
||||||
this.setPeer(peerID);
|
this.setPeer(peerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if(target.tagName == "AVATAR-ELEMENT") {
|
} else if(target.tagName == "AVATAR-ELEMENT") {
|
||||||
let peerID = +target.getAttribute('peer');
|
let peerID = +target.getAttribute('peer');
|
||||||
@ -560,7 +572,7 @@ export class AppImManager {
|
|||||||
if(!isNaN(peerID)) {
|
if(!isNaN(peerID)) {
|
||||||
this.setPeer(peerID);
|
this.setPeer(peerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +595,7 @@ export class AppImManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//console.log('chatInner click', e);
|
//console.log('chatInner click', e);
|
||||||
});
|
}, {capture: true, passive: false});
|
||||||
|
|
||||||
this.closeBtn.addEventListener('click', (e) => {
|
this.closeBtn.addEventListener('click', (e) => {
|
||||||
cancelEvent(e);
|
cancelEvent(e);
|
||||||
@ -831,7 +843,7 @@ export class AppImManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public onScroll(e: Event) {
|
public onScroll() {
|
||||||
if(this.onScrollRAF) window.cancelAnimationFrame(this.onScrollRAF);
|
if(this.onScrollRAF) window.cancelAnimationFrame(this.onScrollRAF);
|
||||||
|
|
||||||
// * В таком случае, кнопка не будет моргать если чат в самом низу, и правильно отработает случай написания нового сообщения и проскролла вниз
|
// * В таком случае, кнопка не будет моргать если чат в самом низу, и правильно отработает случай написания нового сообщения и проскролла вниз
|
||||||
@ -854,10 +866,10 @@ export class AppImManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(this.scrollable.isScrolledDown) {
|
if(this.scrollable.isScrolledDown) {
|
||||||
this.scroll.parentElement.classList.add('scrolled-down');
|
this.bubblesContainer.classList.add('scrolled-down');
|
||||||
this.scrolledDown = true;
|
this.scrolledDown = true;
|
||||||
} else if(this.scroll.parentElement.classList.contains('scrolled-down')) {
|
} else if(this.bubblesContainer.classList.contains('scrolled-down')) {
|
||||||
this.scroll.parentElement.classList.remove('scrolled-down');
|
this.bubblesContainer.classList.remove('scrolled-down');
|
||||||
this.scrolledDown = false;
|
this.scrolledDown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,7 +878,7 @@ export class AppImManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public setScroll() {
|
public setScroll() {
|
||||||
this.scrollable = new Scrollable(this.bubblesContainer, 'IM', this.chatInner, 300);
|
this.scrollable = new Scrollable(this.bubblesContainer/* .firstElementChild */ as HTMLElement, 'IM', this.chatInner, 300);
|
||||||
|
|
||||||
/* const getScrollOffset = () => {
|
/* const getScrollOffset = () => {
|
||||||
//return Math.round(Math.max(300, appPhotosManager.windowH / 1.5));
|
//return Math.round(Math.max(300, appPhotosManager.windowH / 1.5));
|
||||||
@ -880,14 +892,14 @@ export class AppImManager {
|
|||||||
this.scrollable = new Scrollable(this.bubblesContainer, 'y', 'IM', this.chatInner, getScrollOffset()); */
|
this.scrollable = new Scrollable(this.bubblesContainer, 'y', 'IM', this.chatInner, getScrollOffset()); */
|
||||||
this.scroll = this.scrollable.container;
|
this.scroll = this.scrollable.container;
|
||||||
|
|
||||||
this.bubblesContainer.append(this.goDownBtn);
|
this.bubblesContainer/* .firstElementChild */.append(this.goDownBtn);
|
||||||
|
|
||||||
this.scrollable.onScrolledTop = () => this.loadMoreHistory(true);
|
this.scrollable.onScrolledTop = () => this.loadMoreHistory(true);
|
||||||
this.scrollable.onScrolledBottom = () => this.loadMoreHistory(false);
|
this.scrollable.onScrolledBottom = () => this.loadMoreHistory(false);
|
||||||
//this.scrollable.attachSentinels(undefined, 300);
|
//this.scrollable.attachSentinels(undefined, 300);
|
||||||
|
|
||||||
this.scroll.addEventListener('scroll', this.onScroll.bind(this));
|
this.scroll.addEventListener('scroll', this.onScroll.bind(this));
|
||||||
this.scroll.parentElement.classList.add('scrolled-down');
|
this.bubblesContainer.classList.add('scrolled-down');
|
||||||
|
|
||||||
if(isTouchSupported) {
|
if(isTouchSupported) {
|
||||||
this.scroll.addEventListener('touchmove', () => {
|
this.scroll.addEventListener('touchmove', () => {
|
||||||
@ -1289,9 +1301,18 @@ export class AppImManager {
|
|||||||
this.chatInner.classList.toggle('has-rights', hasRights);
|
this.chatInner.classList.toggle('has-rights', hasRights);
|
||||||
|
|
||||||
const canWrite = (!isChannel || hasRights) && (peerID < 0 || appUsersManager.canSendToUser(peerID));
|
const canWrite = (!isChannel || hasRights) && (peerID < 0 || appUsersManager.canSendToUser(peerID));
|
||||||
this.chatInput.style.display = canWrite ? '' : 'none';
|
//const needToChangeInputDisplay = !(!this.chatInput.classList.contains('is-hidden') && canWrite);
|
||||||
|
//this.chatInput.style.display = needToChangeInputDisplay ? 'none' : '';
|
||||||
|
this.chatInput.style.display = '';
|
||||||
|
this.chatInput.classList.toggle('is-hidden', !canWrite);
|
||||||
|
this.bubblesContainer.classList.toggle('is-chat-input-hidden', !canWrite);
|
||||||
|
|
||||||
this.chatInner.classList.toggle('is-chat-input-hidden', !canWrite);
|
// const noTransition = [this.columnEl/* appSidebarRight.sidebarEl, this.backgroundEl,
|
||||||
|
// this.bubblesContainer, this.chatInput, this.chatInner,
|
||||||
|
// this.chatInputC.replyElements.container */];
|
||||||
|
// noTransition.forEach(el => {
|
||||||
|
// el.classList.add('no-transition-all');
|
||||||
|
// });
|
||||||
|
|
||||||
this.topbar.classList.remove('is-pinned-shown');
|
this.topbar.classList.remove('is-pinned-shown');
|
||||||
this.topbar.style.display = '';
|
this.topbar.style.display = '';
|
||||||
@ -1308,6 +1329,13 @@ export class AppImManager {
|
|||||||
this.setPinnedMessage();
|
this.setPinnedMessage();
|
||||||
|
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
|
/* noTransition.forEach(el => {
|
||||||
|
el.classList.remove('no-transition-all');
|
||||||
|
}); */
|
||||||
|
/* if(needToChangeInputDisplay) {
|
||||||
|
this.chatInput.style.display = '';
|
||||||
|
} */
|
||||||
|
|
||||||
let title = '';
|
let title = '';
|
||||||
if(this.peerID == this.myID) title = 'Saved Messages';
|
if(this.peerID == this.myID) title = 'Saved Messages';
|
||||||
else title = appPeersManager.getPeerTitle(this.peerID);
|
else title = appPeersManager.getPeerTitle(this.peerID);
|
||||||
|
@ -2018,7 +2018,7 @@ export class AppMessagesManager {
|
|||||||
withMyScore: true
|
withMyScore: true
|
||||||
}> = {}) {
|
}> = {}) {
|
||||||
peerID = appPeersManager.getPeerMigratedTo(peerID) || peerID;
|
peerID = appPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||||
mids = mids.sort((a, b) => a - b);
|
mids = mids.slice().sort((a, b) => a - b);
|
||||||
|
|
||||||
const splitted = appMessagesIDsManager.splitMessageIDsByChannels(mids);
|
const splitted = appMessagesIDsManager.splitMessageIDsByChannels(mids);
|
||||||
const promises: Promise<void>[] = [];
|
const promises: Promise<void>[] = [];
|
||||||
@ -2442,6 +2442,9 @@ export class AppMessagesManager {
|
|||||||
case 'messageMediaPhoto':
|
case 'messageMediaPhoto':
|
||||||
messageText += '<i>Photo' + (message.message ? ', ' : '') + '</i>';
|
messageText += '<i>Photo' + (message.message ? ', ' : '') + '</i>';
|
||||||
break;
|
break;
|
||||||
|
case 'messageMediaDice':
|
||||||
|
messageText += RichTextProcessor.wrapEmojiText(message.media.emoticon);
|
||||||
|
break;
|
||||||
case 'messageMediaGeo':
|
case 'messageMediaGeo':
|
||||||
messageText += '<i>Geolocation</i>';
|
messageText += '<i>Geolocation</i>';
|
||||||
break;
|
break;
|
||||||
@ -2471,6 +2474,7 @@ export class AppMessagesManager {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
//messageText += message.media._;
|
||||||
///////this.log.warn('Got unknown message.media type!', message);
|
///////this.log.warn('Got unknown message.media type!', message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2660,6 +2664,15 @@ export class AppMessagesManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public canDeleteMessage(messageID: number) {
|
||||||
|
const message = this.messagesStorage[messageID];
|
||||||
|
if(message) {
|
||||||
|
return message.peerID > 0 || message.fromID == $rootScope.myID || appChatsManager.hasRights(message.peerID, 'deleteRevoke');
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public applyConversations(dialogsResult: MessagesPeerDialogs.messagesPeerDialogs) {
|
public applyConversations(dialogsResult: MessagesPeerDialogs.messagesPeerDialogs) {
|
||||||
// * В эту функцию попадут только те диалоги, в которых есть read_inbox_max_id и read_outbox_max_id, в отличие от тех, что будут в getTopMessages
|
// * В эту функцию попадут только те диалоги, в которых есть read_inbox_max_id и read_outbox_max_id, в отличие от тех, что будут в getTopMessages
|
||||||
|
|
||||||
|
@ -349,12 +349,12 @@ namespace RichTextProcessor {
|
|||||||
entities: MessageEntity[],
|
entities: MessageEntity[],
|
||||||
contextSite: string,
|
contextSite: string,
|
||||||
highlightUsername: string,
|
highlightUsername: string,
|
||||||
noLinks: boolean,
|
noLinks: true,
|
||||||
noLinebreaks: boolean,
|
noLinebreaks: true,
|
||||||
noCommands: boolean,
|
noCommands: true,
|
||||||
fromBot: boolean,
|
fromBot: boolean,
|
||||||
noTextFormat: boolean,
|
noTextFormat: true,
|
||||||
nested?: boolean,
|
nested?: true,
|
||||||
contextHashtag?: string
|
contextHashtag?: string
|
||||||
}> = {}) {
|
}> = {}) {
|
||||||
if(!text || !text.length) {
|
if(!text || !text.length) {
|
||||||
|
@ -607,4 +607,15 @@ export function cancelSelection() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSelectedText() {
|
||||||
|
if(window.getSelection) {
|
||||||
|
return window.getSelection().toString();
|
||||||
|
// @ts-ignore
|
||||||
|
} else if(document.selection) {
|
||||||
|
// @ts-ignore
|
||||||
|
return document.selection.createRange().text;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
//(window as any).splitStringByLength = splitStringByLength;
|
//(window as any).splitStringByLength = splitStringByLength;
|
||||||
|
@ -88,6 +88,14 @@ Utility Classes
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* .no-transition {
|
||||||
|
transition: none !important;
|
||||||
|
|
||||||
|
&-all, &-all * {
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
.center-align, .text-center {
|
.center-align, .text-center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
@ -214,6 +214,7 @@ $chat-helper-size: 39px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#chat-input {
|
#chat-input {
|
||||||
|
--translateY: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@ -222,6 +223,8 @@ $chat-helper-size: 39px;
|
|||||||
flex: 0 0 auto; /* Forces side columns to stay same width */
|
flex: 0 0 auto; /* Forces side columns to stay same width */
|
||||||
position: relative;
|
position: relative;
|
||||||
//overflow: hidden;
|
//overflow: hidden;
|
||||||
|
transition: transform var(--layer-transition);
|
||||||
|
transform: translateY(var(--translateY));
|
||||||
|
|
||||||
/* // * for no ESG top
|
/* // * for no ESG top
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
@ -235,10 +238,10 @@ $chat-helper-size: 39px;
|
|||||||
|
|
||||||
@include respond-to(medium-screens) {
|
@include respond-to(medium-screens) {
|
||||||
width: calc(100% - var(--right-column-width));
|
width: calc(100% - var(--right-column-width));
|
||||||
transition: transform var(--layer-transition);
|
//transition: transform var(--layer-transition);
|
||||||
|
|
||||||
body.is-right-column-shown & {
|
body.is-right-column-shown & {
|
||||||
transform: translate3d(calc(var(--right-column-width) / -2), 0, 0);
|
transform: translate3d(calc(var(--right-column-width) / -2), var(--translateY), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.animation-level-0 & {
|
body.animation-level-0 & {
|
||||||
@ -246,20 +249,31 @@ $chat-helper-size: 39px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-hidden {
|
||||||
|
--translateY: 100%;
|
||||||
|
transform: translate3d(0, var(--translateY), 0);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
#bubbles.is-selecting:not(.backwards) ~ & {
|
||||||
|
--translateY: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.chat-input-container {
|
.chat-input-container {
|
||||||
|
--padding-horizontal: #{$chat-padding-handhelds};
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
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%;
|
||||||
padding: 0 $chat-padding-handhelds;
|
padding: 0 var(--padding-horizontal);
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@include respond-to(not-handhelds) {
|
@include respond-to(not-handhelds) {
|
||||||
padding-left: $chat-padding;
|
--padding-horizontal: #{$chat-padding};
|
||||||
padding-right: $chat-padding;
|
|
||||||
padding-bottom: 21px;
|
padding-bottom: 21px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,17 +341,16 @@ $chat-helper-size: 39px;
|
|||||||
top: 0;
|
top: 0;
|
||||||
|
|
||||||
// here percents can be used since there are no other transforms
|
// here percents can be used since there are no other transforms
|
||||||
transform: translateX(calc(-100% + #{-1rem + -$btn-send-margin}));
|
transform: translateX(calc(-100% + var(--padding-horizontal) * -1 + #{-$btn-send-margin}));
|
||||||
|
|
||||||
@include respond-to(handhelds) {
|
/* @include respond-to(handhelds) {
|
||||||
transform: translateX(calc(-100% + #{-.5rem + -$btn-send-margin}));
|
transform: translateX(calc(-100% + #{-.5rem + -$btn-send-margin}));
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-send-container {
|
.btn-send-container {
|
||||||
flex: 0 0 auto;
|
position: absolute;
|
||||||
position: relative;
|
right: var(--padding-horizontal);
|
||||||
align-self: flex-end;
|
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,6 +638,10 @@ $chat-helper-size: 39px;
|
|||||||
.chat-background {
|
.chat-background {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.no-transition:before {
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
&, &:before {
|
&, &:before {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -884,7 +901,7 @@ $chat-helper-size: 39px;
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: calc(100% - #{$chat-input-size + $btn-send-margin});
|
width: calc(100% - #{$chat-input-size + $btn-send-margin});
|
||||||
max-width: 100%;
|
max-width: calc(100% - #{$chat-input-size + $btn-send-margin});
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
@ -920,8 +937,13 @@ $chat-helper-size: 39px;
|
|||||||
@include respond-to(handhelds) {
|
@include respond-to(handhelds) {
|
||||||
--padding: .5px .5rem;
|
--padding: .5px .5rem;
|
||||||
width: calc(100% - #{$chat-input-handhelds-size + $btn-send-margin});
|
width: calc(100% - #{$chat-input-handhelds-size + $btn-send-margin});
|
||||||
|
max-width: calc(100% - #{$chat-input-handhelds-size + $btn-send-margin});
|
||||||
min-height: $chat-input-handhelds-size;
|
min-height: $chat-input-handhelds-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 420px) {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
@include respond-to(esg-bottom) {
|
@include respond-to(esg-bottom) {
|
||||||
--padding: .5px .5rem;
|
--padding: .5px .5rem;
|
||||||
@ -1031,21 +1053,54 @@ $chat-helper-size: 39px;
|
|||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
padding: inherit;
|
padding: inherit;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
font-size: 15px;
|
||||||
|
|
||||||
&-count {
|
&-count {
|
||||||
color: #000;
|
color: #000;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
padding-left: .5rem;
|
white-space: nowrap;
|
||||||
|
//padding-left: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-icon {
|
||||||
|
margin-left: 6px;
|
||||||
|
maRgin-top: 6px;
|
||||||
|
color: #3f454a;
|
||||||
|
height: 42px;
|
||||||
|
width: 42px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
width: 7.5rem;
|
width: auto;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
padding: 0 .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 380px) {
|
||||||
|
font-size: 0;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary + .btn-primary {
|
&-forward {
|
||||||
margin-left: .75rem;
|
&:before {
|
||||||
|
margin-right: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-delete {
|
||||||
|
margin-right: .625rem;
|
||||||
|
margin-left: .375rem;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1086,6 +1141,7 @@ $chat-helper-size: 39px;
|
|||||||
flex: 1 1 auto; /* Lets middle column shrink/grow to available width */
|
flex: 1 1 auto; /* Lets middle column shrink/grow to available width */
|
||||||
//overflow: hidden;
|
//overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
transform: translateY(var(--translateY));
|
transform: translateY(var(--translateY));
|
||||||
transition: transform var(--layer-transition);
|
transition: transform var(--layer-transition);
|
||||||
|
|
||||||
@ -1096,9 +1152,54 @@ $chat-helper-size: 39px;
|
|||||||
.chat-container.is-helper-active & {
|
.chat-container.is-helper-active & {
|
||||||
&:not(.is-selecting), &.is-selecting.backwards {
|
&:not(.is-selecting), &.is-selecting.backwards {
|
||||||
--translateY: -#{$chat-helper-size};
|
--translateY: -#{$chat-helper-size};
|
||||||
|
|
||||||
|
#bubbles-inner {
|
||||||
|
transform: translateY(calc(var(--translateY) * -1));
|
||||||
|
//margin-top: $chat-helper-size;
|
||||||
|
//transition: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-chat-input-hidden.is-selecting:not(.backwards) {
|
||||||
|
--translateY: -79px;
|
||||||
|
|
||||||
|
#bubbles-inner {
|
||||||
|
transform: translateY(calc(var(--translateY) * -1));
|
||||||
|
//margin-top: $chat-helper-size;
|
||||||
|
//transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #bubbles-transform-helper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
position: relative;
|
||||||
|
transform: translateY(var(--translateY));
|
||||||
|
transition: transform var(--layer-transition); */
|
||||||
|
|
||||||
|
> .scrollable {
|
||||||
|
height: auto;
|
||||||
|
/* position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0; */
|
||||||
|
//position: relative; // неизвестно зачем это было
|
||||||
|
|
||||||
|
//display: flex; // for end
|
||||||
|
//flex-direction: unset;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
/* display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end; */
|
||||||
|
// * scrollbar takes some width, don't need to set padding for iOS
|
||||||
|
html.is-safari:not(.is-ios) & {
|
||||||
|
padding-left: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
// ! WARNING, НЕЛЬЗЯ СТАВИТЬ ТРАНСФОРМ КРОМЕ TRANSLATEZ(0) НА БЛОК С OVERFLOW, ОН БУДЕТ ПРЫГАТЬ ВВЕРХ ПРИ ВКЛЮЧЕННОМ ПРАВИЛЕ И ЭТО НЕ ИСПРАВИТЬ JS'ОМ!
|
// ! WARNING, НЕЛЬЗЯ СТАВИТЬ ТРАНСФОРМ КРОМЕ TRANSLATEZ(0) НА БЛОК С OVERFLOW, ОН БУДЕТ ПРЫГАТЬ ВВЕРХ ПРИ ВКЛЮЧЕННОМ ПРАВИЛЕ И ЭТО НЕ ИСПРАВИТЬ JS'ОМ!
|
||||||
@include respond-to(medium-screens) {
|
@include respond-to(medium-screens) {
|
||||||
//transition: transform var(--layer-transition);
|
//transition: transform var(--layer-transition);
|
||||||
@ -1113,9 +1214,6 @@ $chat-helper-size: 39px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.is-selecting {
|
&.is-selecting {
|
||||||
cursor: default !important;
|
|
||||||
user-select: none;
|
|
||||||
|
|
||||||
&:not(.backwards) .is-in .bubble__container {
|
&:not(.backwards) .is-in .bubble__container {
|
||||||
transform: translateX(2.5rem);
|
transform: translateX(2.5rem);
|
||||||
}
|
}
|
||||||
@ -1132,42 +1230,25 @@ $chat-helper-size: 39px;
|
|||||||
/* &.is-selecting > .scrollable::-webkit-scrollbar {
|
/* &.is-selecting > .scrollable::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
> .scrollable {
|
|
||||||
height: auto;
|
|
||||||
/* position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0; */
|
|
||||||
//position: relative; // неизвестно зачем это было
|
|
||||||
|
|
||||||
//display: flex; // for end
|
|
||||||
//flex-direction: unset;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
/* display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-end; */
|
|
||||||
// * scrollbar takes some width, don't need to set padding for iOS
|
|
||||||
html.is-safari:not(.is-ios) & {
|
|
||||||
padding-left: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.scrolled-down):not(.search-results-active) {
|
&:not(.scrolled-down):not(.search-results-active) {
|
||||||
> .scrollable {
|
//> #bubbles-transform-helper {
|
||||||
-webkit-mask-image: -webkit-linear-gradient(bottom, transparent, #000 20px);
|
// ! these lines will blur messages if chat input helper is active
|
||||||
mask-image: linear-gradient(0deg, transparent 0, #000 20px);
|
> .scrollable {
|
||||||
}
|
-webkit-mask-image: -webkit-linear-gradient(bottom, transparent, #000 20px);
|
||||||
|
mask-image: linear-gradient(0deg, transparent 0, #000 20px);
|
||||||
|
}
|
||||||
|
|
||||||
> #bubbles-go-down {
|
> #bubbles-go-down {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
--translateY: 0;
|
--translateY: 0;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
/* &.is-broadcast {
|
/* &.is-broadcast {
|
||||||
--translateY: 79px !important;
|
--translateY: 79px !important;
|
||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
.preloader {
|
.preloader {
|
||||||
@ -1201,6 +1282,11 @@ $chat-helper-size: 39px;
|
|||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
max-width: var(--messages-container-width);
|
max-width: var(--messages-container-width);
|
||||||
|
|
||||||
|
transition: transform var(--layer-transition);
|
||||||
|
transform: translateY(0);
|
||||||
|
/* transition: margin-top var(--layer-transition);
|
||||||
|
transition-delay: .2s; */
|
||||||
|
|
||||||
@include respond-to(medium-screens) {
|
@include respond-to(medium-screens) {
|
||||||
width: calc(100% - var(--right-column-width));
|
width: calc(100% - var(--right-column-width));
|
||||||
}
|
}
|
||||||
@ -1237,9 +1323,9 @@ $chat-helper-size: 39px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-chat-input-hidden {
|
/* #bubbles.is-chat-input-hidden & {
|
||||||
padding-bottom: 55px;
|
padding-bottom: 55px;
|
||||||
}
|
} */
|
||||||
|
|
||||||
&:not(.is-channel), &.is-chat {
|
&:not(.is-channel), &.is-chat {
|
||||||
.message {
|
.message {
|
||||||
|
@ -466,7 +466,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tgico-add:before {
|
.tgico-add:before {
|
||||||
content: "\e903";
|
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
@ -619,17 +618,7 @@
|
|||||||
color: #50a2e9;
|
color: #50a2e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.included-chats-container {
|
.popup-forward, .included-chats-container {
|
||||||
.sidebar-left-h2 {
|
|
||||||
color: #707579;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 6px 24px 8px 24px;
|
|
||||||
|
|
||||||
@include respond-to(handhelds) {
|
|
||||||
padding: 6px 16px 8px 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.selector {
|
.selector {
|
||||||
ul {
|
ul {
|
||||||
li > .rp {
|
li > .rp {
|
||||||
@ -647,10 +636,6 @@
|
|||||||
height: 46px;
|
height: 46px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.user-title {
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-caption {
|
.user-caption {
|
||||||
padding: 0px 0px 0 14px;
|
padding: 0px 0px 0 14px;
|
||||||
margin-top: -2px;
|
margin-top: -2px;
|
||||||
@ -660,7 +645,24 @@
|
|||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.included-chats-container {
|
||||||
|
.sidebar-left-h2 {
|
||||||
|
color: #707579;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 6px 24px 8px 24px;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
padding: 6px 16px 8px 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
ul {
|
||||||
.checkbox {
|
.checkbox {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
@ -129,10 +129,6 @@
|
|||||||
p {
|
p {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.user-title {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.user-last-message {
|
span.user-last-message {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -6,15 +6,15 @@
|
|||||||
width: 420px;
|
width: 420px;
|
||||||
max-width: 420px;
|
max-width: 420px;
|
||||||
//padding: 12px 20px 32.5px;
|
//padding: 12px 20px 32.5px;
|
||||||
padding: .75rem 0 0 0;
|
padding: 9px 0 0 0;
|
||||||
max-height: unquote('min(40.625rem, 100%)');
|
max-height: unquote('min(40.625rem, 100%)');
|
||||||
height: 40.625rem;
|
height: 40.625rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-header {
|
&-header {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
margin-bottom: 9px;
|
margin-bottom: 4px;
|
||||||
padding: 0 .75rem;
|
padding: 0 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
|
@ -60,12 +60,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-sticker {
|
&-sticker {
|
||||||
width: 80px;
|
width: var(--esg-sticker-size);
|
||||||
height: 80px;
|
height: var(--esg-sticker-size);
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background-color: var(--color-gray-hover);
|
background-color: var(--color-gray-hover);
|
||||||
|
@ -840,9 +840,10 @@ input:focus, button:focus {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0; // new
|
padding: 0; // new
|
||||||
|
transition: .2s opacity;
|
||||||
|
|
||||||
html.no-touch &:hover {
|
html.no-touch &:hover {
|
||||||
transition: .2s background-color;
|
transition: .2s background-color, .2s opacity;
|
||||||
background: darken($color-blue, 8%);
|
background: darken($color-blue, 8%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -852,24 +853,31 @@ input:focus, button:focus {
|
|||||||
left: auto;
|
left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
// * tgico
|
&:disabled {
|
||||||
&:before {
|
pointer-events: none !important;
|
||||||
color: #707579;
|
opacity: .25;
|
||||||
font-size: 1.5rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ! example: multiselect input
|
||||||
.btn-transparent {
|
.btn-transparent {
|
||||||
color: #000;
|
color: #000;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
padding: 0 .875rem;
|
||||||
|
//width: auto;
|
||||||
|
|
||||||
html.no-touch &:hover {
|
html.no-touch &:hover {
|
||||||
background-color: var(--color-gray-hover);
|
background-color: var(--color-gray-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * tgico
|
||||||
|
&:before {
|
||||||
|
color: #707579;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary.btn-circle {
|
.btn-primary.btn-circle {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user