This commit is contained in:
[it/its]@Rory& authored and MathMan05 committed 2026-01-02 11:32:31 -06:00
1 parent db64ccefbe
commit 81817dddd5
3 files changed
+140 -126

No files matched your search

+118 -108
View File
@@ -36,6 +36,14 @@ import {Sticker} from "./sticker.js";
import {Hover} from "./hover.js";
import {AccountSwitcher} from "./utils/switcher.js";
import {Favorites} from "./favorites.js";
import {
AnimateTristateValues,
getPreferences,
setPreferences,
ThemeOption,
} from "./utils/storage/userPreferences";
import {getDeveloperSettings, setDeveloperSettings} from "./utils/storage/devSettings";
import {getLocalSettings, ServiceWorkerModeValues} from "./utils/storage/localSettings.js";
type traceObj = {
micros: number;
calls?: (string | traceObj)[];
@@ -289,25 +297,26 @@ class Localuser {
}
async queryBlog() {
this.perminfo.localuser ??= {};
const bstate = localStorage.getItem("blogUpdates") as "Yes" | "No" | "Wait" | null;
if (!bstate) {
localStorage.setItem("blogUpdates", "Wait");
} else if (bstate === "Wait") {
const prefs = await getPreferences();
const bstate = prefs.showBlogUpdates;
if (bstate === undefined) {
const pop = new Dialog("");
pop.options.addText(I18n.blog.wantUpdates());
const opts = pop.options.addOptions("", {ltr: true});
opts.addButtonInput("", I18n.yes(), () => {
localStorage.setItem("blogUpdates", "Yes");
opts.addButtonInput("", I18n.yes(), async () => {
prefs.showBlogUpdates = true;
await setPreferences(prefs);
this.queryBlog();
pop.hide();
});
opts.addButtonInput("", I18n.no(), () => {
localStorage.setItem("blogUpdates", "No");
opts.addButtonInput("", I18n.no(), async () => {
prefs.showBlogUpdates = false;
await setPreferences(prefs);
this.queryBlog();
pop.hide();
});
pop.show();
} else if (bstate === "Yes") {
} else if (bstate) {
const post = (await this.getPosts()).items[0];
if (this.perminfo.localuser.mostRecent !== post.url) {
this.perminfo.localuser.mostRecent = post.url;
@@ -441,7 +450,7 @@ class Localuser {
if (!this.resume_gateway_url || !this.session_id) {
resume = false;
}
const doComp = DecompressionStream && !localStorage.getItem("gateWayComp");
const doComp = DecompressionStream && !getDeveloperSettings().gatewayCompression;
const ws = new WebSocket(
(resume ? this.resume_gateway_url : this.serverurls.gateway.toString()) +
"?encoding=json&v=9" +
@@ -674,7 +683,7 @@ class Localuser {
}
async handleEvent(temp: wsjson) {
if (temp.d._trace) this.handleTrace(temp.d._trace);
if (localStorage.getItem("logGateway")) console.debug(temp);
if (getDeveloperSettings().gatewayLogging) console.debug(temp);
if (temp.s) this.lastSequence = temp.s;
if (temp.op === 9 && this.ws) {
this.errorBackoff = 0;
@@ -2450,31 +2459,34 @@ class Localuser {
}
{
let userinfos = getBulkInfo();
const prefs = await getPreferences();
tas.addColorInput(
I18n.localuser.accentColor(),
(_) => {
userinfos = getBulkInfo();
userinfos.accent_color = _;
localStorage.setItem("userinfos", JSON.stringify(userinfos));
document.documentElement.style.setProperty("--accent-color", userinfos.accent_color);
async (_) => {
prefs.accentColor = _;
await setPreferences(prefs);
document.documentElement.style.setProperty("--accent-color", prefs.accentColor);
},
{initColor: userinfos.accent_color},
{initColor: prefs.accentColor},
);
}
{
const prefs = await getPreferences();
const options = [[null, I18n.noEmojiFont()], ...Localuser.fonts] as const;
const cur = localStorage.getItem("emoji-font");
const cur = prefs.emojiFont;
let index = options.findIndex((_) => _[1] == cur);
if (index === -1) index = 0;
tas.addSelect(
I18n.emojiSelect(),
(index) => {
async (index) => {
if (options[index][0]) {
localStorage.setItem("emoji-font", options[index][1]);
prefs.emojiFont = options[index][1];
} else {
localStorage.removeItem("emoji-font");
prefs.emojiFont = undefined;
}
await setPreferences(prefs);
Localuser.loadFont();
},
options.map((font) => font[1]),
@@ -2483,25 +2495,34 @@ class Localuser {
},
);
}
{
const cur = prefs.renderJoinAvatars;
tas.addCheckboxInput(
I18n.renderJoinAvatars(),
async (v) => {
prefs.renderJoinAvatars = v;
await setPreferences(prefs);
},
{initState: cur},
);
}
}
{
const update = settings.addButton(I18n.localuser.updateSettings());
let index = ["false", "offlineOnly", "true"].indexOf(
localStorage.getItem("SWMode") as string,
);
let index = ServiceWorkerModeValues.indexOf(localSettings.serviceWorkerMode);
if (index === -1) {
index = 2;
}
const sw = update.addSelect(
I18n.localuser.swSettings(),
I18n.settings.updates.serviceWorkerMode.title(),
() => {},
(["SWOff", "SWOffline", "SWOn", "SWUnregistered"] as const).map((e) => I18n.localuser[e]()),
ServiceWorkerModeValues.map((e) => I18n.settings.updates.serviceWorkerMode[e]()),
{
defaultIndex: index,
},
);
sw.onchange = (e) => {
SW.setMode((["false", "offlineOnly", "true", "unregistered"] as const)[e]);
SW.setMode(ServiceWorkerModeValues[e]);
};
update.addButtonInput("", I18n.localuser.CheckUpdate(), async () => {
const update = await SW.checkUpdates();
@@ -2774,16 +2795,12 @@ class Localuser {
this.updateTranslations();
},
[...langmap.values()],
{
defaultIndex: I18n.options().indexOf(I18n.lang),
},
{defaultIndex: I18n.options().indexOf(I18n.lang)},
);
{
security.addButtonInput("", I18n.logout.logout(), async () => {
if (await this.userinfo.logout()) {
window.location.href = "/";
}
if (await this.userinfo.logout()) window.location.href = "/";
});
}
};
@@ -2797,9 +2814,7 @@ class Localuser {
console.log(t);
this.perminfo.user.disableColors = !t;
},
{
initState: !this.perminfo.user.disableColors,
},
{initState: !this.perminfo.user.disableColors},
);
accessibility.addCheckboxInput(
I18n.channel.allowIcons(),
@@ -2807,36 +2822,25 @@ class Localuser {
console.log(t);
this.perminfo.user.disableIcons = !t;
},
{
initState: !this.perminfo.user.disableIcons,
},
{initState: !this.perminfo.user.disableIcons},
);
const gifSettings = ["hover", "always", "never"] as const;
accessibility.addSelect(
I18n.accessibility.playGif(),
(i) => {
localStorage.setItem("gifSetting", gifSettings[i]);
},
gifSettings.map((_) => I18n.accessibility.gifSettings[_]()),
{
defaultIndex:
((gifSettings as readonly string[]).indexOf(
localStorage.getItem("gifSetting") as string,
) + 1 || 1) - 1,
async (i) => {
prefs.animateGifs = AnimateTristateValues[i];
await setPreferences(prefs);
},
AnimateTristateValues.map((_) => I18n.accessibility.gifSettings[_]()),
{defaultIndex: AnimateTristateValues.indexOf(prefs.animateGifs)},
);
accessibility.addSelect(
I18n.accessibility.playIcon(),
(i) => {
localStorage.setItem("iconSetting", gifSettings[i]);
},
gifSettings.map((_) => I18n.accessibility.gifSettings[_]()),
{
defaultIndex:
((gifSettings as readonly string[]).indexOf(
localStorage.getItem("iconSetting") as string,
) + 1 || 1) - 1,
async (i) => {
prefs.animateIcons = AnimateTristateValues[i];
await setPreferences(prefs);
},
AnimateTristateValues.map((_) => I18n.accessibility.gifSettings[_]()),
{defaultIndex: AnimateTristateValues.indexOf(prefs.animateIcons)},
);
}
{
@@ -2909,9 +2913,7 @@ class Localuser {
I18n.localuser["team:"](),
"team_id",
["Personal", ...teams.map((team: {name: string}) => team.name)],
{
defaultIndex: 0,
},
{defaultIndex: 0},
);
});
@@ -3260,14 +3262,11 @@ class Localuser {
const blog = settings.addButton(I18n.blog.blog());
blog.addCheckboxInput(
I18n.blog.blogUpdates(),
(check) => {
if (check) {
localStorage.setItem("blogUpdates", "Yes");
} else {
localStorage.setItem("blogUpdates", "No");
}
async (check) => {
prefs.showBlogUpdates = check;
await setPreferences(prefs);
},
{initState: localStorage.getItem("blogUpdates") === "Yes"},
{initState: prefs.showBlogUpdates},
);
(async () => {
const posts = await this.getPosts();
@@ -3297,74 +3296,82 @@ class Localuser {
devSettings.addText(I18n.devSettings.description());
devSettings.addHR();
const box1 = devSettings.addCheckboxInput(I18n.devSettings.logGateway(), () => {}, {
initState: Boolean(localStorage.getItem("logGateway")),
initState: getDeveloperSettings().gatewayLogging,
});
box1.onchange = (e) => {
if (e) {
localStorage.setItem("logGateway", "true");
} else {
localStorage.removeItem("logGateway");
}
const settings = getDeveloperSettings();
settings.gatewayLogging = e;
setDeveloperSettings(settings);
};
const box2 = devSettings.addCheckboxInput(I18n.devSettings.badUser(), () => {}, {
initState: Boolean(localStorage.getItem("logbad")),
initState: getDeveloperSettings().logBannedFields,
});
box2.onchange = (e) => {
if (e) {
localStorage.setItem("logbad", "true");
} else {
localStorage.removeItem("logbad");
}
const settings = getDeveloperSettings();
settings.logBannedFields = e;
setDeveloperSettings(settings);
};
const box3 = devSettings.addCheckboxInput(I18n.devSettings.traces(), () => {}, {
initState: Boolean(localStorage.getItem("traces")),
initState: getDeveloperSettings().showTraces,
});
box3.onchange = (e) => {
if (e) {
localStorage.setItem("traces", "true");
} else {
localStorage.removeItem("traces");
}
const settings = getDeveloperSettings();
settings.showTraces = e;
setDeveloperSettings(settings);
};
const box4 = devSettings.addCheckboxInput(I18n.devSettings.cache(), () => {}, {
initState: !!localStorage.getItem("isDev"),
initState: getDeveloperSettings().cacheSourceMaps,
});
box4.onchange = (e) => {
if (e) {
localStorage.setItem("isDev", "true");
} else {
localStorage.removeItem("isDev");
}
const settings = getDeveloperSettings();
settings.cacheSourceMaps = e;
setDeveloperSettings(settings);
SW.postMessage({code: "isDev", dev: e});
};
devSettings.addText(I18n.devSettings.cacheDesc());
const box5 = devSettings.addCheckboxInput(I18n.devSettings.captureTrace(), () => {}, {
initState: !!localStorage.getItem("capTrace"),
initState: getDeveloperSettings().interceptApiTraces,
});
box5.onchange = (e) => {
if (e) {
localStorage.setItem("capTrace", "true");
} else {
localStorage.removeItem("capTrace");
}
const settings = getDeveloperSettings();
settings.interceptApiTraces = e;
setDeveloperSettings(settings);
SW.traceInit();
};
const box6 = devSettings.addCheckboxInput(I18n.devSettings.gatewayComp(), () => {}, {
initState: !!localStorage.getItem("gateWayComp"),
initState: getDeveloperSettings().gatewayCompression,
});
box6.onchange = (e) => {
if (e) {
localStorage.setItem("gateWayComp", "true");
} else {
localStorage.removeItem("gateWayComp");
}
const settings = getDeveloperSettings();
settings.gatewayCompression = e;
setDeveloperSettings(settings);
SW.traceInit();
};
devSettings.addButtonInput("", I18n.devSettings.clearWellKnowns(), async () => {
const currentUserInfos = JSON.parse(localStorage.getItem("userinfos")!);
for (const user of Object.keys(currentUserInfos.users)) {
const key =
currentUserInfos.users[user].serverurls.value ??
currentUserInfos.users[user].serverurls.wellknown ??
currentUserInfos.users[user].serverurls.api;
currentUserInfos.users[user].serverurls = await getapiurls(key);
console.log(key, currentUserInfos.users[user].serverurls);
localStorage.setItem("userinfos", JSON.stringify(currentUserInfos));
}
localStorage.removeItem("instanceinfo");
await SW.postMessage("clearCdnCache");
// @ts-ignore - chromium is smelly for not supporting the `forceGet` option (aka skip cache)
window.location.reload(true);
});
}
if (this.trace.length && localStorage.getItem("traces")) {
if (this.trace.length && getDeveloperSettings().showTraces) {
const traces = settings.addButton(I18n.localuser.trace(), {
noSubmit: true,
});
@@ -4362,17 +4369,20 @@ class Localuser {
readonly presences: Map<string, presencejson> = new Map();
static font?: FontFace;
static async loadFont() {
const fontName = localStorage.getItem("emoji-font");
const prefs = await getPreferences();
const fontName = prefs.emojiFont;
if (this.font) {
//TODO see when/if this can be removed
//@ts-ignore this is stupid. it's been here since 2020
document.fonts.delete(this.font);
}
const realname = this.fonts.find((_) => _[1] === fontName)?.[0];
if (realname) {
const font = new FontFace("emojiFont", `url("/emoji/${realname}")`);
await font.load();
console.error("fun");
console.error("Loaded font:", fontName, "/", realname);
//TODO see when/if this can be removed
//@ts-ignore this is stupid. it's been here since 2020
document.fonts.add(font);
+2 -1
View File
@@ -14,6 +14,7 @@ import {createImg, removeAni, safeImg} from "./utils/utils.js";
import {Direct} from "./direct.js";
import {Permissions} from "./permissions.js";
import {Channel} from "./channel.js";
import {getDeveloperSettings} from "./utils/storage/devSettings";
class User extends SnowFlake {
owner: Localuser;
hypotheticalpfp!: boolean;
@@ -45,7 +46,7 @@ class User extends SnowFlake {
constructor(userjson: userjson, owner: Localuser, dontclone: boolean = false) {
super(userjson.id);
this.owner = owner;
if (localStorage.getItem("logbad") && owner.user && owner.user.id !== userjson.id) {
if (getDeveloperSettings().logBannedFields && owner.user && owner.user.id !== userjson.id) {
this.checkfortmi(userjson);
}
if (!owner) {
+20 -17
View File
@@ -4,6 +4,9 @@ import {Dialog} from "../settings.js";
import {fix} from "./cssMagic.js";
import {messageFrom, messageTo} from "./serviceType.js";
import {isLoopback, trimTrailingSlashes} from "./netUtils";
import {getLocalSettings, ServiceWorkerMode, setLocalSettings} from "./storage/localSettings";
import {getPreferences} from "./storage/userPreferences";
import {getDeveloperSettings} from "./storage/devSettings";
fix();
const apiDoms = new Set<string>();
@@ -38,7 +41,7 @@ export function getBulkUsers() {
const user = (json.users[thing] = new Specialuser(json.users[thing]));
apiDoms.add(new URL(user.serverurls.api).host);
}
if (localStorage.getItem("capTrace")) {
if (getDeveloperSettings().interceptApiTraces) {
SW.postMessage({
code: "apiUrls",
hosts: [...apiDoms],
@@ -236,10 +239,6 @@ export class Specialuser {
localStorage.setItem("userinfos", JSON.stringify(info));
}
}
//this currently does not work, and need to be implemented better at some time.
if (!localStorage.getItem("SWMode")) {
localStorage.setItem("SWMode", "SWOn");
}
export function trimswitcher() {
const json = getBulkInfo();
const map = new Map();
@@ -857,11 +856,10 @@ export {checkInstance};
export class SW {
static worker: undefined | ServiceWorker;
static registration: ServiceWorkerRegistration;
static port?: MessagePort;
static init() {
SW.setMode(
(localStorage.getItem("SWMode") as "false" | "offlineOnly" | "true" | undefined) || "true",
);
SW.setMode(getLocalSettings().serviceWorkerMode);
const port = new MessageChannel();
SW.worker?.postMessage(
{
@@ -879,7 +877,7 @@ export class SW {
port.port1.close();
});
this.postMessage({code: "ping"});
this.postMessage({code: "isDev", dev: !!localStorage.getItem("isDev")});
this.postMessage({code: "isDev", dev: getDeveloperSettings().cacheSourceMaps});
this.captureEvent("updates", (update, stop) => {
this.needsUpdate ||= update.updates;
if (update) {
@@ -984,7 +982,7 @@ export class SW {
if (!("serviceWorker" in navigator)) return;
// If it's registered, it handles CDN caching regardless of settings.
if(localStorage.getItem("SWMode") === "unregistered") return;
if (getLocalSettings().serviceWorkerMode == ServiceWorkerMode.Unregistered) return;
return new Promise<void>((res) => {
navigator.serviceWorker
.register("/service.js", {
@@ -994,32 +992,37 @@ export class SW {
let serviceWorker: ServiceWorker | undefined;
if (registration.installing) {
serviceWorker = registration.installing;
console.log("installing");
console.log("Service worker: installing");
} else if (registration.waiting) {
serviceWorker = registration.waiting;
console.log("waiting");
console.log("Service worker: waiting");
} else if (registration.active) {
serviceWorker = registration.active;
console.log("active");
console.log("Service worker: active");
}
SW.worker = serviceWorker;
SW.registration = registration;
SW.init();
if (serviceWorker) {
console.log(serviceWorker.state);
console.log("Service worker state changed:", serviceWorker.state);
serviceWorker.addEventListener("statechange", (_) => {
console.log(serviceWorker.state);
console.log("Service worker state changed:", serviceWorker.state);
});
res();
}
});
});
}
static setMode(mode: "false" | "offlineOnly" | "true" | "unregistered") {
localStorage.setItem("SWMode", mode);
static setMode(mode: ServiceWorkerMode) {
const localSettings = getLocalSettings();
localSettings.serviceWorkerMode = mode;
setLocalSettings(localSettings);
if (this.worker) {
this.worker.postMessage({data: mode, code: "setMode"});
}
if (mode === ServiceWorkerMode.Unregistered) this.registration.unregister().then(r => console.log("Service worker unregistered:", r));
}
static forceClear() {