Media aspecter container
Fix urls Fix merging message entities Decrease sticker size
This commit is contained in:
parent
0e5b5c47d1
commit
1bb0f31026
@ -956,7 +956,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
||||
// TODO: const maxHeight = mediaSizes.isMobile ? appPhotosManager.windowH : appPhotosManager.windowH - 100;
|
||||
const maxHeight = appPhotosManager.windowH - 100;
|
||||
let thumbPromise: Promise<any> = Promise.resolve();
|
||||
const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight, mediaSizes.isMobile ? false : true);
|
||||
const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight, mediaSizes.isMobile ? false : true).photoSize;
|
||||
if(useContainerAsTarget) {
|
||||
const cacheContext = appDownloadManager.getCacheContext(media, size.type);
|
||||
let img: HTMLImageElement;
|
||||
|
@ -859,9 +859,11 @@ export default class ChatBubbles {
|
||||
str += '.attachment video, .attachment img';
|
||||
}
|
||||
|
||||
const hasAspecter = !!this.bubbles[id].querySelector('.media-container-aspecter');
|
||||
let elements = this.bubbles[id].querySelectorAll(str) as NodeListOf<HTMLElement>;
|
||||
const parents: Set<HTMLElement> = new Set();
|
||||
Array.from(elements).forEach((element: HTMLElement) => {
|
||||
if(hasAspecter && !findUpClassName(element, 'media-container-aspecter')) return;
|
||||
let albumItem = findUpClassName(element, 'album-item');
|
||||
const parent = albumItem || element.parentElement;
|
||||
if(parents.has(parent)) return;
|
||||
@ -2330,6 +2332,7 @@ export default class ChatBubbles {
|
||||
if(size.w === size.h && quoteTextDiv.childElementCount) {
|
||||
bubble.classList.add('is-square-photo');
|
||||
isSquare = true;
|
||||
this.appPhotosManager.setAttachmentSize(webpage.photo, preview, 80, 80, false);
|
||||
} else if(size.h > size.w) {
|
||||
bubble.classList.add('is-vertical-photo');
|
||||
}
|
||||
@ -2338,8 +2341,8 @@ export default class ChatBubbles {
|
||||
photo: webpage.photo,
|
||||
message,
|
||||
container: preview,
|
||||
boxWidth: mediaSizes.active.webpage.width,
|
||||
boxHeight: mediaSizes.active.webpage.height,
|
||||
boxWidth: isSquare ? 0 : mediaSizes.active.webpage.width,
|
||||
boxHeight: isSquare ? 0 : mediaSizes.active.webpage.height,
|
||||
isOut,
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
middleware: this.getMiddleware(),
|
||||
@ -2372,8 +2375,9 @@ export default class ChatBubbles {
|
||||
bubble.classList.add('sticker-animated');
|
||||
}
|
||||
|
||||
let size = bubble.classList.contains('emoji-big') ? 140 : 200;
|
||||
this.appPhotosManager.setAttachmentSize(doc, attachmentDiv, size, size);
|
||||
const sizes = mediaSizes.active;
|
||||
const size = bubble.classList.contains('emoji-big') ? sizes.emojiSticker : (doc.animated ? sizes.animatedSticker : sizes.staticSticker);
|
||||
this.appPhotosManager.setAttachmentSize(doc, attachmentDiv, size.width, size.height);
|
||||
//let preloader = new ProgressivePreloader(attachmentDiv, false);
|
||||
bubbleContainer.style.height = attachmentDiv.style.height;
|
||||
bubbleContainer.style.width = attachmentDiv.style.width;
|
||||
|
@ -170,7 +170,11 @@ export default class MarkupTooltip {
|
||||
private applyLink(e: Event) {
|
||||
cancelEvent(e);
|
||||
this.resetSelection();
|
||||
this.appImManager.chat.input.applyMarkdown('link', this.linkInput.value);
|
||||
let url = this.linkInput.value;
|
||||
if(url && !RichTextProcessor.matchUrlProtocol(url)) {
|
||||
url = 'https://' + url;
|
||||
}
|
||||
this.appImManager.chat.input.applyMarkdown('link', url);
|
||||
setTimeout(() => {
|
||||
this.hide();
|
||||
}, 0);
|
||||
|
@ -283,7 +283,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
}
|
||||
|
||||
if(!video.parentElement && container) {
|
||||
container.append(video);
|
||||
(photoRes?.aspecter || container).append(video);
|
||||
}
|
||||
|
||||
const cacheContext = appDownloadManager.getCacheContext(doc);
|
||||
@ -669,7 +669,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
}) {
|
||||
if(!((photo as MyPhoto).sizes || (photo as MyDocument).thumbs)) {
|
||||
if(boxWidth && boxHeight && !size && photo._ === 'document') {
|
||||
size = appPhotosManager.setAttachmentSize(photo, container, boxWidth, boxHeight, undefined, message && message.message);
|
||||
appPhotosManager.setAttachmentSize(photo, container, boxWidth, boxHeight, undefined, message);
|
||||
}
|
||||
|
||||
return {
|
||||
@ -681,7 +681,8 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
thumb: null,
|
||||
full: null
|
||||
},
|
||||
preloader: null
|
||||
preloader: null,
|
||||
aspecter: null
|
||||
};
|
||||
}
|
||||
|
||||
@ -690,7 +691,11 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
if(boxHeight === undefined) boxHeight = mediaSizes.active.regular.height;
|
||||
}
|
||||
|
||||
let loadThumbPromise: Promise<any>;
|
||||
container.classList.add('media-container');
|
||||
let aspecter = container;
|
||||
|
||||
let isFit = true;
|
||||
let loadThumbPromise: Promise<any> = Promise.resolve();
|
||||
let thumbImage: HTMLImageElement;
|
||||
let image: HTMLImageElement;
|
||||
// if(withTail) {
|
||||
@ -699,15 +704,35 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
image = new Image();
|
||||
|
||||
if(boxWidth && boxHeight && !size) { // !album
|
||||
size = appPhotosManager.setAttachmentSize(photo, container, boxWidth, boxHeight, undefined, message && message.message);
|
||||
const set = appPhotosManager.setAttachmentSize(photo, container, boxWidth, boxHeight, undefined, message);
|
||||
size = set.photoSize;
|
||||
isFit = set.isFit;
|
||||
|
||||
if(!isFit) {
|
||||
aspecter = document.createElement('div');
|
||||
aspecter.classList.add('media-container-aspecter');
|
||||
aspecter.style.width = set.size.width + 'px';
|
||||
aspecter.style.height = set.size.height + 'px';
|
||||
|
||||
const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(photo, !noBlur, true);
|
||||
if(gotThumb) {
|
||||
loadThumbPromise = gotThumb.loadPromise;
|
||||
const thumbImage = gotThumb.image; // local scope
|
||||
thumbImage.classList.add('media-photo');
|
||||
container.append(thumbImage);
|
||||
}
|
||||
|
||||
container.classList.add('media-container-fitted');
|
||||
container.append(aspecter);
|
||||
}
|
||||
}
|
||||
|
||||
const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(photo, !noBlur);
|
||||
if(gotThumb) {
|
||||
loadThumbPromise = gotThumb.loadPromise;
|
||||
loadThumbPromise = Promise.all([loadThumbPromise, gotThumb.loadPromise]);
|
||||
thumbImage = gotThumb.image;
|
||||
thumbImage.classList.add('media-photo');
|
||||
container.append(thumbImage);
|
||||
aspecter.append(thumbImage);
|
||||
}
|
||||
// }
|
||||
|
||||
@ -754,7 +779,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
|
||||
renderImageFromUrl(image, cacheContext.url, () => {
|
||||
sequentialDom.mutateElement(container, () => {
|
||||
container.append(image);
|
||||
aspecter.append(image);
|
||||
|
||||
fastRaf(() => {
|
||||
resolve();
|
||||
@ -820,7 +845,8 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
thumb: thumbImage,
|
||||
full: image
|
||||
},
|
||||
preloader
|
||||
preloader,
|
||||
aspecter
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,10 @@ type MediaTypeSizes = {
|
||||
regular: MediaSize,
|
||||
webpage: MediaSize,
|
||||
album: MediaSize,
|
||||
esgSticker: MediaSize
|
||||
esgSticker: MediaSize,
|
||||
animatedSticker: MediaSize,
|
||||
staticSticker: MediaSize,
|
||||
emojiSticker: MediaSize
|
||||
};
|
||||
|
||||
export enum ScreenSize {
|
||||
@ -61,13 +64,19 @@ class MediaSizes extends EventListenerBase<{
|
||||
regular: makeMediaSize(270, 270),
|
||||
webpage: makeMediaSize(270, 200),
|
||||
album: makeMediaSize(270, 0),
|
||||
esgSticker: makeMediaSize(68, 68)
|
||||
esgSticker: makeMediaSize(68, 68),
|
||||
animatedSticker: makeMediaSize(160, 160),
|
||||
staticSticker: makeMediaSize(160, 160),
|
||||
emojiSticker: makeMediaSize(112, 112)
|
||||
},
|
||||
desktop: {
|
||||
regular: makeMediaSize(400, 320),
|
||||
webpage: makeMediaSize(400, 320),
|
||||
album: makeMediaSize(420, 0),
|
||||
esgSticker: makeMediaSize(80, 80)
|
||||
esgSticker: makeMediaSize(80, 80),
|
||||
animatedSticker: makeMediaSize(200, 200),
|
||||
staticSticker: makeMediaSize(200, 200),
|
||||
emojiSticker: makeMediaSize(112, 112)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -216,7 +216,7 @@ export class AppPhotosManager {
|
||||
return {image, loadPromise};
|
||||
}
|
||||
|
||||
public setAttachmentSize(photo: MyPhoto | MyDocument, element: HTMLElement | SVGForeignObjectElement, boxWidth: number, boxHeight: number, noZoom = true, hasText?: boolean) {
|
||||
public setAttachmentSize(photo: MyPhoto | MyDocument, element: HTMLElement | SVGForeignObjectElement, boxWidth: number, boxHeight: number, noZoom = true, message?: any) {
|
||||
const photoSize = this.choosePhotoSize(photo, boxWidth, boxHeight);
|
||||
//console.log('setAttachmentSize', photo, photo.sizes[0].bytes, div);
|
||||
|
||||
@ -227,13 +227,29 @@ export class AppPhotosManager {
|
||||
size = makeMediaSize('w' in photoSize ? photoSize.w : 100, 'h' in photoSize ? photoSize.h : 100);
|
||||
}
|
||||
|
||||
const boxSize = makeMediaSize(boxWidth, boxHeight);
|
||||
let boxSize = makeMediaSize(boxWidth, boxHeight);
|
||||
|
||||
size = size.aspect(boxSize, noZoom);
|
||||
boxSize = size = size.aspect(boxSize, noZoom);
|
||||
|
||||
// /* if(hasText) {
|
||||
// w = Math.max(boxWidth, w);
|
||||
// } */
|
||||
let isFit = true;
|
||||
|
||||
if(photo._ === 'photo' || ['video', 'gif'].includes(photo.type)) {
|
||||
if(boxSize.width < 200 && boxSize.height < 200) { // make at least one side this big
|
||||
boxSize = size = size.aspectCovered(makeMediaSize(200, 200));
|
||||
}
|
||||
|
||||
if(message && (message.message || message.media.webpage || message.replies)) { // make sure that bubble block is human-readable
|
||||
if(boxSize.width < 320) {
|
||||
boxSize = makeMediaSize(320, boxSize.height);
|
||||
isFit = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(isFit && boxSize.width < 120) { // if image is too narrow
|
||||
boxSize = makeMediaSize(120, boxSize.height);
|
||||
isFit = false;
|
||||
}
|
||||
}
|
||||
|
||||
// if(element instanceof SVGForeignObjectElement) {
|
||||
// element.setAttributeNS(null, 'width', '' + w);
|
||||
@ -241,16 +257,16 @@ export class AppPhotosManager {
|
||||
|
||||
// //console.log('set dimensions to svg element:', element, w, h);
|
||||
// } else {
|
||||
element.style.width = size.width + 'px';
|
||||
element.style.height = size.height + 'px';
|
||||
element.style.width = boxSize.width + 'px';
|
||||
element.style.height = boxSize.height + 'px';
|
||||
// }
|
||||
|
||||
return photoSize;
|
||||
return {photoSize, size, isFit};
|
||||
}
|
||||
|
||||
public getStrippedThumbIfNeeded(photo: MyPhoto | MyDocument, useBlur: boolean): ReturnType<AppPhotosManager['getImageFromStrippedThumb']> {
|
||||
public getStrippedThumbIfNeeded(photo: MyPhoto | MyDocument, useBlur: boolean, ignoreCache = false): ReturnType<AppPhotosManager['getImageFromStrippedThumb']> {
|
||||
const cacheContext = appDownloadManager.getCacheContext(photo);
|
||||
if(!cacheContext.downloaded || (photo as MyDocument).type === 'video' || (photo as MyDocument).type === 'gif') {
|
||||
if(!cacheContext.downloaded || (['video', 'gif'] as MyDocument['type'][]).includes((photo as MyDocument).type) || ignoreCache) {
|
||||
if(photo._ === 'document' && cacheContext.downloaded) {
|
||||
return null;
|
||||
}
|
||||
|
@ -54,17 +54,19 @@ const alphaCharsRegExp = 'a-z' +
|
||||
const alphaNumericRegExp = '0-9\_' + alphaCharsRegExp;
|
||||
const domainAddChars = '\u00b7';
|
||||
// Based on Regular Expression for URL validation by Diego Perini
|
||||
const urlRegExp = '((?:https?|ftp)://|mailto:)?' +
|
||||
const urlAlphanumericRegExpPart = '[' + alphaCharsRegExp + '0-9]';
|
||||
const urlProtocolRegExpPart = '((?:https?|ftp)://|mailto:)?';
|
||||
const urlRegExp = urlProtocolRegExpPart +
|
||||
// user:pass authentication
|
||||
'(?:\\S{1,64}(?::\\S{0,64})?@)?' +
|
||||
'(?:' + urlAlphanumericRegExpPart + '{1,64}(?::' + urlAlphanumericRegExpPart + '{0,64})?@)?' +
|
||||
'(?:' +
|
||||
// sindresorhus/ip-regexp
|
||||
'(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])){3}' +
|
||||
'|' +
|
||||
// host name
|
||||
'[' + alphaCharsRegExp + '0-9][' + alphaCharsRegExp + domainAddChars + '0-9\-]{0,64}' +
|
||||
urlAlphanumericRegExpPart + '[' + alphaCharsRegExp + domainAddChars + '0-9\-]{0,64}' +
|
||||
// domain name
|
||||
'(?:\\.[' + alphaCharsRegExp + '0-9][' + alphaCharsRegExp + domainAddChars + '0-9\-]{0,64}){0,10}' +
|
||||
'(?:\\.' + urlAlphanumericRegExpPart + '[' + alphaCharsRegExp + domainAddChars + '0-9\-]{0,64}){0,10}' +
|
||||
// TLD identifier
|
||||
'(?:\\.(xn--[0-9a-z]{2,16}|[' + alphaCharsRegExp + ']{2,24}))' +
|
||||
')' +
|
||||
@ -72,9 +74,11 @@ const urlRegExp = '((?:https?|ftp)://|mailto:)?' +
|
||||
'(?::\\d{2,5})?' +
|
||||
// resource path
|
||||
'(?:/(?:\\S{0,255}[^\\s.;,(\\[\\]{}<>"\'])?)?';
|
||||
const urlProtocolRegExp = new RegExp('^' + urlProtocolRegExpPart.slice(0, -1), 'i');
|
||||
const urlAnyProtocolRegExp = /^((?:.+?):\/\/|mailto:)/;
|
||||
const usernameRegExp = '[a-zA-Z\\d_]{5,32}';
|
||||
const botCommandRegExp = '\\/([a-zA-Z\\d_]{1,32})(?:@(' + usernameRegExp + '))?(\\b|$)';
|
||||
const fullRegExp = new RegExp('(^| )(@)(' + usernameRegExp + ')|(' + urlRegExp + ')|(\\n)|(' + emojiRegExp + ')|(^|[\\s\\(\\]])(#[' + alphaNumericRegExp + ']{2,64})|(^|\\s)' + botCommandRegExp, 'i')
|
||||
const fullRegExp = new RegExp('(^| )(@)(' + usernameRegExp + ')|(' + urlRegExp + ')|(\\n)|(' + emojiRegExp + ')|(^|[\\s\\(\\]])(#[' + alphaNumericRegExp + ']{2,64})|(^|\\s)' + botCommandRegExp, 'i');
|
||||
const emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
//const markdownTestRegExp = /[`_*@~]/;
|
||||
const markdownRegExp = /(^|\s|\n)(````?)([\s\S]+?)(````?)([\s\n\.,:?!;]|$)|(^|\s|\x01)(`|~~|\*\*|__|_-_)([^\n]+?)\7([\x01\s\.,:?!;]|$)|@(\d+)\s*\((.+?)\)|(\[(.+?)\]\((.+?)\))/m;
|
||||
@ -91,7 +95,7 @@ const siteMentions: {[siteName: string]: string} = {
|
||||
Instagram: 'https://instagram.com/{1}/',
|
||||
GitHub: 'https://github.com/{1}'
|
||||
};
|
||||
const markdownEntities: {[markdown: string]: any} = {
|
||||
const markdownEntities: {[markdown: string]: MessageEntity['_']} = {
|
||||
'`': 'messageEntityCode',
|
||||
'``': 'messageEntityPre',
|
||||
'**': 'messageEntityBold',
|
||||
@ -100,6 +104,11 @@ const markdownEntities: {[markdown: string]: any} = {
|
||||
'_-_': 'messageEntityUnderline'
|
||||
};
|
||||
|
||||
const passConflictingEntities: Set<MessageEntity['_']> = new Set();
|
||||
for(let i in markdownEntities) {
|
||||
passConflictingEntities.add(markdownEntities[i]);
|
||||
}
|
||||
|
||||
namespace RichTextProcessor {
|
||||
export const emojiSupported = navigator.userAgent.search(/OS X|iPhone|iPad|iOS/i) !== -1/* && false *//* || true */;
|
||||
|
||||
@ -120,11 +129,11 @@ namespace RichTextProcessor {
|
||||
}
|
||||
|
||||
export function parseEntities(text: string) {
|
||||
var match;
|
||||
var raw = text, url;
|
||||
let match: any;
|
||||
let raw = text;
|
||||
const entities: MessageEntity[] = [];
|
||||
let matchIndex;
|
||||
var rawOffset = 0;
|
||||
let rawOffset = 0;
|
||||
// var start = tsNow()
|
||||
while((match = raw.match(fullRegExp))) {
|
||||
matchIndex = rawOffset + match.index;
|
||||
@ -145,19 +154,19 @@ namespace RichTextProcessor {
|
||||
length: match[4].length
|
||||
});
|
||||
} else {
|
||||
var url: any = false;
|
||||
var protocol = match[5];
|
||||
var tld = match[6];
|
||||
var excluded = '';
|
||||
let url: string;
|
||||
let protocol = match[5];
|
||||
const tld = match[6];
|
||||
// let excluded = '';
|
||||
if(tld) { // URL
|
||||
if(!protocol && (tld.substr(0, 4) === 'xn--' || Config.TLD.indexOf(tld.toLowerCase()) !== -1)) {
|
||||
protocol = 'http://';
|
||||
}
|
||||
|
||||
if(protocol) {
|
||||
var balanced = checkBrackets(match[4]);
|
||||
if (balanced.length !== match[4].length) {
|
||||
excluded = match[4].substring(balanced.length);
|
||||
const balanced = checkBrackets(match[4]);
|
||||
if(balanced.length !== match[4].length) {
|
||||
// excluded = match[4].substring(balanced.length);
|
||||
match[4] = balanced;
|
||||
}
|
||||
|
||||
@ -167,7 +176,7 @@ namespace RichTextProcessor {
|
||||
url = (match[5] ? '' : 'http://') + match[4];
|
||||
}
|
||||
|
||||
if (url) {
|
||||
if(url) {
|
||||
entities.push({
|
||||
_: 'messageEntityUrl',
|
||||
offset: matchIndex,
|
||||
@ -183,7 +192,7 @@ namespace RichTextProcessor {
|
||||
});
|
||||
} else if(match[8]) { // Emoji
|
||||
//console.log('hit', match[8]);
|
||||
let emojiCoords = getEmojiSpritesheetCoords(match[8]);
|
||||
const emojiCoords = getEmojiSpritesheetCoords(match[8]);
|
||||
if(emojiCoords) {
|
||||
entities.push({
|
||||
_: 'messageEntityEmoji',
|
||||
@ -233,7 +242,7 @@ namespace RichTextProcessor {
|
||||
|
||||
const entities: MessageEntity[] = [];
|
||||
let pushedEntity = false;
|
||||
const pushEntity = (entity: MessageEntity) => !findSameEntity(currentEntities, entity) ? (entities.push(entity), pushedEntity = true) : pushedEntity = false;
|
||||
const pushEntity = (entity: MessageEntity) => !findConflictingEntity(currentEntities, entity) ? (entities.push(entity), pushedEntity = true) : pushedEntity = false;
|
||||
|
||||
let raw = text;
|
||||
let match;
|
||||
@ -273,7 +282,7 @@ namespace RichTextProcessor {
|
||||
const isSOH = match[6] === '\x01';
|
||||
|
||||
entity = {
|
||||
_: markdownEntities[match[7]],
|
||||
_: markdownEntities[match[7]] as (MessageEntity.messageEntityBold | MessageEntity.messageEntityCode | MessageEntity.messageEntityItalic)['_'],
|
||||
//offset: matchIndex + match[6].length,
|
||||
offset: matchIndex + (isSOH ? 0 : match[6].length),
|
||||
length: text.length
|
||||
@ -341,17 +350,25 @@ namespace RichTextProcessor {
|
||||
return newText;
|
||||
}
|
||||
|
||||
export function findSameEntity(currentEntities: MessageEntity[], newEntity: MessageEntity) {
|
||||
export function findConflictingEntity(currentEntities: MessageEntity[], newEntity: MessageEntity) {
|
||||
return currentEntities.find(currentEntity => {
|
||||
return newEntity._ === currentEntity._ &&
|
||||
newEntity.offset >= currentEntity.offset &&
|
||||
const isConflictingTypes = newEntity._ === currentEntity._ ||
|
||||
(!passConflictingEntities.has(newEntity._) && !passConflictingEntities.has(currentEntity._));
|
||||
|
||||
if(!isConflictingTypes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isConflictingOffset = newEntity.offset >= currentEntity.offset &&
|
||||
(newEntity.length + newEntity.offset) <= (currentEntity.length + currentEntity.offset);
|
||||
|
||||
return isConflictingOffset;
|
||||
});
|
||||
}
|
||||
|
||||
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[]) {
|
||||
const filtered = newEntities.filter(e => {
|
||||
return !findSameEntity(currentEntities, e);
|
||||
return !findConflictingEntity(currentEntities, e);
|
||||
});
|
||||
|
||||
currentEntities.push(...filtered);
|
||||
@ -536,7 +553,7 @@ namespace RichTextProcessor {
|
||||
if(!(options.noLinks && !passEntities[entity._])) {
|
||||
const entityText = text.substr(entity.offset, entity.length);
|
||||
|
||||
let inner: string;
|
||||
// let inner: string;
|
||||
let url: string;
|
||||
let masked = false;
|
||||
if(entity._ === 'messageEntityTextUrl') {
|
||||
@ -548,6 +565,9 @@ namespace RichTextProcessor {
|
||||
nextEntity.length === entity.length &&
|
||||
nextEntity.offset === entity.offset) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if(url !== entityText) {
|
||||
masked = true;
|
||||
}
|
||||
} else {
|
||||
@ -721,7 +741,7 @@ namespace RichTextProcessor {
|
||||
}
|
||||
|
||||
export function wrapUrl(url: string, unsafe?: number | boolean): string {
|
||||
if(!url.match(/^https?:\/\//i)) {
|
||||
if(!matchUrlProtocol(url)) {
|
||||
url = 'https://' + url;
|
||||
}
|
||||
|
||||
@ -729,7 +749,7 @@ namespace RichTextProcessor {
|
||||
let telescoPeMatch;
|
||||
/* if(unsafe === 2) {
|
||||
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 path = fullPath.split('/');
|
||||
switch(path[0]) {
|
||||
@ -771,7 +791,7 @@ namespace RichTextProcessor {
|
||||
|
||||
break;
|
||||
}
|
||||
} else if((telescoPeMatch = url.match(/^https?:\/\/telesco\.pe\/([^/?]+)\/(\d+)/))) {
|
||||
} else if((telescoPeMatch = url.match(/^(?:https?:\/\/)?telesco\.pe\/([^/?]+)\/(\d+)/))) {
|
||||
url = 'tg://resolve?domain=' + telescoPeMatch[1] + '&post=' + telescoPeMatch[2];
|
||||
}/* else if(unsafe) {
|
||||
url = 'tg://unsafe_url?url=' + encodeURIComponent(url);
|
||||
@ -780,6 +800,10 @@ namespace RichTextProcessor {
|
||||
return url;
|
||||
}
|
||||
|
||||
export function matchUrlProtocol(text: string) {
|
||||
return !text ? null : text.match(urlAnyProtocolRegExp);
|
||||
}
|
||||
|
||||
export function matchUrl(text: string) {
|
||||
return !text ? null : text.match(urlRegExp);
|
||||
}
|
||||
|
@ -604,6 +604,21 @@ $bubble-margin: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.media-container {
|
||||
&-aspecter {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
&-fitted {
|
||||
background-color: transparent !important;
|
||||
|
||||
.thumbnail {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.preloader-container {
|
||||
z-index: 2;
|
||||
}
|
||||
@ -798,11 +813,11 @@ $bubble-margin: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-vertical-photo {
|
||||
/* &.is-vertical-photo {
|
||||
.bubble-content {
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
.reply {
|
||||
padding: 4px;
|
||||
|
Loading…
Reference in New Issue
Block a user