Copy messages/posts link
This commit is contained in:
parent
4e35e481fd
commit
fb434d751b
@ -12,6 +12,7 @@ import PopupForward from "../popups/forward";
|
|||||||
import PopupPinMessage from "../popups/unpinMessage";
|
import PopupPinMessage from "../popups/unpinMessage";
|
||||||
import { copyTextToClipboard } from "../../helpers/clipboard";
|
import { copyTextToClipboard } from "../../helpers/clipboard";
|
||||||
import PopupSendNow from "../popups/sendNow";
|
import PopupSendNow from "../popups/sendNow";
|
||||||
|
import { toast } from "../toast";
|
||||||
|
|
||||||
export default class ChatContextMenu {
|
export default class ChatContextMenu {
|
||||||
private buttons: (ButtonMenuItemOptions & {verify: () => boolean, notDirect?: () => boolean, withSelection?: true})[];
|
private buttons: (ButtonMenuItemOptions & {verify: () => boolean, notDirect?: () => boolean, withSelection?: true})[];
|
||||||
@ -195,6 +196,11 @@ export default class ChatContextMenu {
|
|||||||
verify: () => this.chat.selection.selectedMids.has(this.mid) && !![...this.chat.selection.selectedMids].find(mid => !!this.chat.getMessage(mid).message),
|
verify: () => this.chat.selection.selectedMids.has(this.mid) && !![...this.chat.selection.selectedMids].find(mid => !!this.chat.getMessage(mid).message),
|
||||||
notDirect: () => true,
|
notDirect: () => true,
|
||||||
withSelection: true
|
withSelection: true
|
||||||
|
}, {
|
||||||
|
icon: 'link',
|
||||||
|
text: 'Copy Link',
|
||||||
|
onClick: this.onCopyLinkClick,
|
||||||
|
verify: () => this.appPeersManager.isChannel(this.peerId)
|
||||||
}, {
|
}, {
|
||||||
icon: 'pin',
|
icon: 'pin',
|
||||||
text: 'Pin',
|
text: 'Pin',
|
||||||
@ -300,6 +306,21 @@ export default class ChatContextMenu {
|
|||||||
copyTextToClipboard(str);
|
copyTextToClipboard(str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onCopyLinkClick = () => {
|
||||||
|
const username = this.appPeersManager.getPeerUsername(this.peerId);
|
||||||
|
const msgId = this.appMessagesManager.getServerMessageId(this.mid);
|
||||||
|
let url = 'https://t.me/';
|
||||||
|
if(username) {
|
||||||
|
url += username + '/' + msgId;
|
||||||
|
toast('Link copied to clipboard.');
|
||||||
|
} else {
|
||||||
|
url += 'c/' + Math.abs(this.peerId) + '/' + msgId;
|
||||||
|
toast('This link will only work for chat members.');
|
||||||
|
}
|
||||||
|
|
||||||
|
copyTextToClipboard(url);
|
||||||
|
};
|
||||||
|
|
||||||
private onPinClick = () => {
|
private onPinClick = () => {
|
||||||
new PopupPinMessage(this.peerId, this.mid);
|
new PopupPinMessage(this.peerId, this.mid);
|
||||||
};
|
};
|
||||||
|
@ -90,13 +90,13 @@ export class AppChatsManager {
|
|||||||
|
|
||||||
case 'updateUserTyping':
|
case 'updateUserTyping':
|
||||||
case 'updateChatUserTyping': {
|
case 'updateChatUserTyping': {
|
||||||
if(rootScope.myId == update.user_id) {
|
if(rootScope.myId === update.user_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const peerId = update._ == 'updateUserTyping' ? update.user_id : -update.chat_id;
|
const peerId = update._ === 'updateUserTyping' ? update.user_id : -update.chat_id;
|
||||||
const typings = this.typingsInPeer[peerId] ?? (this.typingsInPeer[peerId] = []);
|
const typings = this.typingsInPeer[peerId] ?? (this.typingsInPeer[peerId] = []);
|
||||||
let typing = typings.find(t => t.userId == update.user_id);
|
let typing = typings.find(t => t.userId === update.user_id);
|
||||||
if(!typing) {
|
if(!typing) {
|
||||||
typing = {
|
typing = {
|
||||||
userId: update.user_id
|
userId: update.user_id
|
||||||
@ -110,7 +110,7 @@ export class AppChatsManager {
|
|||||||
typing.action = update.action;
|
typing.action = update.action;
|
||||||
|
|
||||||
if(!appUsersManager.hasUser(update.user_id)) {
|
if(!appUsersManager.hasUser(update.user_id)) {
|
||||||
if(update._ == 'updateChatUserTyping') {
|
if(update._ === 'updateChatUserTyping') {
|
||||||
if(update.chat_id && appChatsManager.hasChat(update.chat_id) && !appChatsManager.isChannel(update.chat_id)) {
|
if(update.chat_id && appChatsManager.hasChat(update.chat_id) && !appChatsManager.isChannel(update.chat_id)) {
|
||||||
appProfileManager.getChatFull(update.chat_id);
|
appProfileManager.getChatFull(update.chat_id);
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ export class AppChatsManager {
|
|||||||
|
|
||||||
typing.timeout = window.setTimeout(() => {
|
typing.timeout = window.setTimeout(() => {
|
||||||
delete typing.timeout;
|
delete typing.timeout;
|
||||||
typings.findAndSplice(t => t.userId == update.user_id);
|
typings.findAndSplice(t => t.userId === update.user_id);
|
||||||
|
|
||||||
rootScope.broadcast('peer_typings', {peerId, typings});
|
rootScope.broadcast('peer_typings', {peerId, typings});
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ export class AppChatsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(chat._ == 'channel' &&
|
if(chat._ === 'channel' &&
|
||||||
chat.participants_count === undefined &&
|
chat.participants_count === undefined &&
|
||||||
oldChat !== undefined &&
|
oldChat !== undefined &&
|
||||||
oldChat.participants_count) {
|
oldChat.participants_count) {
|
||||||
@ -217,10 +217,10 @@ export class AppChatsManager {
|
|||||||
|
|
||||||
public hasRights(id: number, action: ChatRights, flag?: keyof ChatBannedRights['pFlags']) {
|
public hasRights(id: number, action: ChatRights, flag?: keyof ChatBannedRights['pFlags']) {
|
||||||
const chat = this.getChat(id);
|
const chat = this.getChat(id);
|
||||||
if(chat._ == 'chatEmpty') return false;
|
if(chat._ === 'chatEmpty') return false;
|
||||||
|
|
||||||
if(chat._ == 'chatForbidden' ||
|
if(chat._ === 'chatForbidden' ||
|
||||||
chat._ == 'channelForbidden' ||
|
chat._ === 'channelForbidden' ||
|
||||||
chat.pFlags.kicked ||
|
chat.pFlags.kicked ||
|
||||||
(chat.pFlags.left && !chat.pFlags.megagroup)) {
|
(chat.pFlags.left && !chat.pFlags.megagroup)) {
|
||||||
return false;
|
return false;
|
||||||
@ -241,7 +241,7 @@ export class AppChatsManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(chat._ == 'channel') {
|
if(chat._ === 'channel') {
|
||||||
if((!chat.pFlags.megagroup && !myFlags?.post_messages)) {
|
if((!chat.pFlags.megagroup && !myFlags?.post_messages)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -252,7 +252,7 @@ export class AppChatsManager {
|
|||||||
|
|
||||||
// good
|
// good
|
||||||
case 'deleteRevoke': {
|
case 'deleteRevoke': {
|
||||||
if(chat._ == 'channel') {
|
if(chat._ === 'channel') {
|
||||||
return !!myFlags?.delete_messages;
|
return !!myFlags?.delete_messages;
|
||||||
} else if(!chat.pFlags.admin) {
|
} else if(!chat.pFlags.admin) {
|
||||||
return false;
|
return false;
|
||||||
@ -263,7 +263,7 @@ export class AppChatsManager {
|
|||||||
|
|
||||||
// good
|
// good
|
||||||
case 'pin': {
|
case 'pin': {
|
||||||
if(chat._ == 'channel') {
|
if(chat._ === 'channel') {
|
||||||
return chat.admin_rights ? !!myFlags.pin_messages || !!myFlags.post_messages : myFlags && !myFlags.pin_messages;
|
return chat.admin_rights ? !!myFlags.pin_messages || !!myFlags.post_messages : myFlags && !myFlags.pin_messages;
|
||||||
} else {
|
} else {
|
||||||
if(myFlags?.pin_messages && !chat.pFlags.admin) {
|
if(myFlags?.pin_messages && !chat.pFlags.admin) {
|
||||||
@ -277,9 +277,9 @@ export class AppChatsManager {
|
|||||||
case 'edit_title':
|
case 'edit_title':
|
||||||
case 'edit_photo':
|
case 'edit_photo':
|
||||||
case 'invite': {
|
case 'invite': {
|
||||||
if(chat._ == 'channel') {
|
if(chat._ === 'channel') {
|
||||||
if(chat.pFlags.megagroup) {
|
if(chat.pFlags.megagroup) {
|
||||||
if(!(action == 'invite' && chat.pFlags.democracy)) {
|
if(!(action === 'invite' && chat.pFlags.democracy)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -314,7 +314,7 @@ export class AppChatsManager {
|
|||||||
public isChannel(id: number) {
|
public isChannel(id: number) {
|
||||||
if(id < 0) id = -id;
|
if(id < 0) id = -id;
|
||||||
const chat = this.chats[id];
|
const chat = this.chats[id];
|
||||||
if(chat && (chat._ == 'channel' || chat._ == 'channelForbidden')/* || this.channelAccess[id] */) {
|
if(chat && (chat._ === 'channel' || chat._ === 'channelForbidden')/* || this.channelAccess[id] */) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -326,7 +326,7 @@ export class AppChatsManager {
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
const chat = this.chats[id];
|
const chat = this.chats[id];
|
||||||
if(chat && chat._ == 'channel' && chat.pFlags.megagroup) {
|
if(chat && chat._ === 'channel' && chat.pFlags.megagroup) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -410,7 +410,7 @@ export class AppChatsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(chatFull.participants &&
|
if(chatFull.participants &&
|
||||||
chatFull.participants._ == 'chatParticipants') {
|
chatFull.participants._ === 'chatParticipants') {
|
||||||
chatFull.participants.participants = this.wrapParticipants(id, chatFull.participants.participants);
|
chatFull.participants.participants = this.wrapParticipants(id, chatFull.participants.participants);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,8 +430,8 @@ export class AppChatsManager {
|
|||||||
if(this.isChannel(id)) {
|
if(this.isChannel(id)) {
|
||||||
const isAdmin = chat.pFlags.creator;
|
const isAdmin = chat.pFlags.creator;
|
||||||
participants.forEach((participant) => {
|
participants.forEach((participant) => {
|
||||||
participant.canLeave = myId == participant.user_id;
|
participant.canLeave = myId === participant.user_id;
|
||||||
participant.canKick = isAdmin && participant._ == 'channelParticipant';
|
participant.canKick = isAdmin && participant._ === 'channelParticipant';
|
||||||
|
|
||||||
// just for order by last seen
|
// just for order by last seen
|
||||||
participant.user = appUsersManager.getUser(participant.user_id);
|
participant.user = appUsersManager.getUser(participant.user_id);
|
||||||
@ -439,10 +439,10 @@ export class AppChatsManager {
|
|||||||
} else {
|
} else {
|
||||||
const isAdmin = chat.pFlags.creator || chat.pFlags.admins_enabled && chat.pFlags.admin;
|
const isAdmin = chat.pFlags.creator || chat.pFlags.admins_enabled && chat.pFlags.admin;
|
||||||
participants.forEach((participant) => {
|
participants.forEach((participant) => {
|
||||||
participant.canLeave = myId == participant.user_id;
|
participant.canLeave = myId === participant.user_id;
|
||||||
participant.canKick = !participant.canLeave && (
|
participant.canKick = !participant.canLeave && (
|
||||||
chat.pFlags.creator ||
|
chat.pFlags.creator ||
|
||||||
participant._ == 'chatParticipant' && (isAdmin || myId == participant.inviter_id)
|
participant._ === 'chatParticipant' && (isAdmin || myId === participant.inviter_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
// just for order by last seen
|
// just for order by last seen
|
||||||
@ -541,7 +541,7 @@ export class AppChatsManager {
|
|||||||
|
|
||||||
return participants.reduce((acc: number, participant) => {
|
return participants.reduce((acc: number, participant) => {
|
||||||
const user = appUsersManager.getUser(participant.user_id);
|
const user = appUsersManager.getUser(participant.user_id);
|
||||||
if(user && user.status && user.status._ == 'userStatusOnline') {
|
if(user && user.status && user.status._ === 'userStatusOnline') {
|
||||||
return acc + 1;
|
return acc + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ export class AppImManager {
|
|||||||
switch(p[0]) {
|
switch(p[0]) {
|
||||||
case '@': {
|
case '@': {
|
||||||
appUsersManager.resolveUsername(p).then(peer => {
|
appUsersManager.resolveUsername(p).then(peer => {
|
||||||
const isUser = peer._ == 'user';
|
const isUser = peer._ === 'user';
|
||||||
const peerId = isUser ? peer.id : -peer.id;
|
const peerId = isUser ? peer.id : -peer.id;
|
||||||
|
|
||||||
this.setInnerPeer(peerId, postId);
|
this.setInnerPeer(peerId, postId);
|
||||||
@ -365,7 +365,7 @@ export class AppImManager {
|
|||||||
const drops: ChatDragAndDrop[] = [];
|
const drops: ChatDragAndDrop[] = [];
|
||||||
let mounted = false;
|
let mounted = false;
|
||||||
const toggle = async(e: DragEvent, mount: boolean) => {
|
const toggle = async(e: DragEvent, mount: boolean) => {
|
||||||
if(mount == mounted) return;
|
if(mount === mounted) return;
|
||||||
|
|
||||||
const _types = e.dataTransfer.types;
|
const _types = e.dataTransfer.types;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -489,7 +489,7 @@ export class AppImManager {
|
|||||||
|
|
||||||
getFilesFromEvent(e).then((files: File[]) => {
|
getFilesFromEvent(e).then((files: File[]) => {
|
||||||
if(files.length) {
|
if(files.length) {
|
||||||
if(attachType == 'media' && files.find(file => !['image', 'video'].includes(file.type.split('/')[0]))) {
|
if(attachType === 'media' && files.find(file => !['image', 'video'].includes(file.type.split('/')[0]))) {
|
||||||
attachType = 'document';
|
attachType = 'document';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,7 +704,7 @@ export class AppImManager {
|
|||||||
} else { // user
|
} else { // user
|
||||||
const user = appUsersManager.getUser(peerId);
|
const user = appUsersManager.getUser(peerId);
|
||||||
|
|
||||||
if(rootScope.myId == peerId) {
|
if(rootScope.myId === peerId) {
|
||||||
return '';
|
return '';
|
||||||
} else if(user) {
|
} else if(user) {
|
||||||
subtitle = appUsersManager.getUserStatusString(user.id);
|
subtitle = appUsersManager.getUserStatusString(user.id);
|
||||||
@ -713,7 +713,7 @@ export class AppImManager {
|
|||||||
const typings = appChatsManager.typingsInPeer[peerId];
|
const typings = appChatsManager.typingsInPeer[peerId];
|
||||||
if(typings && typings.length) {
|
if(typings && typings.length) {
|
||||||
return '<span class="online">typing...</span>';
|
return '<span class="online">typing...</span>';
|
||||||
} else if(subtitle == 'online') {
|
} else if(subtitle === 'online') {
|
||||||
return `<span class="online">${subtitle}</span>`;
|
return `<span class="online">${subtitle}</span>`;
|
||||||
} else {
|
} else {
|
||||||
return subtitle;
|
return subtitle;
|
||||||
|
@ -118,7 +118,7 @@ export class AppPeersManager {
|
|||||||
else if(isObject(peerString)) return peerString.user_id ? peerString.user_id : -(peerString.channel_id || peerString.chat_id);
|
else if(isObject(peerString)) return peerString.user_id ? peerString.user_id : -(peerString.channel_id || peerString.chat_id);
|
||||||
else if(!peerString) return 0;
|
else if(!peerString) return 0;
|
||||||
|
|
||||||
const isUser = peerString.charAt(0) == 'u';
|
const isUser = peerString.charAt(0) === 'u';
|
||||||
const peerParams = peerString.substr(1).split('_');
|
const peerParams = peerString.substr(1).split('_');
|
||||||
|
|
||||||
return isUser ? peerParams[0] : -peerParams[0] || 0;
|
return isUser ? peerParams[0] : -peerParams[0] || 0;
|
||||||
@ -238,7 +238,7 @@ export class AppPeersManager {
|
|||||||
} else if(peerId < 0) {
|
} else if(peerId < 0) {
|
||||||
return 'group';
|
return 'group';
|
||||||
} else {
|
} else {
|
||||||
return peerId == rootScope.myId ? 'saved' : 'chat';
|
return peerId === rootScope.myId ? 'saved' : 'chat';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ namespace RichTextProcessor {
|
|||||||
export function getEmojiSpritesheetCoords(emojiCode: string) {
|
export function getEmojiSpritesheetCoords(emojiCode: string) {
|
||||||
let unified = encodeEmoji(emojiCode)/* .replace(/(-fe0f|fe0f)/g, '') */;
|
let unified = encodeEmoji(emojiCode)/* .replace(/(-fe0f|fe0f)/g, '') */;
|
||||||
|
|
||||||
if(unified == '1f441-200d-1f5e8') {
|
if(unified === '1f441-200d-1f5e8') {
|
||||||
unified = '1f441-fe0f-200d-1f5e8-fe0f';
|
unified = '1f441-fe0f-200d-1f5e8-fe0f';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ namespace RichTextProcessor {
|
|||||||
if(text.match(/^`*$/)) {
|
if(text.match(/^`*$/)) {
|
||||||
newText.push(match[0]);
|
newText.push(match[0]);
|
||||||
} else if(match[3]) { // pre
|
} else if(match[3]) { // pre
|
||||||
if(match[5] == '\n') {
|
if(match[5] === '\n') {
|
||||||
match[5] = '';
|
match[5] = '';
|
||||||
rawOffset -= 1;
|
rawOffset -= 1;
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@ namespace RichTextProcessor {
|
|||||||
|
|
||||||
rawOffset -= match[2].length + match[4].length;
|
rawOffset -= match[2].length + match[4].length;
|
||||||
} else if(match[7]) { // code|italic|bold
|
} else if(match[7]) { // code|italic|bold
|
||||||
const isSOH = match[6] == '\x01';
|
const isSOH = match[6] === '\x01';
|
||||||
if(!isSOH) {
|
if(!isSOH) {
|
||||||
newText.push(match[6] + text + match[9]);
|
newText.push(match[6] + text + match[9]);
|
||||||
} else {
|
} else {
|
||||||
@ -311,7 +311,7 @@ namespace RichTextProcessor {
|
|||||||
|
|
||||||
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[]) {
|
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[]) {
|
||||||
currentEntities = currentEntities.slice();
|
currentEntities = currentEntities.slice();
|
||||||
const filtered = newEntities.filter(e => !currentEntities.find(_e => e._ == _e._ && e.offset == _e.offset && e.length == _e.length));
|
const filtered = newEntities.filter(e => !currentEntities.find(_e => e._ === _e._ && e.offset === _e.offset && e.length === _e.length));
|
||||||
currentEntities.push(...filtered);
|
currentEntities.push(...filtered);
|
||||||
currentEntities.sort((a, b) => a.offset - b.offset);
|
currentEntities.sort((a, b) => a.offset - b.offset);
|
||||||
return currentEntities;
|
return currentEntities;
|
||||||
@ -496,7 +496,7 @@ namespace RichTextProcessor {
|
|||||||
|
|
||||||
let inner: string;
|
let inner: string;
|
||||||
let url: string;
|
let url: string;
|
||||||
if(entity._ == 'messageEntityTextUrl') {
|
if(entity._ === 'messageEntityTextUrl') {
|
||||||
url = (entity as MessageEntity.messageEntityTextUrl).url;
|
url = (entity as MessageEntity.messageEntityTextUrl).url;
|
||||||
url = wrapUrl(url, true);
|
url = wrapUrl(url, true);
|
||||||
//inner = wrapRichNestedText(entityText, entity.nested, options);
|
//inner = wrapRichNestedText(entityText, entity.nested, options);
|
||||||
@ -659,7 +659,7 @@ namespace RichTextProcessor {
|
|||||||
export function wrapEmojiText(text: string) {
|
export function wrapEmojiText(text: string) {
|
||||||
if(!text) return '';
|
if(!text) return '';
|
||||||
|
|
||||||
let entities = parseEntities(text).filter(e => e._ == 'messageEntityEmoji');
|
let entities = parseEntities(text).filter(e => e._ === 'messageEntityEmoji');
|
||||||
return wrapRichText(text, {entities});
|
return wrapRichText(text, {entities});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,7 +670,7 @@ namespace RichTextProcessor {
|
|||||||
|
|
||||||
let tgMeMatch;
|
let tgMeMatch;
|
||||||
let telescoPeMatch;
|
let telescoPeMatch;
|
||||||
/* if(unsafe == 2) {
|
/* if(unsafe === 2) {
|
||||||
url = 'tg://unsafe_url?url=' + encodeURIComponent(url);
|
url = 'tg://unsafe_url?url=' + encodeURIComponent(url);
|
||||||
} else */if((tgMeMatch = url.match(/^https?:\/\/t(?:elegram)?\.me\/(.+)/))) {
|
} else */if((tgMeMatch = url.match(/^https?:\/\/t(?:elegram)?\.me\/(.+)/))) {
|
||||||
const fullPath = tgMeMatch[1];
|
const fullPath = tgMeMatch[1];
|
||||||
@ -733,7 +733,7 @@ namespace RichTextProcessor {
|
|||||||
|
|
||||||
const first = [...splitted[0]][0];
|
const first = [...splitted[0]][0];
|
||||||
|
|
||||||
if(onlyFirst || splitted.length == 1) return wrapEmojiText(first);
|
if(onlyFirst || splitted.length === 1) return wrapEmojiText(first);
|
||||||
|
|
||||||
const last = [...splitted[splitted.length - 1]][0];
|
const last = [...splitted[splitted.length - 1]][0];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user