Telegram Web K with changes to work inside I2P
https://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
285 lines
10 KiB
285 lines
10 KiB
/* |
|
* https://github.com/morethanwords/tweb |
|
* Copyright (C) 2019-2021 Eduard Kuzmenko |
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE |
|
*/ |
|
|
|
import MEDIA_MIME_TYPES_SUPPORTED from "../../environment/mediaMimeTypesSupport"; |
|
import { CancellablePromise } from "../../helpers/cancellablePromise"; |
|
import { clearBadCharsAndTrim } from "../../helpers/cleanSearchText"; |
|
import { formatFullSentTime } from "../../helpers/date"; |
|
import { simulateClickEvent, attachClickEvent } from "../../helpers/dom/clickEvent"; |
|
import replaceContent from "../../helpers/dom/replaceContent"; |
|
import formatBytes from "../../helpers/formatBytes"; |
|
import { MediaSizeType } from "../../helpers/mediaSizes"; |
|
import noop from "../../helpers/noop"; |
|
import { Message, MessageMedia, WebPage } from "../../layer"; |
|
import { MyDocument } from "../../lib/appManagers/appDocsManager"; |
|
import appDownloadManager, { Progress } from "../../lib/appManagers/appDownloadManager"; |
|
import appImManager from "../../lib/appManagers/appImManager"; |
|
import { AppManagers } from "../../lib/appManagers/managers"; |
|
import getDownloadMediaDetails from "../../lib/appManagers/utils/download/getDownloadMediaDetails"; |
|
import choosePhotoSize from "../../lib/appManagers/utils/photos/choosePhotoSize"; |
|
import { joinElementsWith } from "../../lib/langPack"; |
|
import wrapPlainText from "../../lib/richTextProcessor/wrapPlainText"; |
|
import rootScope from "../../lib/rootScope"; |
|
import type { ThumbCache } from "../../lib/storages/thumbs"; |
|
import { MediaSearchContext } from "../appMediaPlaybackController"; |
|
import AudioElement from "../audio"; |
|
import LazyLoadQueue from "../lazyLoadQueue"; |
|
import { MiddleEllipsisElement } from "../middleEllipsis"; |
|
import ProgressivePreloader from "../preloader"; |
|
import wrapPhoto from './photo'; |
|
import wrapSenderToPeer from "./senderToPeer"; |
|
import wrapSentTime from "./sentTime"; |
|
|
|
rootScope.addEventListener('document_downloading', (docId) => { |
|
const elements = Array.from(document.querySelectorAll(`.document[data-doc-id="${docId}"]`)) as HTMLElement[]; |
|
elements.forEach((element) => { |
|
if(element.querySelector('.preloader-container.manual')) { |
|
simulateClickEvent(element); |
|
} |
|
}); |
|
}); |
|
|
|
export default async function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showSender, searchContext, loadPromises, autoDownloadSize, lazyLoadQueue, sizeType, managers = rootScope.managers, cacheContext}: { |
|
message: Message.message, |
|
withTime?: boolean, |
|
fontWeight?: number, |
|
voiceAsMusic?: boolean, |
|
showSender?: boolean, |
|
searchContext?: MediaSearchContext, |
|
loadPromises?: Promise<any>[], |
|
autoDownloadSize?: number, |
|
lazyLoadQueue?: LazyLoadQueue, |
|
sizeType?: MediaSizeType, |
|
managers?: AppManagers, |
|
cacheContext?: ThumbCache |
|
}): Promise<HTMLElement> { |
|
if(!fontWeight) fontWeight = 500; |
|
if(!sizeType) sizeType = '' as any; |
|
const noAutoDownload = autoDownloadSize === 0; |
|
|
|
const doc = ((message.media as MessageMedia.messageMediaDocument).document || ((message.media as MessageMedia.messageMediaWebPage).webpage as WebPage.webPage).document) as MyDocument; |
|
const uploadFileName = message?.uploadingFileName; |
|
if(doc.type === 'audio' || doc.type === 'voice' || doc.type === 'round') { |
|
const audioElement = new AudioElement(); |
|
audioElement.withTime = withTime; |
|
audioElement.message = message; |
|
audioElement.noAutoDownload = noAutoDownload; |
|
audioElement.lazyLoadQueue = lazyLoadQueue; |
|
audioElement.loadPromises = loadPromises; |
|
|
|
if(voiceAsMusic) audioElement.voiceAsMusic = voiceAsMusic; |
|
if(searchContext) audioElement.searchContext = searchContext; |
|
if(showSender) audioElement.showSender = showSender; |
|
|
|
audioElement.dataset.fontWeight = '' + fontWeight; |
|
audioElement.dataset.sizeType = sizeType; |
|
await audioElement.render(); |
|
return audioElement; |
|
} |
|
|
|
let extSplitted = doc.file_name ? doc.file_name.split('.') : ''; |
|
let ext = ''; |
|
ext = extSplitted.length > 1 && Array.isArray(extSplitted) ? |
|
clearBadCharsAndTrim(extSplitted.pop().split(' ', 1)[0].toLowerCase()) : |
|
'file'; |
|
|
|
let docDiv = document.createElement('div'); |
|
docDiv.classList.add('document', `ext-${ext}`); |
|
docDiv.dataset.docId = '' + doc.id; |
|
|
|
// return docDiv; |
|
|
|
const icoDiv = document.createElement('div'); |
|
icoDiv.classList.add('document-ico'); |
|
|
|
const hadContext = !!cacheContext; |
|
const getCacheContext = () => { |
|
return hadContext ? cacheContext : managers.thumbsStorage.getCacheContext(doc); |
|
}; |
|
|
|
cacheContext = await getCacheContext(); |
|
if((doc.thumbs?.length || (message.pFlags.is_outgoing && cacheContext.url && doc.type === 'photo'))/* && doc.mime_type !== 'image/gif' */) { |
|
docDiv.classList.add('document-with-thumb'); |
|
|
|
let imgs: (HTMLImageElement | HTMLCanvasElement)[] = []; |
|
// ! WARNING, use thumbs for check when thumb will be generated for media |
|
if(message.pFlags.is_outgoing && ['photo', 'video'].includes(doc.type)) { |
|
icoDiv.innerHTML = `<img src="${cacheContext.url}">`; |
|
imgs.push(icoDiv.firstElementChild as HTMLImageElement); |
|
} else { |
|
const perf = performance.now(); |
|
const wrapped = await wrapPhoto({ |
|
photo: doc, |
|
message: null, |
|
container: icoDiv, |
|
boxWidth: 54, |
|
boxHeight: 54, |
|
loadPromises, |
|
withoutPreloader: true, |
|
lazyLoadQueue, |
|
size: choosePhotoSize(doc, 54, 54, true), |
|
managers |
|
}); |
|
// console.log('was wrapping photo', performance.now() - perf); |
|
icoDiv.style.width = icoDiv.style.height = ''; |
|
if(wrapped.images.thumb) imgs.push(wrapped.images.thumb); |
|
if(wrapped.images.full) imgs.push(wrapped.images.full); |
|
} |
|
|
|
imgs.forEach((img) => img.classList.add('document-thumb')); |
|
} else { |
|
icoDiv.innerText = ext; |
|
} |
|
|
|
//let fileName = stringMiddleOverflow(doc.file_name || 'Unknown.file', 26); |
|
let fileName = doc.file_name ? wrapPlainText(doc.file_name) : 'Unknown.file'; |
|
const descriptionEl = document.createElement('div'); |
|
descriptionEl.classList.add('document-description'); |
|
const bytesEl = formatBytes(doc.size); |
|
const descriptionParts: (HTMLElement | string | DocumentFragment)[] = [bytesEl]; |
|
|
|
if(withTime) { |
|
descriptionParts.push(formatFullSentTime(message.date)); |
|
} |
|
|
|
if(showSender) { |
|
descriptionParts.push(await wrapSenderToPeer(message)); |
|
} |
|
|
|
docDiv.innerHTML = ` |
|
${(cacheContext.downloaded && !uploadFileName) || !message.mid ? '' : `<div class="document-download"></div>`} |
|
<div class="document-name"></div> |
|
<div class="document-size"></div> |
|
`; |
|
|
|
const nameDiv = docDiv.querySelector('.document-name') as HTMLElement; |
|
const middleEllipsisEl = new MiddleEllipsisElement(); |
|
middleEllipsisEl.dataset.fontWeight = '' + fontWeight; |
|
middleEllipsisEl.dataset.sizeType = sizeType; |
|
middleEllipsisEl.textContent = fileName; |
|
// setInnerHTML(middleEllipsisEl, fileName); |
|
|
|
nameDiv.append(middleEllipsisEl); |
|
|
|
if(showSender) { |
|
nameDiv.append(wrapSentTime(message)); |
|
} |
|
|
|
const sizeDiv = docDiv.querySelector('.document-size') as HTMLElement; |
|
sizeDiv.append(...joinElementsWith(descriptionParts, ' · ')); |
|
|
|
docDiv.prepend(icoDiv); |
|
|
|
if(!uploadFileName && message.pFlags.is_outgoing && !message.mid) { |
|
return docDiv; |
|
} |
|
|
|
let downloadDiv: HTMLElement, preloader: ProgressivePreloader = null; |
|
const onLoad = () => { |
|
if(downloadDiv) { |
|
downloadDiv.classList.add('downloaded'); |
|
const _downloadDiv = downloadDiv; |
|
setTimeout(() => { |
|
_downloadDiv.remove(); |
|
}, 200); |
|
downloadDiv = null; |
|
} |
|
|
|
if(preloader) { |
|
preloader = null; |
|
} |
|
}; |
|
|
|
const addByteProgress = (promise: CancellablePromise<any>) => { |
|
const sizeContainer = document.createElement('span'); |
|
promise.then(() => { |
|
onLoad(); |
|
sizeContainer.replaceWith(bytesEl); |
|
}, () => { |
|
replaceContent(sizeContainer, bytesEl); |
|
}); |
|
|
|
let d = formatBytes(0); |
|
bytesEl.replaceWith(sizeContainer); |
|
sizeContainer.append(d, ' / ', bytesEl); |
|
promise.addNotifyListener((progress: Progress) => { |
|
const _d = formatBytes(progress.done); |
|
d.replaceWith(_d); |
|
d = _d; |
|
}); |
|
}; |
|
|
|
const load = async(e?: Event) => { |
|
const save = !e || e.isTrusted; |
|
const doc = await managers.appDocsManager.getDoc(docDiv.dataset.docId); |
|
let download: CancellablePromise<any>; |
|
const queueId = appImManager.chat.bubbles ? appImManager.chat.bubbles.lazyLoadQueue.queueId : undefined; |
|
if(!save) { |
|
download = appDownloadManager.downloadMediaVoid({media: doc, queueId}); |
|
} else if(doc.type === 'pdf') { |
|
const canOpenAfter = /* managers.appDocsManager.downloading.has(doc.id) || */!preloader || preloader.detached; |
|
download = appDownloadManager.downloadMediaURL({media: doc, queueId}); |
|
if(canOpenAfter) { |
|
download.then(() => { |
|
setTimeout(async() => { // wait for preloader animation end |
|
const url = (await getCacheContext()).url; |
|
window.open(url); |
|
}, rootScope.settings.animationsEnabled ? 250 : 0); |
|
}); |
|
} |
|
} else if(MEDIA_MIME_TYPES_SUPPORTED.has(doc.mime_type) && doc.thumbs?.length) { |
|
download = appDownloadManager.downloadMediaURL({media: doc, queueId}); |
|
} else { |
|
download = appDownloadManager.downloadToDisc({media: doc, queueId}); |
|
} |
|
|
|
if(downloadDiv) { |
|
preloader.attach(downloadDiv, true, download); |
|
addByteProgress(download); |
|
} |
|
}; |
|
|
|
const {fileName: downloadFileName} = getDownloadMediaDetails({media: doc}); |
|
if(await managers.apiFileManager.isDownloading(downloadFileName)) { |
|
downloadDiv = docDiv.querySelector('.document-download'); |
|
const promise = appDownloadManager.downloadMediaVoid({media: doc}); |
|
|
|
preloader = new ProgressivePreloader(); |
|
preloader.attach(downloadDiv, false, promise); |
|
preloader.setDownloadFunction(load); |
|
} else if(!cacheContext.downloaded || uploadFileName) { |
|
downloadDiv = docDiv.querySelector('.document-download'); |
|
preloader = new ProgressivePreloader({ |
|
isUpload: !!uploadFileName |
|
}); |
|
|
|
if(!uploadFileName) { |
|
preloader.construct(); |
|
preloader.setManual(); |
|
preloader.attach(downloadDiv); |
|
preloader.setDownloadFunction(load); |
|
|
|
if(autoDownloadSize !== undefined && autoDownloadSize >= doc.size) { |
|
simulateClickEvent(preloader.preloader); |
|
} |
|
} else { |
|
const uploadPromise = appDownloadManager.getUpload(uploadFileName); |
|
preloader.attachPromise(uploadPromise); |
|
preloader.attach(downloadDiv); |
|
addByteProgress(uploadPromise); |
|
} |
|
} |
|
|
|
attachClickEvent(docDiv, (e) => { |
|
if(preloader) { |
|
preloader.onClick(e); |
|
} else { |
|
load(e); |
|
} |
|
}); |
|
|
|
return docDiv; |
|
}
|
|
|