Refactored links from /# to t.me/
This commit is contained in:
parent
725f5743f2
commit
4d9793efb7
@ -43,7 +43,7 @@ import LazyLoadQueue from "../lazyLoadQueue";
|
|||||||
import ListenerSetter from "../../helpers/listenerSetter";
|
import ListenerSetter from "../../helpers/listenerSetter";
|
||||||
import PollElement from "../poll";
|
import PollElement from "../poll";
|
||||||
import AudioElement from "../audio";
|
import AudioElement from "../audio";
|
||||||
import { Message, MessageEntity, MessageReplyHeader, ReplyMarkup, Update } from "../../layer";
|
import { Message, MessageEntity, MessageReplyHeader, Photo, PhotoSize, ReplyMarkup, Update, WebPage } from "../../layer";
|
||||||
import { REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
import { REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||||
import { FocusDirection } from "../../helpers/fastSmoothScroll";
|
import { FocusDirection } from "../../helpers/fastSmoothScroll";
|
||||||
import useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent, interruptHeavyAnimation } from "../../hooks/useHeavyAnimationCheck";
|
import useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent, interruptHeavyAnimation } from "../../hooks/useHeavyAnimationCheck";
|
||||||
@ -841,11 +841,8 @@ export default class ChatBubbles {
|
|||||||
const message = this.chat.getMessage(bubbleMid) as Message.message;
|
const message = this.chat.getMessage(bubbleMid) as Message.message;
|
||||||
const peerId = this.appPeersManager.getPeerId(message.reply_to.reply_to_peer_id);
|
const peerId = this.appPeersManager.getPeerId(message.reply_to.reply_to_peer_id);
|
||||||
const threadId = message.reply_to.reply_to_top_id;
|
const threadId = message.reply_to.reply_to_top_id;
|
||||||
|
const lastMsgId = message.fwd_from.saved_from_msg_id;
|
||||||
this.appMessagesManager.wrapSingleMessage(peerId, threadId).then(() => {
|
this.chat.appImManager.openThread(peerId, lastMsgId, threadId);
|
||||||
this.appMessagesManager.generateThreadServiceStartMessage(this.appMessagesManager.getMessageByPeer(peerId, threadId));
|
|
||||||
this.chat.appImManager.setInnerPeer(peerId, message.fwd_from.saved_from_msg_id, 'discussion', threadId);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
const message = this.appMessagesManager.filterMessages(this.chat.getMessage(bubbleMid), message => !!(message as Message.message).replies)[0] as Message.message;
|
const message = this.appMessagesManager.filterMessages(this.chat.getMessage(bubbleMid), message => !!(message as Message.message).replies)[0] as Message.message;
|
||||||
const replies = message.replies;
|
const replies = message.replies;
|
||||||
@ -2424,7 +2421,7 @@ export default class ChatBubbles {
|
|||||||
case 'messageMediaWebPage': {
|
case 'messageMediaWebPage': {
|
||||||
processingWebPage = true;
|
processingWebPage = true;
|
||||||
|
|
||||||
let webpage = messageMedia.webpage;
|
let webpage: WebPage.webPage | WebPage.webPageEmpty = messageMedia.webpage;
|
||||||
////////this.log('messageMediaWebPage', webpage);
|
////////this.log('messageMediaWebPage', webpage);
|
||||||
if(webpage._ === 'webPageEmpty') {
|
if(webpage._ === 'webPageEmpty') {
|
||||||
break;
|
break;
|
||||||
@ -2439,7 +2436,8 @@ export default class ChatBubbles {
|
|||||||
quote.classList.add('quote');
|
quote.classList.add('quote');
|
||||||
|
|
||||||
let previewResizer: HTMLDivElement, preview: HTMLDivElement;
|
let previewResizer: HTMLDivElement, preview: HTMLDivElement;
|
||||||
if(webpage.photo || webpage.document) {
|
const photo: Photo.photo = webpage.photo as any;
|
||||||
|
if(photo || webpage.document) {
|
||||||
previewResizer = document.createElement('div');
|
previewResizer = document.createElement('div');
|
||||||
previewResizer.classList.add('preview-resizer');
|
previewResizer.classList.add('preview-resizer');
|
||||||
preview = document.createElement('div');
|
preview = document.createElement('div');
|
||||||
@ -2487,15 +2485,14 @@ export default class ChatBubbles {
|
|||||||
quoteTextDiv.append(previewResizer);
|
quoteTextDiv.append(previewResizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// let t: HTMLElement;
|
let t: HTMLElement;
|
||||||
if(webpage.site_name) {
|
if(webpage.site_name) {
|
||||||
let nameEl = document.createElement('a');
|
const html = RichTextProcessor.wrapRichText(webpage.url);
|
||||||
nameEl.classList.add('webpage-name');
|
const a: HTMLAnchorElement = htmlToDocumentFragment(html).firstElementChild as any;
|
||||||
nameEl.setAttribute('target', '_blank');
|
a.classList.add('webpage-name');
|
||||||
nameEl.href = webpage.url || '#';
|
setInnerHTML(a, RichTextProcessor.wrapEmojiText(webpage.site_name));
|
||||||
setInnerHTML(nameEl, RichTextProcessor.wrapEmojiText(webpage.site_name));
|
quoteTextDiv.append(a);
|
||||||
quoteTextDiv.append(nameEl);
|
t = a;
|
||||||
// t = nameEl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(webpage.rTitle) {
|
if(webpage.rTitle) {
|
||||||
@ -2503,7 +2500,7 @@ export default class ChatBubbles {
|
|||||||
titleDiv.classList.add('title');
|
titleDiv.classList.add('title');
|
||||||
setInnerHTML(titleDiv, webpage.rTitle);
|
setInnerHTML(titleDiv, webpage.rTitle);
|
||||||
quoteTextDiv.append(titleDiv);
|
quoteTextDiv.append(titleDiv);
|
||||||
// t = titleDiv;
|
t = titleDiv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(webpage.rDescription) {
|
if(webpage.rDescription) {
|
||||||
@ -2511,7 +2508,7 @@ export default class ChatBubbles {
|
|||||||
textDiv.classList.add('text');
|
textDiv.classList.add('text');
|
||||||
setInnerHTML(textDiv, webpage.rDescription);
|
setInnerHTML(textDiv, webpage.rDescription);
|
||||||
quoteTextDiv.append(textDiv);
|
quoteTextDiv.append(textDiv);
|
||||||
// t = textDiv;
|
t = textDiv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if(t) {
|
/* if(t) {
|
||||||
@ -2522,15 +2519,15 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
quote.append(quoteTextDiv);
|
quote.append(quoteTextDiv);
|
||||||
|
|
||||||
if(webpage.photo && !doc) {
|
if(photo && !doc) {
|
||||||
bubble.classList.add('photo');
|
bubble.classList.add('photo');
|
||||||
|
|
||||||
const size = webpage.photo.sizes[webpage.photo.sizes.length - 1];
|
const size: PhotoSize.photoSize = photo.sizes[photo.sizes.length - 1] as any;
|
||||||
let isSquare = false;
|
let isSquare = false;
|
||||||
if(size.w === size.h && quoteTextDiv.childElementCount) {
|
if(size.w === size.h && t) {
|
||||||
bubble.classList.add('is-square-photo');
|
bubble.classList.add('is-square-photo');
|
||||||
isSquare = true;
|
isSquare = true;
|
||||||
this.appPhotosManager.setAttachmentSize(webpage.photo, preview, 32, 32, false);
|
this.appPhotosManager.setAttachmentSize(photo, preview, 32, 32, false);
|
||||||
|
|
||||||
/* if(t) {
|
/* if(t) {
|
||||||
t.append(timeSpan);
|
t.append(timeSpan);
|
||||||
@ -2540,7 +2537,7 @@ export default class ChatBubbles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wrapPhoto({
|
wrapPhoto({
|
||||||
photo: webpage.photo,
|
photo,
|
||||||
message,
|
message,
|
||||||
container: preview,
|
container: preview,
|
||||||
boxWidth: isSquare ? 0 : mediaSizes.active.webpage.width,
|
boxWidth: isSquare ? 0 : mediaSizes.active.webpage.width,
|
||||||
|
@ -272,11 +272,11 @@ export class AppImManager {
|
|||||||
this.addAnchorListener<{hashtag: string}>({
|
this.addAnchorListener<{hashtag: string}>({
|
||||||
name: 'searchByHashtag',
|
name: 'searchByHashtag',
|
||||||
callback: (params) => {
|
callback: (params) => {
|
||||||
if(!params) {
|
const {hashtag} = params;
|
||||||
|
if(!hashtag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {hashtag} = params;
|
|
||||||
this.chat.initSearch('#' + hashtag + ' ');
|
this.chat.initSearch('#' + hashtag + ' ');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -316,34 +316,75 @@ export class AppImManager {
|
|||||||
},
|
},
|
||||||
parsePathname: true
|
parsePathname: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.addAnchorListener<{
|
||||||
|
// pathnameParams: ['c', string, string],
|
||||||
|
// uriParams: {thread?: number}
|
||||||
|
// } | {
|
||||||
|
// pathnameParams: [string, string?],
|
||||||
|
// uriParams: {comment?: number}
|
||||||
|
pathnameParams: ['c', string, string] | [string, string?],
|
||||||
|
uriParams: {thread?: number} | {comment?: number}
|
||||||
|
}>({
|
||||||
|
name: 'im',
|
||||||
|
callback: (params) => {
|
||||||
|
console.log(params);
|
||||||
|
|
||||||
|
const {pathnameParams, uriParams} = params;
|
||||||
|
if(pathnameParams[0] === 'c') {
|
||||||
|
const peerId = -+pathnameParams[1];
|
||||||
|
const postId = appMessagesIdsManager.generateMessageId(+pathnameParams[2]);
|
||||||
|
const threadId = 'thread' in uriParams ? appMessagesIdsManager.generateMessageId(+uriParams.thread) : undefined;
|
||||||
|
|
||||||
|
if(threadId) this.openThread(peerId, postId, threadId);
|
||||||
|
else this.setInnerPeer(peerId, postId);
|
||||||
|
} else {
|
||||||
|
const username = pathnameParams[0];
|
||||||
|
const postId = pathnameParams[1] ? appMessagesIdsManager.generateMessageId(+pathnameParams[1]) : undefined;
|
||||||
|
const commentId = 'comment' in uriParams ? appMessagesIdsManager.generateMessageId(uriParams.comment) : undefined;
|
||||||
|
|
||||||
|
this.openUsername(username, postId, undefined, commentId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
parsePathname: true,
|
||||||
|
parseUriParams: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private addAnchorListener<Params extends any>(options: {
|
private addAnchorListener<Params extends any>(options: {
|
||||||
name: 'showMaskedAlert' | 'execBotCommand' | 'searchByHashtag' | 'addstickers' | 'joinchat',
|
name: 'showMaskedAlert' | 'execBotCommand' | 'searchByHashtag' | 'addstickers' | 'joinchat' | 'im',
|
||||||
callback: (params: Params, element: HTMLAnchorElement) => boolean | void,
|
callback: (params: Params, element: HTMLAnchorElement) => boolean | void,
|
||||||
noParams?: boolean,
|
noParams?: boolean,
|
||||||
parsePathname?: boolean
|
parsePathname?: boolean,
|
||||||
|
parseUriParams?: boolean,
|
||||||
}) {
|
}) {
|
||||||
(window as any)[options.name] = (element: HTMLAnchorElement/* , e: Event */) => {
|
(window as any)[options.name] = (element: HTMLAnchorElement/* , e: Event */) => {
|
||||||
cancelEvent(null);
|
cancelEvent(null);
|
||||||
|
|
||||||
const href = element.href;
|
const href = element.href;
|
||||||
let params: any;
|
let pathnameParams: any[];
|
||||||
|
let uriParams: any;
|
||||||
|
|
||||||
if(!options.noParams) {
|
if(!options.noParams) {
|
||||||
params = options.parsePathname ? new URL(element.href).pathname.split('/').slice(1) : this.parseUriParams(href);
|
if(options.parsePathname) pathnameParams = new URL(element.href).pathname.split('/').slice(1);
|
||||||
|
if(options.parseUriParams) uriParams = this.parseUriParams(href);
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = options.callback(params, element);
|
let out: any;
|
||||||
|
if(pathnameParams && uriParams) {
|
||||||
|
out = {pathnameParams, uriParams};
|
||||||
|
} else {
|
||||||
|
out = pathnameParams || uriParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = options.callback(out, element);
|
||||||
return res === undefined ? res : false;
|
return res === undefined ? res : false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseUriParams(uri: string, splitted = uri.split('?')) {
|
private parseUriParams(uri: string, splitted = uri.split('?')) {
|
||||||
if(!splitted[1]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const params: any = {};
|
const params: any = {};
|
||||||
|
if(!splitted[1]) return params;
|
||||||
splitted[1].split('&').forEach(item => {
|
splitted[1].split('&').forEach(item => {
|
||||||
params[item.split('=')[0]] = decodeURIComponent(item.split('=')[1]);
|
params[item.split('=')[0]] = decodeURIComponent(item.split('=')[1]);
|
||||||
});
|
});
|
||||||
@ -382,12 +423,14 @@ export class AppImManager {
|
|||||||
//location.hash = '';
|
//location.hash = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
public openUsername(username: string, msgId?: number) {
|
public openUsername(username: string, msgId?: number, threadId?: number, commentId?: number) {
|
||||||
return appUsersManager.resolveUsername(username).then(peer => {
|
return appUsersManager.resolveUsername(username).then(peer => {
|
||||||
const isUser = peer._ === 'user';
|
const isUser = peer._ === 'user';
|
||||||
const peerId = isUser ? peer.id : -peer.id;
|
const peerId = isUser ? peer.id : -peer.id;
|
||||||
|
|
||||||
return this.setInnerPeer(peerId, msgId);
|
if(threadId) return this.openThread(peerId, msgId, threadId);
|
||||||
|
else if(commentId) return this.openComment(peerId, msgId, commentId);
|
||||||
|
else return this.setInnerPeer(peerId, msgId);
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
if(err.type === 'USERNAME_NOT_OCCUPIED') {
|
if(err.type === 'USERNAME_NOT_OCCUPIED') {
|
||||||
toast(i18n('NoUsernameFound'));
|
toast(i18n('NoUsernameFound'));
|
||||||
@ -395,6 +438,27 @@ export class AppImManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens thread when peerId of discussion group is known
|
||||||
|
*/
|
||||||
|
public openThread(peerId: number, lastMsgId: number, threadId: number) {
|
||||||
|
return appMessagesManager.wrapSingleMessage(peerId, threadId).then(() => {
|
||||||
|
const message = appMessagesManager.getMessageByPeer(peerId, threadId);
|
||||||
|
appMessagesManager.generateThreadServiceStartMessage(message);
|
||||||
|
|
||||||
|
return this.setInnerPeer(peerId, lastMsgId, 'discussion', threadId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens comment directly from original channel
|
||||||
|
*/
|
||||||
|
public openComment(peerId: number, msgId: number, commentId: number) {
|
||||||
|
return appMessagesManager.getDiscussionMessage(peerId, msgId).then(message => {
|
||||||
|
return this.openThread(message.peerId, commentId, message.mid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public setCurrentBackground(broadcastEvent = false) {
|
public setCurrentBackground(broadcastEvent = false) {
|
||||||
const theme = rootScope.getTheme();
|
const theme = rootScope.getTheme();
|
||||||
|
|
||||||
|
@ -597,7 +597,7 @@ namespace RichTextProcessor {
|
|||||||
//inner = encodeEntities(replaceUrlEncodings(entityText));
|
//inner = encodeEntities(replaceUrlEncodings(entityText));
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentContext = url[0] === '#';
|
const currentContext = !!onclick;
|
||||||
if(!onclick && masked && !currentContext) {
|
if(!onclick && masked && !currentContext) {
|
||||||
onclick = 'showMaskedAlert';
|
onclick = 'showMaskedAlert';
|
||||||
}
|
}
|
||||||
@ -644,12 +644,15 @@ namespace RichTextProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'messageEntityMention': {
|
case 'messageEntityMention': {
|
||||||
const contextUrl = !options.noLinks && siteMentions[contextSite];
|
// const contextUrl = !options.noLinks && siteMentions[contextSite];
|
||||||
if(contextUrl) {
|
if(!options.noLinks) {
|
||||||
const entityText = text.substr(entity.offset, entity.length);
|
const entityText = text.substr(entity.offset, entity.length);
|
||||||
const username = entityText.substr(1);
|
const username = entityText.substr(1);
|
||||||
|
|
||||||
insertPart(entity, `<a class="mention" href="${contextUrl.replace('{1}', encodeURIComponent(username))}"${contextExternal ? ' target="_blank" rel="noopener noreferrer"' : ''}>`, '</a>');
|
const {url, onclick} = wrapUrl('t.me/' + username);
|
||||||
|
|
||||||
|
// insertPart(entity, `<a class="mention" href="${contextUrl.replace('{1}', encodeURIComponent(username))}"${contextExternal ? ' target="_blank" rel="noopener noreferrer"' : ''}>`, '</a>');
|
||||||
|
insertPart(entity, `<a class="mention" href="${url}" ${onclick ? `onclick=${onclick}(this)` : ''}>`, '</a>');
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -812,42 +815,10 @@ namespace RichTextProcessor {
|
|||||||
onclick = path[0];
|
onclick = path[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* case 'joinchat':
|
|
||||||
onclick = 'joinchat';
|
|
||||||
url = 'tg://join?invite=' + path[1];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'addstickers':
|
|
||||||
onclick = 'addstickers';
|
|
||||||
url = 'tg://addstickers?set=' + path[1];
|
|
||||||
break; */
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if(path[1] && path[1].match(/^\d+$/)) { // https://t.me/.+/[0-9]+ (channel w/ username)
|
if((path[1] && path[1].match(/^\d+(?:\?(?:comment|thread)=\d+)?$/)) || path.length === 1) {
|
||||||
if(path[0] === 'c' && path[2]) { // https://t.me/c/111111111/111 (channel w/o username)
|
onclick = 'im';
|
||||||
url = '#/im?p=' + path[1] + '&post=' + path[2];
|
break;
|
||||||
} else { // https://t.me/durov/151 (channel w/ username)
|
|
||||||
url = siteMentions['Telegram'].replace('{1}', path[0] + '&post=' + path[1]);
|
|
||||||
}
|
|
||||||
} else if(path.length === 1) {
|
|
||||||
const domainQuery = path[0].split('?');
|
|
||||||
const domain = domainQuery[0];
|
|
||||||
const query = domainQuery[1];
|
|
||||||
|
|
||||||
if(domain === 'iv') {
|
|
||||||
const match = (query || '').match(/url=([^&=]+)/);
|
|
||||||
if(match) {
|
|
||||||
url = match[1];
|
|
||||||
try {
|
|
||||||
url = decodeURIComponent(url);
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
return wrapUrl(url, unsafe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
url = siteMentions['Telegram'].replace('{1}', domain + (query ? '&' + query : ''));
|
|
||||||
//url = 'tg://resolve?domain=' + domain + (query ? '&' + query : '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -860,6 +860,7 @@ $bubble-margin: .25rem;
|
|||||||
.webpage-name {
|
.webpage-name {
|
||||||
font-size: var(--messages-secondary-text-size);
|
font-size: var(--messages-secondary-text-size);
|
||||||
font-weight: 500 !important;
|
font-weight: 500 !important;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
@include hover() {
|
@include hover() {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
Loading…
Reference in New Issue
Block a user