Context menu unpin
Refactored pinned container Pin rights fixed again
This commit is contained in:
parent
28b6653e65
commit
076e648300
@ -1,65 +1,43 @@
|
||||
import appImManager from "../../lib/appManagers/appImManager";
|
||||
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
|
||||
import appPeersManager from "../../lib/appManagers/appPeersManager";
|
||||
import { RichTextProcessor } from "../../lib/richtextprocessor";
|
||||
import $rootScope from "../../lib/rootScope";
|
||||
import { cancelEvent } from "../../lib/utils";
|
||||
import appMediaPlaybackController from "../appMediaPlaybackController";
|
||||
import DivAndCaption from "../divAndCaption";
|
||||
import { formatDate } from "../wrappers";
|
||||
import PinnedContainer from "./pinnedContainer";
|
||||
|
||||
export class ChatAudio {
|
||||
public container: HTMLElement;
|
||||
private toggle: HTMLElement;
|
||||
private title: HTMLElement;
|
||||
private subtitle: HTMLElement;
|
||||
private close: HTMLElement;
|
||||
export class ChatAudio extends PinnedContainer {
|
||||
private toggleEl: HTMLElement;
|
||||
|
||||
constructor() {
|
||||
this.container = document.createElement('div');
|
||||
this.container.classList.add('pinned-audio', 'pinned-container');
|
||||
this.container.style.display = 'none';
|
||||
|
||||
this.toggle = document.createElement('div');
|
||||
this.toggle.classList.add('pinned-audio-ico', 'tgico');
|
||||
|
||||
this.title = document.createElement('div');
|
||||
this.title.classList.add('pinned-audio-title');
|
||||
|
||||
this.subtitle = document.createElement('div');
|
||||
this.subtitle.classList.add('pinned-audio-subtitle');
|
||||
|
||||
this.close = document.createElement('button');
|
||||
this.close.classList.add('pinned-audio-close', 'btn-icon', 'tgico-close');
|
||||
|
||||
this.container.append(this.toggle, this.title, this.subtitle, this.close);
|
||||
|
||||
this.close.addEventListener('click', (e) => {
|
||||
cancelEvent(e);
|
||||
const scrollTop = appImManager.scrollable.scrollTop;
|
||||
this.container.style.display = 'none';
|
||||
appImManager.topbar.classList.remove('is-audio-shown');
|
||||
if(this.toggle.classList.contains('flip-icon')) {
|
||||
super('audio', new DivAndCaption('pinned-audio', (title: string, subtitle: string) => {
|
||||
this.divAndCaption.title.innerHTML = title;
|
||||
this.divAndCaption.subtitle.innerHTML = subtitle;
|
||||
}), () => {
|
||||
if(this.toggleEl.classList.contains('flip-icon')) {
|
||||
appMediaPlaybackController.toggle();
|
||||
}
|
||||
|
||||
if(!appImManager.topbar.classList.contains('is-pinned-shown')) {
|
||||
appImManager.scrollable.scrollTop = scrollTop - height;
|
||||
}
|
||||
});
|
||||
|
||||
this.toggle.addEventListener('click', (e) => {
|
||||
this.divAndCaption.border.remove();
|
||||
|
||||
this.toggleEl = document.createElement('div');
|
||||
this.toggleEl.classList.add('pinned-audio-ico', 'tgico');
|
||||
this.toggleEl.addEventListener('click', (e) => {
|
||||
cancelEvent(e);
|
||||
appMediaPlaybackController.toggle();
|
||||
});
|
||||
|
||||
const height = 52;
|
||||
this.divAndCaption.container.prepend(this.toggleEl);
|
||||
|
||||
$rootScope.$on('audio_play', (e) => {
|
||||
const {doc, mid} = e.detail;
|
||||
|
||||
let title: string, subtitle: string;
|
||||
const message = appMessagesManager.getMessage(mid);
|
||||
if(doc.type == 'voice' || doc.type == 'round') {
|
||||
const message = appMessagesManager.getMessage(mid);
|
||||
title = appPeersManager.getPeerTitle(message.fromID, false, true);
|
||||
//subtitle = 'Voice message';
|
||||
subtitle = formatDate(message.date, false, false);
|
||||
@ -68,24 +46,13 @@ export class ChatAudio {
|
||||
subtitle = doc.audioPerformer ? RichTextProcessor.wrapPlainText(doc.audioPerformer) : 'Unknown Artist';
|
||||
}
|
||||
|
||||
this.title.innerHTML = title;
|
||||
this.subtitle.innerHTML = subtitle;
|
||||
this.toggle.classList.add('flip-icon');
|
||||
|
||||
this.container.dataset.mid = '' + mid;
|
||||
if(this.container.style.display) {
|
||||
const scrollTop = appImManager.scrollable.scrollTop;
|
||||
this.container.style.display = '';
|
||||
appImManager.topbar.classList.add('is-audio-shown');
|
||||
|
||||
if(!appImManager.topbar.classList.contains('is-pinned-shown')) {
|
||||
appImManager.scrollable.scrollTop = scrollTop + height;
|
||||
}
|
||||
}
|
||||
this.fill(title, subtitle, message);
|
||||
this.toggleEl.classList.add('flip-icon');
|
||||
this.toggle(false);
|
||||
});
|
||||
|
||||
$rootScope.$on('audio_pause', () => {
|
||||
this.toggle.classList.remove('flip-icon');
|
||||
this.toggleEl.classList.remove('flip-icon');
|
||||
});
|
||||
}
|
||||
}
|
@ -77,7 +77,15 @@ export class ChatContextMenu {
|
||||
icon: 'pin',
|
||||
text: 'Pin',
|
||||
onClick: this.onPinClick,
|
||||
verify: (peerID: number) => peerID == $rootScope.myID || (peerID < 0 && appChatsManager.hasRights(-peerID, 'pin'))
|
||||
verify: (peerID: number, msgID: number) => {
|
||||
const message = appMessagesManager.getMessage(msgID);
|
||||
return message._ != 'messageService' && appImManager.pinnedMsgID != msgID && (peerID == $rootScope.myID || (peerID < 0 && appChatsManager.hasRights(-peerID, 'pin')));
|
||||
}
|
||||
}, {
|
||||
icon: 'unpin',
|
||||
text: 'Unpin',
|
||||
onClick: this.onUnpinClick,
|
||||
verify: (peerID: number, msgID: number) => appImManager.pinnedMsgID == msgID && (peerID == $rootScope.myID || (peerID < 0 && appChatsManager.hasRights(-peerID, 'pin')))
|
||||
}, {
|
||||
icon: 'revote',
|
||||
text: 'Revote',
|
||||
@ -154,6 +162,10 @@ export class ChatContextMenu {
|
||||
appMessagesManager.updatePinnedMessage($rootScope.selectedPeerID, this.msgID);
|
||||
};
|
||||
|
||||
private onUnpinClick = () => {
|
||||
appMessagesManager.updatePinnedMessage($rootScope.selectedPeerID, 0);
|
||||
};
|
||||
|
||||
private onRetractVote = () => {
|
||||
appPollsManager.sendVote(this.msgID, []);
|
||||
};
|
||||
|
61
src/components/chat/pinnedContainer.ts
Normal file
61
src/components/chat/pinnedContainer.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import mediaSizes from "../../helpers/mediaSizes";
|
||||
import appImManager from "../../lib/appManagers/appImManager";
|
||||
import { cancelEvent } from "../../lib/utils";
|
||||
import DivAndCaption from "../divAndCaption";
|
||||
|
||||
const CLASSNAME_SHOWN_MAIN = 'is-pinned-message-shown';
|
||||
const CLASSNAME_BASE = 'pinned-container';
|
||||
const HEIGHT = 52;
|
||||
|
||||
export default class PinnedContainer {
|
||||
private close: HTMLElement;
|
||||
|
||||
constructor(protected className: string, public divAndCaption: DivAndCaption<(title: string, subtitle: string, message?: any) => void>, onClose?: () => void | Promise<boolean>) {
|
||||
/* const prev = this.divAndCaption.fill;
|
||||
this.divAndCaption.fill = (mid, title, subtitle) => {
|
||||
this.divAndCaption.container.dataset.mid = '' + mid;
|
||||
prev(mid, title, subtitle);
|
||||
}; */
|
||||
|
||||
divAndCaption.container.classList.add(CLASSNAME_BASE, 'hide');
|
||||
divAndCaption.title.classList.add(CLASSNAME_BASE + '-title');
|
||||
divAndCaption.subtitle.classList.add(CLASSNAME_BASE + '-subtitle');
|
||||
|
||||
this.close = document.createElement('button');
|
||||
this.close.classList.add(CLASSNAME_BASE + '-close', `pinned-${className}-close`, 'btn-icon', 'tgico-close');
|
||||
|
||||
divAndCaption.container.append(this.close);
|
||||
|
||||
this.close.addEventListener('click', (e) => {
|
||||
cancelEvent(e);
|
||||
|
||||
((onClose ? onClose() : null) || Promise.resolve(true)).then(needClose => {
|
||||
if(needClose) {
|
||||
this.toggle(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public toggle(hide?: boolean) {
|
||||
const isHidden = this.divAndCaption.container.classList.contains('hide');
|
||||
if(hide === undefined) {
|
||||
hide = !isHidden;
|
||||
} else if(hide == isHidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
const scrollTop = mediaSizes.isMobile ? appImManager.scrollable.scrollTop : undefined;
|
||||
this.divAndCaption.container.classList.toggle('hide', hide);
|
||||
appImManager.topbar.classList.toggle(`is-pinned-${this.className}-shown`, !hide);
|
||||
|
||||
if(scrollTop !== undefined && !appImManager.topbar.classList.contains(CLASSNAME_SHOWN_MAIN)) {
|
||||
appImManager.scrollable.scrollTop = scrollTop + ((hide ? -1 : 1) * HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
public fill(title: string, subtitle: string, message: any) {
|
||||
this.divAndCaption.container.dataset.mid = '' + message.mid;
|
||||
this.divAndCaption.fill(title, subtitle, message);
|
||||
}
|
||||
}
|
59
src/components/chat/replyContainer.ts
Normal file
59
src/components/chat/replyContainer.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import appPhotosManager from "../../lib/appManagers/appPhotosManager";
|
||||
import { RichTextProcessor } from "../../lib/richtextprocessor";
|
||||
import DivAndCaption from "../divAndCaption";
|
||||
import { renderImageFromUrl } from "../misc";
|
||||
|
||||
export default class ReplyContainer extends DivAndCaption<(title: string, subtitle: string, message?: any) => void> {
|
||||
private mediaEl: HTMLElement;
|
||||
|
||||
constructor(protected className: string) {
|
||||
super(className, (title: string, subtitle: string = '', message?: any) => {
|
||||
if(title.length > 150) {
|
||||
title = title.substr(0, 140) + '...';
|
||||
}
|
||||
|
||||
if(subtitle.length > 150) {
|
||||
subtitle = subtitle.substr(0, 140) + '...';
|
||||
}
|
||||
|
||||
title = title ? RichTextProcessor.wrapEmojiText(title) : '';
|
||||
|
||||
if(this.mediaEl) {
|
||||
this.mediaEl.remove();
|
||||
this.container.classList.remove('is-media');
|
||||
}
|
||||
|
||||
const media = message && message.media;
|
||||
if(media) {
|
||||
subtitle = message.rReply;
|
||||
|
||||
//console.log('wrap reply', media);
|
||||
|
||||
if(media.photo || (media.document && ['video'].indexOf(media.document.type) !== -1)) {
|
||||
let replyMedia = document.createElement('div');
|
||||
replyMedia.classList.add(this.className + '-media');
|
||||
|
||||
let photo = media.photo || media.document;
|
||||
|
||||
let sizes = photo.sizes || photo.thumbs;
|
||||
if(sizes && sizes[0].bytes) {
|
||||
appPhotosManager.setAttachmentPreview(sizes[0].bytes, replyMedia, false, true);
|
||||
}
|
||||
|
||||
appPhotosManager.preloadPhoto(photo, appPhotosManager.choosePhotoSize(photo, 32, 32))
|
||||
.then(() => {
|
||||
renderImageFromUrl(replyMedia, photo._ == 'photo' ? photo.url : appPhotosManager.getDocumentCachedThumb(photo.id).url);
|
||||
});
|
||||
|
||||
this.content.prepend(this.mediaEl = replyMedia);
|
||||
this.container.classList.add('is-media');
|
||||
}
|
||||
} else {
|
||||
subtitle = subtitle ? RichTextProcessor.wrapEmojiText(subtitle) : '';
|
||||
}
|
||||
|
||||
this.title.innerHTML = title;
|
||||
this.subtitle.innerHTML = subtitle;
|
||||
});
|
||||
}
|
||||
}
|
27
src/components/divAndCaption.ts
Normal file
27
src/components/divAndCaption.ts
Normal file
@ -0,0 +1,27 @@
|
||||
export default class DivAndCaption<T> {
|
||||
public container: HTMLElement;
|
||||
public border: HTMLElement;
|
||||
public content: HTMLElement;
|
||||
public title: HTMLElement;
|
||||
public subtitle: HTMLElement;
|
||||
|
||||
constructor(protected className: string, public fill: T) {
|
||||
this.container = document.createElement('div');
|
||||
this.container.className = className;
|
||||
|
||||
this.border = document.createElement('div');
|
||||
this.border.classList.add(className + '-border');
|
||||
|
||||
this.content = document.createElement('div');
|
||||
this.content.classList.add(className + '-content');
|
||||
|
||||
this.title = document.createElement('div');
|
||||
this.title.classList.add(className + '-title');
|
||||
|
||||
this.subtitle = document.createElement('div');
|
||||
this.subtitle.classList.add(className + '-subtitle');
|
||||
|
||||
this.content.append(this.title, this.subtitle);
|
||||
this.container.append(this.border, this.content);
|
||||
}
|
||||
}
|
@ -104,17 +104,22 @@ export class ScrollableBase {
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.scrollLocked) clearTimeout(this.scrollLocked);
|
||||
else {
|
||||
this.scrollLockedPromise = deferredPromise<void>();
|
||||
}
|
||||
|
||||
this.scrollLocked = window.setTimeout(() => {
|
||||
this.scrollLocked = 0;
|
||||
const wasLocked = !!this.scrollLocked;
|
||||
if(wasLocked) clearTimeout(this.scrollLocked);
|
||||
if(smooth) {
|
||||
if(!wasLocked) {
|
||||
this.scrollLockedPromise = deferredPromise<void>();
|
||||
}
|
||||
|
||||
this.scrollLocked = window.setTimeout(() => {
|
||||
this.scrollLocked = 0;
|
||||
this.scrollLockedPromise.resolve();
|
||||
//this.onScroll();
|
||||
this.container.dispatchEvent(new CustomEvent('scroll'));
|
||||
}, scrollTime);
|
||||
} else if(wasLocked) {
|
||||
this.scrollLockedPromise.resolve();
|
||||
//this.onScroll();
|
||||
this.container.dispatchEvent(new CustomEvent('scroll'));
|
||||
}, scrollTime);
|
||||
}
|
||||
|
||||
const options: SmoothScrollToOptions = {
|
||||
behavior: smooth ? 'smooth' : 'auto',
|
||||
@ -124,6 +129,10 @@ export class ScrollableBase {
|
||||
options[side] = value;
|
||||
|
||||
this.container.scrollTo(options as any);
|
||||
|
||||
if(!smooth) {
|
||||
this.container.dispatchEvent(new CustomEvent('scroll'));
|
||||
}
|
||||
}
|
||||
|
||||
get length() {
|
||||
@ -490,6 +499,10 @@ export default class Scrollable extends ScrollableBase {
|
||||
return this.scrollTop;
|
||||
};
|
||||
|
||||
get isScrolledDown() {
|
||||
return this.scrollHeight - Math.round(this.scrollTop + this.container.offsetHeight) <= 1;
|
||||
}
|
||||
|
||||
set scrollTop(y: number) {
|
||||
this.container.scrollTop = y;
|
||||
}
|
||||
|
@ -1,26 +1,26 @@
|
||||
import appPhotosManager, {MyPhoto} from '../lib/appManagers/appPhotosManager';
|
||||
import LottieLoader from '../lib/lottieLoader';
|
||||
import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager";
|
||||
import { formatBytes, getEmojiToneIndex, isInDOM } from "../lib/utils";
|
||||
import ProgressivePreloader from './preloader';
|
||||
import LazyLoadQueue from './lazyLoadQueue';
|
||||
import VideoPlayer from '../lib/mediaPlayer';
|
||||
import { RichTextProcessor } from '../lib/richtextprocessor';
|
||||
import { renderImageFromUrl } from './misc';
|
||||
import appMessagesManager from '../lib/appManagers/appMessagesManager';
|
||||
import { Layouter, RectPart } from './groupedLayout';
|
||||
import PollElement from './poll';
|
||||
import animationIntersector from './animationIntersector';
|
||||
import AudioElement from './audio';
|
||||
import { DownloadBlob } from '../lib/appManagers/appDownloadManager';
|
||||
import webpWorkerController from '../lib/webp/webpWorkerController';
|
||||
import { readBlobAsText } from '../helpers/blob';
|
||||
import appMediaPlaybackController from './appMediaPlaybackController';
|
||||
import { PhotoSize } from '../layer';
|
||||
import { deferredPromise } from '../helpers/cancellablePromise';
|
||||
import { months } from '../helpers/date';
|
||||
import mediaSizes from '../helpers/mediaSizes';
|
||||
import { isSafari } from '../helpers/userAgent';
|
||||
import { months } from '../helpers/date';
|
||||
import { PhotoSize } from '../layer';
|
||||
import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager";
|
||||
import { DownloadBlob } from '../lib/appManagers/appDownloadManager';
|
||||
import appMessagesManager from '../lib/appManagers/appMessagesManager';
|
||||
import appPhotosManager, { MyPhoto } from '../lib/appManagers/appPhotosManager';
|
||||
import LottieLoader from '../lib/lottieLoader';
|
||||
import VideoPlayer from '../lib/mediaPlayer';
|
||||
import { formatBytes, getEmojiToneIndex, isInDOM } from "../lib/utils";
|
||||
import webpWorkerController from '../lib/webp/webpWorkerController';
|
||||
import animationIntersector from './animationIntersector';
|
||||
import appMediaPlaybackController from './appMediaPlaybackController';
|
||||
import AudioElement from './audio';
|
||||
import ReplyContainer from './chat/replyContainer';
|
||||
import { Layouter, RectPart } from './groupedLayout';
|
||||
import LazyLoadQueue from './lazyLoadQueue';
|
||||
import { renderImageFromUrl } from './misc';
|
||||
import PollElement from './poll';
|
||||
import ProgressivePreloader from './preloader';
|
||||
|
||||
export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue, noInfo, group}: {
|
||||
doc: MyDocument,
|
||||
@ -697,68 +697,11 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
|
||||
return lazyLoadQueue && (!doc.downloaded || stickerType == 2) ? (lazyLoadQueue.push({div, load, wasSeen: group == 'chat' && stickerType != 2}), Promise.resolve()) : load();
|
||||
}
|
||||
|
||||
export function wrapReply(title: string, subtitle: string, message?: any, isPinned?: boolean) {
|
||||
const prefix = isPinned ? 'pinned-message' : 'reply';
|
||||
const div = document.createElement('div');
|
||||
div.classList.add(prefix);
|
||||
|
||||
const replyBorder = document.createElement('div');
|
||||
replyBorder.classList.add(prefix + '-border');
|
||||
|
||||
const replyContent = document.createElement('div');
|
||||
replyContent.classList.add(prefix + '-content');
|
||||
|
||||
const replyTitle = document.createElement('div');
|
||||
replyTitle.classList.add(prefix + '-title');
|
||||
|
||||
const replySubtitle = document.createElement('div');
|
||||
replySubtitle.classList.add(prefix + '-subtitle');
|
||||
|
||||
if(title.length > 150) {
|
||||
title = title.substr(0, 140) + '...';
|
||||
}
|
||||
|
||||
if(subtitle.length > 150) {
|
||||
subtitle = subtitle.substr(0, 140) + '...';
|
||||
}
|
||||
|
||||
replyTitle.innerHTML = title ? RichTextProcessor.wrapEmojiText(title) : '';
|
||||
|
||||
const media = message && message.media;
|
||||
if(media) {
|
||||
replySubtitle.innerHTML = message.rReply;
|
||||
|
||||
//console.log('wrap reply', media);
|
||||
|
||||
if(media.photo || (media.document && ['video'].indexOf(media.document.type) !== -1)) {
|
||||
let replyMedia = document.createElement('div');
|
||||
replyMedia.classList.add(prefix + '-media');
|
||||
|
||||
let photo = media.photo || media.document;
|
||||
|
||||
let sizes = photo.sizes || photo.thumbs;
|
||||
if(sizes && sizes[0].bytes) {
|
||||
appPhotosManager.setAttachmentPreview(sizes[0].bytes, replyMedia, false, true);
|
||||
}
|
||||
|
||||
appPhotosManager.preloadPhoto(photo, appPhotosManager.choosePhotoSize(photo, 32, 32))
|
||||
.then(() => {
|
||||
renderImageFromUrl(replyMedia, photo._ == 'photo' ? photo.url : appPhotosManager.getDocumentCachedThumb(photo.id).url);
|
||||
});
|
||||
|
||||
replyContent.append(replyMedia);
|
||||
div.classList.add('is-media');
|
||||
}
|
||||
} else {
|
||||
replySubtitle.innerHTML = subtitle ? RichTextProcessor.wrapEmojiText(subtitle) : '';
|
||||
}
|
||||
|
||||
replyContent.append(replyTitle, replySubtitle);
|
||||
div.append(replyBorder, replyContent);
|
||||
|
||||
export function wrapReply(title: string, subtitle: string, message?: any) {
|
||||
const replyContainer = new ReplyContainer('reply');
|
||||
replyContainer.fill(title, subtitle, message);
|
||||
/////////console.log('wrapReply', title, subtitle, media);
|
||||
|
||||
return div;
|
||||
return replyContainer.container;
|
||||
}
|
||||
|
||||
export function wrapAlbum({groupID, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut}: {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ChatBannedRights, InputChannel, InputChatPhoto, InputPeer, Updates } from "../../layer";
|
||||
import { ChatAdminRights, ChatBannedRights, InputChannel, InputChatPhoto, InputPeer, Updates } from "../../layer";
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import $rootScope from "../rootScope";
|
||||
@ -166,17 +166,19 @@ export class AppChatsManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
let myFlags = (chat.admin_rights || chat.banned_rights || chat.default_banned_rights)?.pFlags ?? {};
|
||||
const rights = chat.admin_rights || chat.banned_rights || chat.default_banned_rights;
|
||||
let myFlags: {[flag in keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags']]: true};
|
||||
if(rights) myFlags = rights.pFlags;
|
||||
|
||||
switch(action) {
|
||||
// good
|
||||
case 'send': {
|
||||
if(flag && myFlags[flag]) {
|
||||
if(flag && myFlags && myFlags[flag]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(chat._ == 'channel') {
|
||||
if((!chat.pFlags.megagroup && !myFlags.post_messages)) {
|
||||
if((!chat.pFlags.megagroup && !myFlags?.post_messages)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -187,7 +189,7 @@ export class AppChatsManager {
|
||||
// good
|
||||
case 'deleteRevoke': {
|
||||
if(chat._ == 'channel') {
|
||||
return !!myFlags.delete_messages;
|
||||
return !!myFlags?.delete_messages;
|
||||
} else if(!chat.pFlags.admin) {
|
||||
return false;
|
||||
}
|
||||
@ -198,9 +200,9 @@ export class AppChatsManager {
|
||||
// good
|
||||
case 'pin': {
|
||||
if(chat._ == 'channel') {
|
||||
return chat.admin_rights ? !!myFlags.pin_messages || !!myFlags.post_messages : !!myFlags.pin_messages;
|
||||
return chat.admin_rights ? !!myFlags.pin_messages || !!myFlags.post_messages : myFlags && !myFlags.pin_messages;
|
||||
} else {
|
||||
if(myFlags.pin_messages && !chat.pFlags.admin) {
|
||||
if(myFlags?.pin_messages && !chat.pFlags.admin) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import BubbleGroups from '../../components/bubbleGroups';
|
||||
import { ChatAudio } from '../../components/chat/audio';
|
||||
import { ChatContextMenu } from '../../components/chat/contextMenu';
|
||||
import { ChatInput } from '../../components/chat/input';
|
||||
import PinnedContainer from '../../components/chat/pinnedContainer';
|
||||
import ReplyContainer from '../../components/chat/replyContainer';
|
||||
import { ChatSearch } from '../../components/chat/search';
|
||||
import { horizontalMenu } from '../../components/horizontalMenu';
|
||||
import LazyLoadQueue from '../../components/lazyLoadQueue';
|
||||
@ -94,7 +96,7 @@ export class AppImManager {
|
||||
public updateStatusInterval = 0;
|
||||
|
||||
public pinnedMsgID = 0;
|
||||
private pinnedMessageContainer: HTMLDivElement = null;
|
||||
private pinnedMessageContainer: PinnedContainer = null;
|
||||
|
||||
public lazyLoadQueue = new LazyLoadQueue();
|
||||
|
||||
@ -165,7 +167,10 @@ export class AppImManager {
|
||||
parseMenuButtonsTo(this.menuButtons, this.columnEl.querySelector('.chat-more-button').firstElementChild.children);
|
||||
|
||||
this.chatAudio = new ChatAudio();
|
||||
this.chatInfo.nextElementSibling.prepend(this.chatAudio.container);
|
||||
this.chatInfo.nextElementSibling.prepend(this.chatAudio.divAndCaption.container);
|
||||
|
||||
this.pinnedMessageContainer = new PinnedContainer('message', new ReplyContainer('pinned-message'));
|
||||
this.btnJoin.parentElement.insertBefore(this.pinnedMessageContainer.divAndCaption.container, this.btnJoin);
|
||||
|
||||
// will call when message is sent (only 1)
|
||||
$rootScope.$on('history_append', (e) => {
|
||||
@ -323,17 +328,20 @@ export class AppImManager {
|
||||
this.renderMessage(message, true, false, bubble, false);
|
||||
});
|
||||
|
||||
$rootScope.$on('peer_pinned_message', (e) => {
|
||||
const peerID = e.detail;
|
||||
|
||||
if(peerID == this.peerID) {
|
||||
(this.messagesQueuePromise || Promise.resolve()).then(() => {
|
||||
this.setPinnedMessage();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$on('messages_downloaded', (e) => {
|
||||
const mids: number[] = e.detail;
|
||||
|
||||
const pinnedMessage = appMessagesManager.getPinnedMessage(this.peerID);
|
||||
mids.forEach(mid => {
|
||||
if(pinnedMessage.mid == mid) {
|
||||
(this.messagesQueuePromise || Promise.resolve()).then(() => {
|
||||
this.setPinnedMessage(pinnedMessage);
|
||||
});
|
||||
}
|
||||
|
||||
/* const promise = (this.scrollable.scrollLocked && this.scrollable.scrollLockedPromise) || Promise.resolve();
|
||||
promise.then(() => {
|
||||
|
||||
@ -747,38 +755,18 @@ export class AppImManager {
|
||||
});
|
||||
};
|
||||
|
||||
public setPinnedMessage(message: any) {
|
||||
public setPinnedMessage() {
|
||||
/////this.log('setting pinned message', message);
|
||||
//return;
|
||||
const height = 52;
|
||||
const scrollTop = this.scrollable.container.scrollTop;
|
||||
const newPinned = wrapReply('Pinned Message', message.message, message, true);
|
||||
newPinned.dataset.mid = '' + message.mid;
|
||||
newPinned.classList.add('pinned-container');
|
||||
|
||||
const close = document.createElement('button');
|
||||
close.classList.add('pinned-message-close', 'btn-icon', 'tgico-close');
|
||||
close.addEventListener('click', (e) => {
|
||||
cancelEvent(e);
|
||||
const scrollTop = this.scrollable.scrollTop;
|
||||
newPinned.remove();
|
||||
this.topbar.classList.remove('is-pinned-shown');
|
||||
|
||||
this.pinnedMessageContainer = null;
|
||||
this.scrollable.scrollTop = scrollTop - height;
|
||||
}, {once: true});
|
||||
newPinned.append(close);
|
||||
|
||||
this.btnJoin.parentElement.insertBefore(newPinned, this.btnJoin);
|
||||
this.topbar.classList.add('is-pinned-shown');
|
||||
|
||||
if(this.pinnedMessageContainer) {
|
||||
this.pinnedMessageContainer.remove();
|
||||
const message = appMessagesManager.getPinnedMessage(this.peerID);
|
||||
if(message && !message.deleted) {
|
||||
this.pinnedMessageContainer.fill('Pinned Message', message.message, message);
|
||||
this.pinnedMessageContainer.toggle(false);
|
||||
this.pinnedMsgID = message.mid;
|
||||
} else if(this.pinnedMsgID) {
|
||||
this.pinnedMsgID = 0;
|
||||
this.pinnedMessageContainer.toggle(true);
|
||||
}
|
||||
|
||||
this.pinnedMessageContainer = newPinned;
|
||||
//this.pinnedMessageContent.innerHTML = message.rReply;
|
||||
this.scrollable.scrollTop = scrollTop + height;
|
||||
}
|
||||
|
||||
public updateStatus() {
|
||||
@ -851,7 +839,7 @@ export class AppImManager {
|
||||
}, 1350);
|
||||
}
|
||||
|
||||
if(this.scroll.scrollHeight - Math.round(this.scroll.scrollTop + this.scroll.offsetHeight) <= 1/* <= 5 */) {
|
||||
if(this.scrollable.isScrolledDown) {
|
||||
this.scroll.parentElement.classList.add('scrolled-down');
|
||||
this.scrolledDown = true;
|
||||
} else if(this.scroll.parentElement.classList.contains('scrolled-down')) {
|
||||
@ -1289,13 +1277,7 @@ export class AppImManager {
|
||||
|
||||
this.menuButtons.mute.style.display = this.myID == this.peerID ? 'none' : '';
|
||||
|
||||
const pinned = appMessagesManager.getPinnedMessage(peerID);
|
||||
if(pinned && !pinned.deleted) {
|
||||
this.setPinnedMessage(pinned);
|
||||
} else if(this.pinnedMessageContainer) {
|
||||
this.pinnedMessageContainer.remove();
|
||||
this.pinnedMessageContainer = null;
|
||||
}
|
||||
this.setPinnedMessage();
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
let title = '';
|
||||
@ -1370,9 +1352,13 @@ export class AppImManager {
|
||||
|
||||
//if(scrolledDown) this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
||||
if(this.messagesQueuePromise && scrolledDown) {
|
||||
this.scrollable.scrollTo(this.scrollable.scrollHeight - 1, 'top', false, true);
|
||||
if(this.scrollable.isScrolledDown && !this.scrollable.scrollLocked) {
|
||||
//this.log('renderNewMessagesByIDs: messagesQueuePromise before will set prev max');
|
||||
this.scrollable.scrollTo(this.scrollable.scrollHeight - 1, 'top', false, true);
|
||||
}
|
||||
|
||||
this.messagesQueuePromise.then(() => {
|
||||
//this.log('messagesQueuePromise after:', this.chatInner.childElementCount, this.scrollable.scrollHeight);
|
||||
//this.log('renderNewMessagesByIDs: messagesQueuePromise after', this.scrollable.isScrolledDown);
|
||||
this.scrollable.scrollTo(this.scrollable.scrollHeight, 'top', true, true);
|
||||
|
||||
/* setTimeout(() => {
|
||||
|
@ -2162,11 +2162,19 @@ export class AppMessagesManager {
|
||||
public savePinnedMessage(peerID: number, mid: number) {
|
||||
if(!mid) {
|
||||
delete this.pinnedMessages[peerID];
|
||||
return;
|
||||
} else {
|
||||
this.pinnedMessages[peerID] = mid;
|
||||
|
||||
if(!this.messagesStorage.hasOwnProperty(mid)) {
|
||||
this.wrapSingleMessage(mid).then(() => {
|
||||
$rootScope.$broadcast('peer_pinned_message', peerID);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.pinnedMessages[peerID] = mid;
|
||||
this.wrapSingleMessage(mid);
|
||||
$rootScope.$broadcast('peer_pinned_message', peerID);
|
||||
}
|
||||
|
||||
public getPinnedMessage(peerID: number) {
|
||||
|
@ -17,13 +17,13 @@
|
||||
// border-bottom: 1px solid #DADCE0;
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
&.is-audio-shown, &.is-pinned-shown:not(.hide-pinned) {
|
||||
&.is-pinned-audio-shown, &.is-pinned-message-shown:not(.hide-pinned) {
|
||||
& + #bubbles {
|
||||
margin-top: 52px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-pinned-shown:not(.hide-pinned):not(.is-audio-shown) {
|
||||
&.is-pinned-message-shown:not(.hide-pinned):not(.is-pinned-audio-shown) {
|
||||
.pinned-message {
|
||||
display: flex;
|
||||
}
|
||||
@ -38,7 +38,7 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.is-pinned-shown:not(.hide-pinned) {
|
||||
&.is-pinned-message-shown:not(.hide-pinned) {
|
||||
.pinned-message {
|
||||
display: flex;
|
||||
}
|
||||
@ -102,18 +102,18 @@
|
||||
}
|
||||
|
||||
@include respond-to(medium-screens) {
|
||||
&.is-pinned-shown {
|
||||
&.is-pinned-message-shown {
|
||||
body.is-right-column-shown & {
|
||||
.chat-info {
|
||||
max-width: calc(100% - var(--right-column-width) * 1.75);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-pinned-shown.is-audio-shown {
|
||||
body.is-right-column-shown & {
|
||||
.chat-info {
|
||||
max-width: calc(100% - var(--right-column-width) * 2.25);
|
||||
&.is-pinned-audio-shown {
|
||||
body.is-right-column-shown & {
|
||||
.chat-info {
|
||||
max-width: calc(100% - var(--right-column-width) * 2.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -792,6 +792,7 @@
|
||||
|
||||
.pinned-container {
|
||||
flex: 0 0 auto;
|
||||
overflow: visible;
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.15);
|
||||
@ -808,21 +809,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
.pinned-message-close, .pinned-audio-close, .pinned-audio-ico {
|
||||
&-close, .pinned-audio-ico {
|
||||
font-size: 1.5rem;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&.tgico-close {
|
||||
visibility: hidden;
|
||||
&-close {
|
||||
visibility: hidden;
|
||||
//left: -3rem;
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
font-size: 1.4rem;
|
||||
right: 9px;
|
||||
visibility: visible;
|
||||
}
|
||||
@include respond-to(handhelds) {
|
||||
font-size: 1.4rem;
|
||||
right: 9px;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user