mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 21:45:31 +09:00
perf(desktop): cache display media and retain shown images (#3264)
This commit is contained in:
1 parent
6a24ac3f4e
commit
ee1c861eb2
14 files changed
+172
-18
No files matched your search
@@ -0,0 +1,44 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {LRUCache} from 'lru-cache';
|
||||
|
||||
const RETAINED_IMAGE_BYTE_BUDGET = 192 * 1024 * 1024;
|
||||
const RETAINED_IMAGE_MAX_ENTRIES = 2000;
|
||||
const RETAINED_IMAGE_MIN_BYTES = 1024;
|
||||
const BYTES_PER_PIXEL = 4;
|
||||
const MAX_RETAINED_SOURCE_LENGTH = 16 * 1024;
|
||||
|
||||
const retainedImages = new LRUCache<string, HTMLImageElement>({
|
||||
max: RETAINED_IMAGE_MAX_ENTRIES,
|
||||
maxSize: RETAINED_IMAGE_BYTE_BUDGET,
|
||||
sizeCalculation: (image) => estimateDecodedBytes(image.naturalWidth, image.naturalHeight),
|
||||
});
|
||||
|
||||
function estimateDecodedBytes(width: number, height: number): number {
|
||||
return Math.min(RETAINED_IMAGE_BYTE_BUDGET, Math.max(RETAINED_IMAGE_MIN_BYTES, width * height * BYTES_PER_PIXEL));
|
||||
}
|
||||
|
||||
function isRetainableSource(src: string): boolean {
|
||||
return (
|
||||
src.length > 0 && src.length <= MAX_RETAINED_SOURCE_LENGTH && !src.startsWith('data:') && !src.startsWith('blob:')
|
||||
);
|
||||
}
|
||||
|
||||
export function retainImage(image: HTMLImageElement): void {
|
||||
if (!image.complete || image.naturalWidth <= 0) return;
|
||||
const src = image.currentSrc || image.src;
|
||||
if (!isRetainableSource(src)) return;
|
||||
if (retainedImages.get(src) != null) return;
|
||||
const holder = new Image();
|
||||
holder.decoding = 'async';
|
||||
holder.src = src;
|
||||
retainedImages.set(src, holder, {size: estimateDecodedBytes(image.naturalWidth, image.naturalHeight)});
|
||||
}
|
||||
|
||||
export function installImageRetention(target: Document): () => void {
|
||||
const handleLoad = (event: Event): void => {
|
||||
if (event.target instanceof HTMLImageElement) retainImage(event.target);
|
||||
};
|
||||
target.addEventListener('load', handleLoad, true);
|
||||
return () => target.removeEventListener('load', handleLoad, true);
|
||||
}
|
||||
Reference in new issue
Block a user