Fixed Firefox private mode

canary
WolverinDEV 2020-12-05 16:19:37 +01:00
parent 28ecc39853
commit 4823ed4f76
6 changed files with 95 additions and 64 deletions

View File

@ -1,4 +1,7 @@
# Changelog:
* **05.12.20**
- Fixed the webclient for Firefox in incognito mode
* **04.12.20**
- Properly logging channel creations, deletions, shows and hides
- Fixed missing collapsed arrow update after channel move

View File

@ -70,7 +70,6 @@ class RetryTimeCalculator {
this.retryCount++;
const time = this.currentTime;
this.currentTime = Math.min(this.currentTime + this.increment, this.maxTime);
console.error(time + " - " + this.retryCount);
return time;
}

View File

@ -1,4 +1,5 @@
import {tr} from "../i18n/localize";
import {LogCategory, logDebug} from "tc-shared/log";
export enum ImageType {
UNKNOWN,
@ -56,51 +57,84 @@ export function responseImageType(encoded_data: string | ArrayBuffer, base64_enc
return ImageType.UNKNOWN;
}
export type ImageCacheState = {
state: "loaded",
instance: Cache
} | {
state: "errored",
reason: string
} | {
state: "unloaded"
}
export class ImageCache {
readonly cache_name: string;
readonly cacheName: string;
private _cache_category: Cache;
private state: ImageCacheState;
constructor(name: string) {
this.cache_name = name;
private constructor(name: string) {
this.cacheName = name;
this.state = { state: "unloaded" };
}
setupped() : boolean { return !!this._cache_category; }
public static async load(cacheName: string) : Promise<ImageCache> {
const cache = new ImageCache(cacheName);
async reset() {
if(!window.caches)
return cache;
}
private async initialize() {
if(!window.caches) {
this.state = { "state": "errored", reason: tr("Caches are not enabled by the user") };
return;
}
try {
await caches.delete(this.cache_name);
const instance = await window.caches.open(this.cacheName);
this.state = { state: "loaded", instance: instance };
} catch (error) {
logDebug(LogCategory.GENERAL, tr("Failed to open image cache %s: %o"), this.cacheName, error);
this.state = { "state": "errored", reason: tr("Failed to open the cache") };
}
}
private getCacheInstance() : Cache | undefined {
return this.state.state === "loaded" ? this.state.instance : undefined;
}
isPersistent() {
return this.state.state === "loaded";
}
async reset() {
if(!window.caches) {
/* Caches are disabled by the user */
return;
}
try {
await caches.delete(this.cacheName);
} catch(error) {
throw "Failed to delete cache: " + error;
}
try {
await this.setup();
await this.initialize();
} catch(error) {
throw "Failed to reinitialize cache!";
}
}
async setup() {
if(!window.caches)
throw "Missing caches!";
if(this._cache_category)
return;
this._cache_category = await caches.open(this.cache_name);
}
async cleanup(maxAge: number) {
/* FIXME: TODO */
}
async resolveCached(key: string, maxAge?: number) : Promise<Response | undefined> {
maxAge = typeof(maxAge) === "number" ? maxAge : -1;
const cacheInstance = this.getCacheInstance();
if(!cacheInstance) { return undefined; }
const cachedResponse = await this._cache_category.match("https://_local_cache/cache_request_" + key);
maxAge = typeof(maxAge) === "number" ? maxAge : -1;
const cachedResponse = await cacheInstance.match("https://_local_cache/cache_request_" + key);
if(!cachedResponse)
return undefined;
@ -109,6 +143,9 @@ export class ImageCache {
}
async putCache(key: string, value: Response, type?: string, headers?: {[key: string]:string}) {
const cacheInstance = this.getCacheInstance();
if(!cacheInstance) { return; }
const new_headers = new Headers();
for(const key of value.headers.keys())
new_headers.set(key, value.headers.get(key));
@ -117,13 +154,16 @@ export class ImageCache {
for(const key of Object.keys(headers || {}))
new_headers.set(key, headers[key]);
await this._cache_category.put("https://_local_cache/cache_request_" + key, new Response(value.body, {
await cacheInstance.put("https://_local_cache/cache_request_" + key, new Response(value.body, {
headers: new_headers
}));
}
async delete(key: string) {
const flag = await this._cache_category.delete("https://_local_cache/cache_request_" + key, {
const cacheInstance = this.getCacheInstance();
if(!cacheInstance) { return; }
const flag = await cacheInstance.delete("https://_local_cache/cache_request_" + key, {
ignoreVary: true,
ignoreMethod: true,
ignoreSearch: true

View File

@ -42,19 +42,14 @@ class LocalClientAvatar extends ClientAvatar {
}
}
let localAvatarCache: ImageCache;
export class AvatarManager extends AbstractAvatarManager {
private static cache: ImageCache;
readonly handle: FileManager;
private cachedAvatars: {[avatarId: string]: LocalClientAvatar} = {};
constructor(handle: FileManager) {
super();
this.handle = handle;
if(!AvatarManager.cache) {
AvatarManager.cache = new ImageCache("avatars");
}
}
destroy() {
@ -83,11 +78,7 @@ export class AvatarManager extends AbstractAvatarManager {
/* try to lookup our cache for the avatar */
cache_lookup: {
if(!AvatarManager.cache.setupped()) {
await AvatarManager.cache.setup();
}
const response = await AvatarManager.cache.resolveCached('avatar_' + avatar.clientAvatarId); //TODO age!
const response = await localAvatarCache.resolveCached('avatar_' + avatar.clientAvatarId); //TODO age!
if(!response) {
break cache_lookup;
}
@ -96,11 +87,11 @@ export class AvatarManager extends AbstractAvatarManager {
if(avatar.getAvatarHash() !== "unknown") {
if(cachedAvatarHash === undefined) {
log.debug(LogCategory.FILE_TRANSFER, tr("Invalidating cached avatar for %s (Version miss match. Cached: unset, Current: %s)"), avatar.clientAvatarId, avatar.getAvatarHash());
await AvatarManager.cache.delete('avatar_' + avatar.clientAvatarId);
await localAvatarCache.delete('avatar_' + avatar.clientAvatarId);
break cache_lookup;
} else if(cachedAvatarHash !== avatar.getAvatarHash()) {
log.debug(LogCategory.FILE_TRANSFER, tr("Invalidating cached avatar for %s (Version miss match. Cached: %s, Current: %s)"), avatar.clientAvatarId, cachedAvatarHash, avatar.getAvatarHash());
await AvatarManager.cache.delete('avatar_' + avatar.clientAvatarId);
await localAvatarCache.delete('avatar_' + avatar.clientAvatarId);
break cache_lookup;
}
} else if(cachedAvatarHash) {
@ -174,7 +165,7 @@ export class AvatarManager extends AbstractAvatarManager {
return;
}
await AvatarManager.cache.putCache('avatar_' + avatar.clientAvatarId, transferResponse.getResponse().clone(), "image/" + media, {
await localAvatarCache.putCache('avatar_' + avatar.clientAvatarId, transferResponse.getResponse().clone(), "image/" + media, {
"X-avatar-version": avatar.getAvatarHash()
});
@ -231,31 +222,29 @@ export class AvatarManager extends AbstractAvatarManager {
});
}
updateCache(clientAvatarId: string, clientAvatarHash: string) {
AvatarManager.cache.setup().then(async () => {
const cached = this.cachedAvatars[clientAvatarId];
if(cached) {
if(cached.getAvatarHash() === clientAvatarHash)
return;
async updateCache(clientAvatarId: string, clientAvatarHash: string) {
const cached = this.cachedAvatars[clientAvatarId];
if(cached) {
if(cached.getAvatarHash() === clientAvatarHash)
return;
log.info(LogCategory.GENERAL, tr("Deleting cached avatar for client %s. Cached version: %s; New version: %s"), cached.getAvatarHash(), clientAvatarHash);
}
log.info(LogCategory.GENERAL, tr("Deleting cached avatar for client %s. Cached version: %s; New version: %s"), cached.getAvatarHash(), clientAvatarHash);
}
const response = await AvatarManager.cache.resolveCached('avatar_' + clientAvatarId);
if(response) {
let cachedAvatarHash = response.headers.has("X-avatar-version") ? response.headers.get("X-avatar-version") : undefined;
if(cachedAvatarHash !== clientAvatarHash) {
await AvatarManager.cache.delete("avatar_" + clientAvatarId).catch(error => {
log.warn(LogCategory.FILE_TRANSFER, tr("Failed to delete avatar %s: %o"), clientAvatarId, error);
});
}
const response = await localAvatarCache.resolveCached('avatar_' + clientAvatarId);
if(response) {
let cachedAvatarHash = response.headers.has("X-avatar-version") ? response.headers.get("X-avatar-version") : undefined;
if(cachedAvatarHash !== clientAvatarHash) {
await localAvatarCache.delete("avatar_" + clientAvatarId).catch(error => {
log.warn(LogCategory.FILE_TRANSFER, tr("Failed to delete avatar %s: %o"), clientAvatarId, error);
});
}
}
if(cached) {
cached.events.fire("avatar_changed", { newAvatarHash: clientAvatarHash });
this.executeAvatarLoad(cached);
}
});
if(cached) {
cached.events.fire("avatar_changed", { newAvatarHash: clientAvatarHash });
this.executeAvatarLoad(cached);
}
}
resolveAvatar(clientAvatarId: string, avatarHash?: string, cacheOnly?: boolean) : ClientAvatar {
@ -449,6 +438,7 @@ class LocalAvatarManagerFactory extends AbstractAvatarManagerFactory {
loader.register_task(Stage.LOADED, {
name: "Avatar init",
function: async () => {
localAvatarCache = await ImageCache.load("avatars");
setGlobalAvatarManagerFactory(new LocalAvatarManagerFactory());
},
priority: 5

View File

@ -346,9 +346,7 @@ loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
name: "icon init",
priority: 60,
function: async () => {
localIconCache = new ImageCache("icons");
await localIconCache.setup();
localIconCache = await ImageCache.load("icons");
setIconManager(new IconManager());
}
});

View File

@ -65,8 +65,9 @@ export const ServerLogRenderer = (props: { events: Registry<ServerLogUIEvents>,
});
const fixScroll = () => {
if(!refContainer.current)
if(!refContainer.current) {
return;
}
refContainer.current.scrollTop = scrollOffset.current === "bottom" ? refContainer.current.scrollHeight : scrollOffset.current;
};
@ -86,7 +87,7 @@ export const ServerLogRenderer = (props: { events: Registry<ServerLogUIEvents>,
const top = target.scrollTop;
const total = target.scrollHeight - target.clientHeight;
const shouldFollow = top + 50 > total;
const shouldFollow = top + 100 > total;
scrollOffset.current = shouldFollow ? "bottom" : top;
}}>