Fix stickers border

Stickers are now uncompress in SW
This commit is contained in:
morethanwords 2020-08-23 15:12:08 +03:00
parent c33748eb5c
commit 99203abe01
11 changed files with 179 additions and 172 deletions

View File

@ -355,34 +355,27 @@ class StickersTab implements EmoticonsTab {
//console.log('got stickerSet', stickerSet, li); //console.log('got stickerSet', stickerSet, li);
if(stickerSet.set.thumb) { if(stickerSet.set.thumb) {
appStickersManager.getStickerSetThumb(stickerSet.set).then((blob) => { const thumbURL = appStickersManager.getStickerSetThumbURL(stickerSet.set);
//console.log('setting thumb', stickerSet, blob);
if(stickerSet.set.pFlags.animated) { // means animated
const reader = new FileReader();
reader.addEventListener('loadend', async(e) => { if(stickerSet.set.pFlags.animated) {
// @ts-ignore fetch(thumbURL)
const text = e.srcElement.result; .then(res => res.json())
let json = await apiManager.gzipUncompress<string>(text, true); .then(json => {
lottieLoader.loadAnimationWorker({
let animation = await lottieLoader.loadAnimationWorker({
container: li, container: li,
loop: true, loop: true,
autoplay: false, autoplay: false,
animationData: JSON.parse(json), animationData: json,
width: 32, width: 32,
height: 32 height: 32
}, EMOTICONSSTICKERGROUP); }, EMOTICONSSTICKERGROUP);
}); });
reader.readAsArrayBuffer(blob);
} else { } else {
let image = new Image(); const image = new Image();
renderImageFromUrl(image, URL.createObjectURL(blob)); renderImageFromUrl(image, thumbURL).then(() => {
li.append(image); li.append(image);
})
} }
});
} else { // as thumb will be used first sticker } else { // as thumb will be used first sticker
wrapSticker({ wrapSticker({
doc: stickerSet.documents[0], doc: stickerSet.documents[0],

View File

@ -165,17 +165,14 @@ let set = (elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLSourceEl
else elem.style.backgroundImage = 'url(' + url + ')'; else elem.style.backgroundImage = 'url(' + url + ')';
}; };
export function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLSourceElement, url: string): Promise<boolean> { export async function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLSourceElement, url: string): Promise<boolean> {
if(loadedURLs[url]) { if(loadedURLs[url]) {
set(elem, url); set(elem, url);
return Promise.resolve(true); } else {
}
if(elem instanceof HTMLSourceElement) { if(elem instanceof HTMLSourceElement) {
elem.src = url; elem.src = url;
return Promise.resolve(false);
} else { } else {
return new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
let loader = new Image(); let loader = new Image();
loader.src = url; loader.src = url;
//let perf = performance.now(); //let perf = performance.now();
@ -190,6 +187,9 @@ export function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGIma
} }
} }
return !!loadedURLs[url];
}
export function putPreloader(elem: Element, returnDiv = false) { export function putPreloader(elem: Element, returnDiv = false) {
const html = ` const html = `
<svg xmlns="http://www.w3.org/2000/svg" class="preloader-circular" viewBox="25 25 50 50"> <svg xmlns="http://www.w3.org/2000/svg" class="preloader-circular" viewBox="25 25 50 50">

View File

@ -1,6 +1,4 @@
import appPhotosManager from '../lib/appManagers/appPhotosManager'; import appPhotosManager from '../lib/appManagers/appPhotosManager';
//import CryptoWorker from '../lib/crypto/cryptoworker';
import apiManager from '../lib/mtproto/mtprotoworker';
import LottieLoader from '../lib/lottieLoader'; import LottieLoader from '../lib/lottieLoader';
import appDocsManager from "../lib/appManagers/appDocsManager"; import appDocsManager from "../lib/appManagers/appDocsManager";
import { formatBytes, getEmojiToneIndex } from "../lib/utils"; import { formatBytes, getEmojiToneIndex } from "../lib/utils";
@ -416,13 +414,18 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
//console.log('wrap sticker', thumb, div); //console.log('wrap sticker', thumb, div);
let img: HTMLImageElement;
const afterRender = () => {
if(!div.childElementCount) {
div.append(img);
}
};
if(thumb.bytes) { if(thumb.bytes) {
let img = new Image(); img = new Image();
if((!isSafari || doc.stickerThumbConverted)/* && false */) { if((!isSafari || doc.stickerThumbConverted)/* && false */) {
renderImageFromUrl(img, appPhotosManager.getPreviewURLFromThumb(thumb, true)); renderImageFromUrl(img, appPhotosManager.getPreviewURLFromThumb(thumb, true)).then(afterRender);
div.append(img);
} else { } else {
webpWorkerController.convert(doc.id, thumb.bytes).then(bytes => { webpWorkerController.convert(doc.id, thumb.bytes).then(bytes => {
if(middleware && !middleware()) return; if(middleware && !middleware()) return;
@ -431,11 +434,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
doc.stickerThumbConverted = true; doc.stickerThumbConverted = true;
if(!div.childElementCount) { if(!div.childElementCount) {
renderImageFromUrl(img, appPhotosManager.getPreviewURLFromThumb(thumb, true)).then(() => { renderImageFromUrl(img, appPhotosManager.getPreviewURLFromThumb(thumb, true)).then(afterRender);
if(!div.childElementCount) {
div.append(img);
}
});
} }
}); });
} }
@ -444,26 +443,24 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
return Promise.resolve(); return Promise.resolve();
} }
} else if(!onlyThumb && stickerType == 2 && withThumb && toneIndex <= 0) { } else if(!onlyThumb && stickerType == 2 && withThumb && toneIndex <= 0) {
let img = new Image(); img = new Image();
let load = () => appDocsManager.downloadDocThumb(doc, thumb.type).then(url => {
const load = () => appDocsManager.downloadDocThumb(doc, thumb.type).then(url => {
if(div.childElementCount || (middleware && !middleware())) return; if(div.childElementCount || (middleware && !middleware())) return;
let promise = renderImageFromUrl(img, url); const promise = renderImageFromUrl(img, url);
if(!downloaded) { //if(!downloaded) {
promise.then(() => { promise.then(afterRender);
if(!div.childElementCount) { //}
div.append(img);
}
});
}
}); });
let downloaded = appDocsManager.hasDownloadedThumb(doc.id, thumb.type); /* let downloaded = appDocsManager.hasDownloadedThumb(doc.id, thumb.type);
if(downloaded) { if(downloaded) {
div.append(img); div.append(img);
} } */
lazyLoadQueue && !downloaded ? lazyLoadQueue.push({div, load, wasSeen: group == 'chat'}) : load(); //lazyLoadQueue && !downloaded ? lazyLoadQueue.push({div, load, wasSeen: group == 'chat'}) : load();
load();
} }
} }
@ -482,33 +479,27 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
} }
let downloaded = doc.downloaded; let downloaded = doc.downloaded;
let load = () => appDocsManager.downloadDocNew(doc.id).promise.then(blob => { let load = async() => {
//console.log('loaded sticker:', doc, div);
if(middleware && !middleware()) return; if(middleware && !middleware()) return;
//return;
if(stickerType == 2) { if(stickerType == 2) {
const reader = new FileReader();
reader.addEventListener('loadend', async(e) => {
//console.time('decompress sticker' + doc.id);
//console.time('render sticker' + doc.id);
// @ts-ignore
const text = e.srcElement.result;
let json = await apiManager.gzipUncompress<string>(text, true);
//console.timeEnd('decompress sticker' + doc.id);
/* if(doc.id == '1860749763008266301') { /* if(doc.id == '1860749763008266301') {
console.log('loaded sticker:', doc, div); console.log('loaded sticker:', doc, div);
} */ } */
//console.time('download sticker' + doc.id);
//appDocsManager.downloadDocNew(doc.id).promise.then(res => res.json()).then(async(json) => {
fetch(doc.url).then(res => res.json()).then(async(json) => {
//console.timeEnd('download sticker' + doc.id);
//console.log('loaded sticker:', doc, div);
if(middleware && !middleware()) return;
let animation = await LottieLoader.loadAnimationWorker/* loadAnimation */({ let animation = await LottieLoader.loadAnimationWorker/* loadAnimation */({
container: div, container: div,
loop: loop && !emoji, loop: loop && !emoji,
autoplay: play, autoplay: play,
animationData: JSON.parse(json), animationData: json,
width, width,
height height
}, group, toneIndex); }, group, toneIndex);
@ -530,11 +521,9 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
} }
}); });
} }
//console.timeEnd('render sticker' + doc.id);
}); });
reader.readAsArrayBuffer(blob); //console.timeEnd('render sticker' + doc.id);
} else if(stickerType == 1) { } else if(stickerType == 1) {
let img = new Image(); let img = new Image();
@ -543,6 +532,8 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
img.style.opacity = '0'; img.style.opacity = '0';
img.addEventListener('load', () => { img.addEventListener('load', () => {
doc.downloaded = true;
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
img.style.opacity = ''; img.style.opacity = '';
}); });
@ -557,7 +548,7 @@ export function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, o
div.append(img); div.append(img);
}); });
} }
}); };
return lazyLoadQueue && (!doc.downloaded || stickerType == 2) ? (lazyLoadQueue.push({div, load, wasSeen: group == 'chat' && stickerType != 2}), Promise.resolve()) : load(); return lazyLoadQueue && (!doc.downloaded || stickerType == 2) ? (lazyLoadQueue.push({div, load, wasSeen: group == 'chat' && stickerType != 2}), Promise.resolve()) : load();
} }

View File

@ -4,7 +4,7 @@ import { isObject, getFileURL } from '../utils';
import opusDecodeController from '../opusDecodeController'; import opusDecodeController from '../opusDecodeController';
import { MTDocument, inputDocumentFileLocation } from '../../types'; import { MTDocument, inputDocumentFileLocation } from '../../types';
import { getFileNameByLocation } from '../bin_utils'; import { getFileNameByLocation } from '../bin_utils';
import appDownloadManager, { Download } from './appDownloadManager'; import appDownloadManager, { Download, ResponseMethod } from './appDownloadManager';
class AppDocsManager { class AppDocsManager {
private docs: {[docID: string]: MTDocument} = {}; private docs: {[docID: string]: MTDocument} = {};
@ -273,7 +273,7 @@ class AppDocsManager {
return this.downloadPromises[doc.id] = deferred; return this.downloadPromises[doc.id] = deferred;
} }
public downloadDocNew(docID: string | MTDocument, toFileEntry?: any): Download { public downloadDocNew(docID: string | MTDocument/* , method: ResponseMethod = 'blob' */): Download {
const doc = this.getDoc(docID); const doc = this.getDoc(docID);
if(doc._ == 'documentEmpty') { if(doc._ == 'documentEmpty') {
@ -287,15 +287,15 @@ class AppDocsManager {
return download; return download;
} }
download = appDownloadManager.download(fileName, doc.url); download = appDownloadManager.download(fileName, doc.url/* , method */);
//const _download: Download = {...download};
//_download.promise = _download.promise.then(async(blob) => { const originalPromise = download.promise;
download.promise = download.promise.then(async(blob) => { originalPromise.then(() => {
if(blob) {
doc.downloaded = true; doc.downloaded = true;
});
if(doc.type == 'voice' && !opusDecodeController.isPlaySupported()) { if(doc.type == 'voice' && !opusDecodeController.isPlaySupported()) {
download.promise = originalPromise.then(async(blob) => {
let reader = new FileReader(); let reader = new FileReader();
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
@ -313,13 +313,13 @@ class AppDocsManager {
reader.readAsArrayBuffer(blob); reader.readAsArrayBuffer(blob);
}); });
}
}
return blob; return blob;
//return originalPromise;
//return new Response(blob);
}); });
}
//return this.downloadPromisesNew[doc.id] = _download;
return download; return download;
} }

View File

@ -1,7 +1,14 @@
import { $rootScope } from "../utils"; import { $rootScope } from "../utils";
import apiManager from "../mtproto/mtprotoworker"; import apiManager from "../mtproto/mtprotoworker";
export type Download = {promise: Promise<Blob>, controller: AbortController}; export type ResponseMethodBlob = 'blob';
export type ResponseMethodJson = 'json';
export type ResponseMethod = ResponseMethodBlob | ResponseMethodJson;
export type DownloadBlob = {promise: Promise<Blob>, controller: AbortController};
export type DownloadJson = {promise: Promise<any>, controller: AbortController};
export type Download = DownloadBlob/* | DownloadJson */;
export type Progress = {done: number, fileName: string, total: number, offset: number}; export type Progress = {done: number, fileName: string, total: number, offset: number};
export type ProgressCallback = (details: Progress) => void; export type ProgressCallback = (details: Progress) => void;
@ -22,12 +29,14 @@ export class AppDownloadManager {
}); });
} }
public download(fileName: string, url: string) { public download(fileName: string, url: string, responseMethod?: ResponseMethodBlob): DownloadBlob;
public download(fileName: string, url: string, responseMethod?: ResponseMethodJson): DownloadJson;
public download(fileName: string, url: string, responseMethod: ResponseMethod = 'blob'): Download {
if(this.downloads.hasOwnProperty(fileName)) return this.downloads[fileName]; if(this.downloads.hasOwnProperty(fileName)) return this.downloads[fileName];
const controller = new AbortController(); const controller = new AbortController();
const promise = fetch(url, {signal: controller.signal}) const promise = fetch(url, {signal: controller.signal})
.then(res => res.blob()) .then(res => res[responseMethod]())
.catch(err => { // Только потому что event.request.signal не работает в SW, либо я кривой? .catch(err => { // Только потому что event.request.signal не работает в SW, либо я кривой?
if(err.name === 'AbortError') { if(err.name === 'AbortError') {
//console.log('Fetch aborted'); //console.log('Fetch aborted');

View File

@ -217,7 +217,7 @@ class AppStickersManager {
}, 100); }, 100);
} }
public getStickerSetThumb(stickerSet: MTStickerSet) { public getStickerSetThumbURL(stickerSet: MTStickerSet) {
const thumb = stickerSet.thumb; const thumb = stickerSet.thumb;
const dcID = stickerSet.thumb_dc_id; const dcID = stickerSet.thumb_dc_id;
@ -231,7 +231,7 @@ class AppStickersManager {
}; };
const url = getFileURL('document', {dcID, location: input, size: thumb.size, mimeType: isAnimated ? "application/x-tgsticker" : 'image/webp'}); const url = getFileURL('document', {dcID, location: input, size: thumb.size, mimeType: isAnimated ? "application/x-tgsticker" : 'image/webp'});
return fetch(url).then(res => res.blob()); return url;
//return promise; //return promise;
} }

View File

@ -134,15 +134,15 @@ export function dataUrlToBlob(url: string) {
return blob; return blob;
} }
export function blobConstruct(blobParts: any, mimeType: string = '') { export function blobConstruct(blobParts: any, mimeType: string = ''): Blob {
var blob; let blob;
var safeMimeType = blobSafeMimeType(mimeType); const safeMimeType = blobSafeMimeType(mimeType);
try { try {
blob = new Blob(blobParts, {type: safeMimeType}); blob = new Blob(blobParts, {type: safeMimeType});
} catch(e) { } catch(e) {
// @ts-ignore // @ts-ignore
var bb = new BlobBuilder; let bb = new BlobBuilder;
blobParts.forEach(function(blobPart: any) { blobParts.forEach((blobPart: any) => {
bb.append(blobPart); bb.append(blobPart);
}); });
blob = bb.getBlob(safeMimeType); blob = bb.getBlob(safeMimeType);
@ -163,6 +163,7 @@ export function blobSafeMimeType(mimeType: string) {
'audio/ogg', 'audio/ogg',
'audio/mpeg', 'audio/mpeg',
'audio/mp4', 'audio/mp4',
'application/json'
].indexOf(mimeType) === -1) { ].indexOf(mimeType) === -1) {
return 'application/octet-stream'; return 'application/octet-stream';
} }

View File

@ -15,12 +15,8 @@ export class FileManager {
return this.blobSupported; return this.blobSupported;
} }
public write(fileWriter: ReturnType<FileManager['getFakeFileWriter']>, bytes: Uint8Array | Blob | {file: any}): Promise<void> { public write(fileWriter: ReturnType<FileManager['getFakeFileWriter']>, bytes: Uint8Array | Blob | string): Promise<void> {
if('file' in bytes) { if(bytes instanceof Blob) { // is file bytes
return bytes.file((file: any) => {
return fileWriter.write(file);
});
} else if(bytes instanceof Blob) { // is file bytes
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let fileReader = new FileReader(); let fileReader = new FileReader();
fileReader.onload = function(event) { fileReader.onload = function(event) {
@ -39,20 +35,20 @@ export class FileManager {
} }
public getFakeFileWriter(mimeType: string, saveFileCallback: (blob: Blob) => Promise<Blob>) { public getFakeFileWriter(mimeType: string, saveFileCallback: (blob: Blob) => Promise<Blob>) {
let blobParts: Array<Uint8Array> = []; const blobParts: Array<Uint8Array | string> = [];
const fakeFileWriter = { const fakeFileWriter = {
write: async(blob: Uint8Array) => { write: async(part: Uint8Array | string) => {
if(!this.blobSupported) { if(!this.blobSupported) {
throw false; throw false;
} }
blobParts.push(blob); blobParts.push(part);
}, },
truncate: () => { truncate: () => {
blobParts = []; blobParts.length = 0;
}, },
finalize: () => { finalize: () => {
const blob = blobConstruct(blobParts, mimeType) as Blob; const blob = blobConstruct(blobParts, mimeType);
if(saveFileCallback) { if(saveFileCallback) {
saveFileCallback(blob); saveFileCallback(blob);
} }

View File

@ -4,9 +4,10 @@ import cacheStorage from "../cacheStorage";
import FileManager from "../filemanager"; import FileManager from "../filemanager";
import apiManager from "./apiManager"; import apiManager from "./apiManager";
import { deferredPromise, CancellablePromise } from "../polyfill"; import { deferredPromise, CancellablePromise } from "../polyfill";
import { logger } from "../logger"; import { logger, LogLevels } from "../logger";
import { InputFileLocation, FileLocation, UploadFile } from "../../types"; import { InputFileLocation, FileLocation, UploadFile } from "../../types";
import { isSafari } from "../../helpers/userAgent"; import { isSafari } from "../../helpers/userAgent";
import cryptoWorker from "../crypto/cryptoworker";
type Delayed = { type Delayed = {
offset: number, offset: number,
@ -43,7 +44,7 @@ export class ApiFileManager {
public webpConvertPromises: {[fileName: string]: CancellablePromise<Uint8Array>} = {}; public webpConvertPromises: {[fileName: string]: CancellablePromise<Uint8Array>} = {};
private log: ReturnType<typeof logger> = logger('AFM'); private log: ReturnType<typeof logger> = logger('AFM', LogLevels.error);
public downloadRequest(dcID: 'upload', cb: () => Promise<void>, activeDelta: number): Promise<void>; public downloadRequest(dcID: 'upload', cb: () => Promise<void>, activeDelta: number): Promise<void>;
public downloadRequest(dcID: number, cb: () => Promise<UploadFile>, activeDelta: number): Promise<UploadFile>; public downloadRequest(dcID: number, cb: () => Promise<UploadFile>, activeDelta: number): Promise<UploadFile>;
@ -144,6 +145,29 @@ export class ApiFileManager {
return bytes * 1024; return bytes * 1024;
} }
uncompressTGS = (bytes: Uint8Array, fileName: string) => {
//this.log('uncompressTGS', bytes, bytes.slice().buffer);
// slice нужен потому что в uint8array - 5053 length, в arraybuffer - 5084
return cryptoWorker.gzipUncompress<string>(bytes.slice().buffer, true);
};
convertWebp = (bytes: Uint8Array, fileName: string) => {
const convertPromise = deferredPromise<Uint8Array>();
(self as any as ServiceWorkerGlobalScope)
.clients
.matchAll({includeUncontrolled: false, type: 'window'})
.then((listeners) => {
if(!listeners.length) {
return;
}
listeners[0].postMessage({type: 'convertWebp', payload: {fileName, bytes}});
});
return this.webpConvertPromises[fileName] = convertPromise;
};
public downloadFile(options: DownloadOptions): CancellablePromise<Blob> { public downloadFile(options: DownloadOptions): CancellablePromise<Blob> {
if(!FileManager.isAvailable()) { if(!FileManager.isAvailable()) {
return Promise.reject({type: 'BROWSER_BLOB_NOT_SUPPORTED'}); return Promise.reject({type: 'BROWSER_BLOB_NOT_SUPPORTED'});
@ -152,18 +176,21 @@ export class ApiFileManager {
let size = options.size ?? 0; let size = options.size ?? 0;
let {dcID, location} = options; let {dcID, location} = options;
let processWebp = false; let process: ApiFileManager['uncompressTGS'] | ApiFileManager['convertWebp'];
if(options.mimeType == 'image/webp' && isSafari) { if(options.mimeType == 'image/webp' && isSafari) {
processWebp = true; process = this.convertWebp;
options.mimeType = 'image/png'; options.mimeType = 'image/png';
} else if(options.mimeType == 'application/x-tgsticker') {
process = this.uncompressTGS;
options.mimeType = 'application/json';
} }
// this.log('Dload file', dcID, location, size)
const fileName = getFileNameByLocation(location); const fileName = getFileNameByLocation(location);
const cachedPromise = this.cachedDownloadPromises[fileName]; const cachedPromise = this.cachedDownloadPromises[fileName];
const fileStorage = this.getFileStorage(); const fileStorage = this.getFileStorage();
//this.log('downloadFile', fileName, fileName.length, location, arguments); //this.log('downloadFile', fileName, size, location, options.mimeType, process);
if(cachedPromise) { if(cachedPromise) {
if(options.processPart) { if(options.processPart) {
@ -266,22 +293,11 @@ export class ApiFileManager {
await options.processPart(bytes, offset, delayed); await options.processPart(bytes, offset, delayed);
} }
if(processWebp) { if(process) {
const convertPromise = deferredPromise<Uint8Array>(); //const perf = performance.now();
const processed = await process(bytes, fileName);
(self as any as ServiceWorkerGlobalScope) //this.log('downloadFile process downloaded time', performance.now() - perf, mimeType, process);
.clients return processed;
.matchAll({includeUncontrolled: false, type: 'window'})
.then((listeners) => {
if(!listeners.length) {
return;
}
listeners[0].postMessage({type: 'convertWebp', payload: {fileName, bytes}});
});
return await (this.webpConvertPromises[fileName] = convertPromise);
//return appWebpManager.convertToPng(bytes);
} }
return bytes; return bytes;
@ -318,12 +334,12 @@ export class ApiFileManager {
superpuper(); superpuper();
} }
////////////////////////////////////////// //done += limit;
done += result.bytes.byteLength;
const processedResult = await processDownloaded(result.bytes, offset); const processedResult = await processDownloaded(result.bytes, offset);
checkCancel(); checkCancel();
//done += limit;
done += processedResult.byteLength;
const isFinal = offset + limit >= size; const isFinal = offset + limit >= size;
//if(!isFinal) { //if(!isFinal) {
////this.log('deferred notify 2:', {done: offset + limit, total: size}, deferred); ////this.log('deferred notify 2:', {done: offset + limit, total: size}, deferred);

View File

@ -11,7 +11,7 @@ import { getFileNameByLocation } from '../bin_utils';
import { logger, LogLevels } from '../logger'; import { logger, LogLevels } from '../logger';
import { isSafari } from '../../helpers/userAgent'; import { isSafari } from '../../helpers/userAgent';
const log = logger('SW'/* , LogLevels.error */); const log = logger('SW', LogLevels.error);
const ctx = self as any as ServiceWorkerGlobalScope; const ctx = self as any as ServiceWorkerGlobalScope;

View File

@ -14,7 +14,7 @@
"sourceMap": true, /* Generates corresponding '.map' file. */ "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */ // "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./dist/", /* Redirect output structure to the directory. */ // "outDir": "./dist/", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ //"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */ // "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */ // "removeComments": true, /* Do not emit comments to output. */
@ -65,8 +65,9 @@
"node_modules", "node_modules",
"public", "public",
"coverage", "coverage",
"./public/*.js",
"./src/lib/crypto/crypto.worker.js", "./src/lib/crypto/crypto.worker.js",
"src/vendor/StackBlur.js", "./src/vendor/StackBlur.js",
"./src/lib/*.js", "./src/lib/*.js",
"./src/*.js", "./src/*.js",
"*.js", "*.js",