mirror of
https://github.com/smartfrigde/armcord.git
synced 2026-06-23 05:25:43 +00:00
Compare commits
4 commits
7d933c6529
...
158f537e7d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
158f537e7d | ||
|
|
8aea77ba25 | ||
|
|
3ec1bc2d32 |
||
|
|
11d02104d9 |
14 changed files with 74 additions and 66 deletions
|
|
@ -5,7 +5,7 @@ import { applyAppImageSandboxFix } from "./scripts/build/sandboxFix.mjs";
|
|||
export const config: Configuration = {
|
||||
appId: "app.legcord.Legcord",
|
||||
productName: "Legcord",
|
||||
artifactName: `Legcord-${version}-${os}-${arch}.${ext}`,
|
||||
artifactName: "Legcord-${version}-${os}-${arch}.${ext}",
|
||||
beforePack: applyAppImageSandboxFix,
|
||||
protocols: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export let firstRun: boolean;
|
|||
// Performance optimization: Cache config to avoid reading file on every call
|
||||
let configCache: Settings | null = null;
|
||||
let configCacheTime = 0;
|
||||
const CONFIG_CACHE_TTL = 1000; // Cache for 1 second
|
||||
const CONFIG_CACHE_TTL = 5000; // Cache for 5 seconds
|
||||
const defaults: Settings = {
|
||||
windowStyle: "default",
|
||||
channel: "stable",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
import type { BrowserWindow } from "electron";
|
||||
|
||||
let scriptCounter = 0;
|
||||
|
||||
export function addStyle(styleUrl: string): void {
|
||||
const id = `legcord-style-${styleUrl.replace(/[^a-zA-Z0-9]/g, "-")}`;
|
||||
if (document.getElementById(id)) return;
|
||||
const style = document.createElement("link");
|
||||
style.id = id;
|
||||
style.rel = "stylesheet";
|
||||
style.type = "text/css";
|
||||
style.href = styleUrl;
|
||||
|
|
@ -9,6 +14,7 @@ export function addStyle(styleUrl: string): void {
|
|||
}
|
||||
|
||||
export function addTheme(id: string, styleString: string): void {
|
||||
if (document.getElementById(id)) return;
|
||||
const style = document.createElement("style");
|
||||
style.textContent = styleString;
|
||||
style.id = id;
|
||||
|
|
@ -16,18 +22,21 @@ export function addTheme(id: string, styleString: string): void {
|
|||
}
|
||||
|
||||
export function addScript(scriptString: string): void {
|
||||
const id = `legcord-script-${++scriptCounter}`;
|
||||
if (document.getElementById(id)) return;
|
||||
const script = document.createElement("script");
|
||||
script.id = id;
|
||||
script.appendChild(document.createTextNode(scriptString));
|
||||
document.body.append(script);
|
||||
}
|
||||
|
||||
export async function injectJS(inject: string): Promise<void> {
|
||||
const id = `legcord-inject-${inject.replace(/[^a-zA-Z0-9]/g, "-")}`;
|
||||
if (document.getElementById(id)) return;
|
||||
const js = await (await fetch(`${inject}`)).text();
|
||||
|
||||
const el = document.createElement("script");
|
||||
|
||||
el.id = id;
|
||||
el.appendChild(document.createTextNode(js));
|
||||
|
||||
document.body.appendChild(el);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import type { WindowState } from "../@types/windowState.js";
|
|||
// Performance optimization: Cache window state to avoid reading file on every call
|
||||
let windowStateCache: WindowState | null = null;
|
||||
let windowStateCacheTime = 0;
|
||||
const WINDOW_STATE_CACHE_TTL = 1000; // Cache for 1 second
|
||||
const WINDOW_STATE_CACHE_TTL = 5000; // Cache for 5 seconds
|
||||
|
||||
export function getWindowStateLocation() {
|
||||
const userDataPath = app.getPath("userData");
|
||||
|
|
|
|||
|
|
@ -54,8 +54,7 @@ async function cacheCheck(mod: ValidMods) {
|
|||
}
|
||||
try {
|
||||
const latestRef = await getRef(modData[mod].repoData);
|
||||
// biome-ignore lint/correctness/noConstantCondition: https://github.com/Legcord/Legcord/issues/763
|
||||
if (/*latestRef === modCache![mod]*/ false) {
|
||||
if (latestRef === modCache![mod]) {
|
||||
console.log(`[Mod Loader]: ${mod} Cache hit!`);
|
||||
return;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,11 @@ function ifExistsRead(path: string): string | undefined {
|
|||
if (existsSync(path)) return readFileSync(path, "utf-8");
|
||||
}
|
||||
|
||||
let ipcRegistered = false;
|
||||
|
||||
export function registerIpc(passedWindow: BrowserWindow): void {
|
||||
if (ipcRegistered) return;
|
||||
ipcRegistered = true;
|
||||
ipcMain.handle("getShelterBundle", () => {
|
||||
return {
|
||||
js: ifExistsRead(path.join(app.getPath("userData"), "shelter.js")),
|
||||
|
|
|
|||
|
|
@ -1,18 +1,10 @@
|
|||
type OptimizableFunction<T extends Node> = (child: T) => T;
|
||||
|
||||
const optimize = <T extends Node>(orig: OptimizableFunction<T>) => {
|
||||
return function (this: Element, ...args: [Element]): T | number {
|
||||
if (typeof args[0]?.className === "string" && args[0].className.includes("activity")) {
|
||||
// fix by xql.dev <@1356430365774053448>
|
||||
setTimeout(() => orig.apply(this, args as unknown as [T]), 100);
|
||||
return args[0] as unknown as T;
|
||||
}
|
||||
return function (this: Element, ...args: [Element]): T {
|
||||
return orig.apply(this, args as unknown as [T]);
|
||||
} as unknown as OptimizableFunction<T>;
|
||||
};
|
||||
|
||||
// We are taking in the function itself
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
Element.prototype.removeChild = optimize(Element.prototype.removeChild);
|
||||
|
||||
// Thanks Ari - <@1249446413952225452>
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ async function load() {
|
|||
el.id = "ac-ver";
|
||||
el.textContent = `Legcord Version: ${version}`;
|
||||
info.after(el);
|
||||
observer.disconnect();
|
||||
});
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ let rpcWorker: Worker;
|
|||
export let processList: GameList[] = [];
|
||||
|
||||
export function startRPC(window: BrowserWindow) {
|
||||
if (rpcWorker) {
|
||||
rpcWorker.terminate();
|
||||
}
|
||||
const rpcPath = path.join(__dirname, "rpc.js");
|
||||
|
||||
rpcWorker = new Worker(rpcPath, {
|
||||
|
|
|
|||
|
|
@ -187,6 +187,14 @@ function doAfterDefiningTheWindow(passedWindow: BrowserWindow): void {
|
|||
if (blockedPatterns.some((pattern) => pattern.test(details.url))) {
|
||||
return callback({ cancel: true });
|
||||
}
|
||||
if (
|
||||
details.url.includes("ws://127.0.0.1:") &&
|
||||
!details.url.includes("127.0.0.1:1211") &&
|
||||
!details.url.includes("127.0.0.1:1112") &&
|
||||
!details.url.includes("127.0.0.1:6888")
|
||||
) {
|
||||
return callback({ cancel: true });
|
||||
}
|
||||
return callback({});
|
||||
});
|
||||
|
||||
|
|
@ -268,9 +276,7 @@ function doAfterDefiningTheWindow(passedWindow: BrowserWindow): void {
|
|||
// Update window title with Legcord suffix
|
||||
if (!title.endsWith(legcordSuffix)) {
|
||||
e.preventDefault();
|
||||
// Security: Use JSON.stringify to prevent code injection via title
|
||||
const safeTitle = JSON.stringify(title.replace("Discord |", "") + legcordSuffix);
|
||||
void passedWindow.webContents.executeJavaScript(`document.title = ${safeTitle}`);
|
||||
passedWindow.setTitle(title.replace("Discord |", "") + legcordSuffix);
|
||||
}
|
||||
});
|
||||
injectThemesMain(passedWindow);
|
||||
|
|
@ -303,18 +309,7 @@ function doAfterDefiningTheWindow(passedWindow: BrowserWindow): void {
|
|||
});
|
||||
setForceQuit(true);
|
||||
});
|
||||
passedWindow.webContents.session.webRequest.onBeforeRequest((details, callback) => {
|
||||
// Lune Dev exceptions, https://github.com/uwu/shelter/blob/8d4ca369bf01abf348df9d4e111d534800c7a38c/packages/shelter/src/devmode/index.tsx#L24
|
||||
if (
|
||||
details.url.includes("ws://127.0.0.1:") &&
|
||||
!details.url.includes("127.0.0.1:1211") &&
|
||||
!details.url.includes("127.0.0.1:1112") &&
|
||||
!details.url.includes("127.0.0.1:6888")
|
||||
) {
|
||||
return callback({ cancel: true });
|
||||
}
|
||||
return callback({});
|
||||
});
|
||||
|
||||
passedWindow.on("focus", () => {
|
||||
void passedWindow.webContents.executeJavaScript(`document.body.removeAttribute("unFocused");`);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,7 +22,10 @@ const {
|
|||
flux: { dispatcher, storesFlat },
|
||||
} = shelter;
|
||||
|
||||
const settingsPages = [
|
||||
let settingsCleanups: (() => void)[] = [];
|
||||
|
||||
function registerSections(): (() => void)[] {
|
||||
return [
|
||||
registerSection("divider"),
|
||||
registerSection("header", "Legcord"),
|
||||
registerSection("section", "legcord-settings", "Settings", SettingsPage, { icon: SettingsSidebarIcon }),
|
||||
|
|
@ -30,18 +33,19 @@ const settingsPages = [
|
|||
registerSection("section", "legcord-plugins", "Plugins", PluginsPage, { icon: PluginsSidebarIcon }),
|
||||
registerSection("section", "legcord-keybinds", "Keybinds", KeybindsPage, { icon: KeybindsSidebarIcon }),
|
||||
registerSection("section", "legcord-games", "Games", RegisteredGamesPage, { icon: GamesSidebarIcon }),
|
||||
];
|
||||
];
|
||||
}
|
||||
|
||||
function restartRequired(payload: { event: string; properties: { origin_pane: string } }) {
|
||||
if (payload.event === "settings_pane_viewed" && typeof payload.properties.origin_pane !== "undefined") {
|
||||
const pane = payload.properties.origin_pane;
|
||||
if ((pane === "legcord-settings" || pane === "legcord-games") && isRestartRequired) {
|
||||
openConfirmationModal({
|
||||
header: () => store.i18n["settings-restartRequired"],
|
||||
body: () => store.i18n["settings-restartRequiredBody"],
|
||||
header: () => store.i18n?.["settings-restartRequired"] ?? "Restart required",
|
||||
body: () => store.i18n?.["settings-restartRequiredBody"] ?? "A restart is required to apply changes.",
|
||||
type: "danger",
|
||||
confirmText: store.i18n["settings-restart"],
|
||||
cancelText: store.i18n["settings-restartLater"],
|
||||
confirmText: store.i18n?.["settings-restart"] ?? "Restart",
|
||||
cancelText: store.i18n?.["settings-restartLater"] ?? "Later",
|
||||
}).then(
|
||||
() => window.legcord.restart(),
|
||||
() => console.log("restart skipped"),
|
||||
|
|
@ -57,11 +61,11 @@ export function onLoad() {
|
|||
store.i18n = window.legcord.translations;
|
||||
log("Legcord Settings");
|
||||
window.legcord.settings.setLang(storesFlat.LocaleStore.locale);
|
||||
settingsPages;
|
||||
settingsCleanups = registerSections();
|
||||
dispatcher.subscribe("TRACK", restartRequired);
|
||||
}
|
||||
export function onUnload() {
|
||||
settingsPages.forEach((e) => {
|
||||
settingsCleanups.forEach((e) => {
|
||||
e();
|
||||
});
|
||||
dispatcher.unsubscribe("TRACK", restartRequired);
|
||||
|
|
|
|||
|
|
@ -12,21 +12,24 @@ const {
|
|||
ui: { SwitchItem, Header, HeaderTags, Button, ButtonSizes },
|
||||
} = shelter;
|
||||
|
||||
const settings = store.settings as Settings;
|
||||
const noBundleUpdates = () => {
|
||||
const noBundleUpdates = (settings: Settings) => {
|
||||
const value = settings.noBundleUpdates;
|
||||
if (Array.isArray(value)) return value;
|
||||
return value ? ["shelter", "vencord", "equicord", "custom"] : [];
|
||||
};
|
||||
|
||||
export function SettingsPage() {
|
||||
const settings = store.settings as Settings;
|
||||
if (!settings) {
|
||||
return (
|
||||
<>
|
||||
<Header class={classes.category} tag={HeaderTags.HeadingXL}>
|
||||
{store.i18n["settings-firstTimeCrash"]}
|
||||
{store.i18n?.["settings-firstTimeCrash"] ?? "Setting things up..."}
|
||||
</Header>
|
||||
<p>{store.i18n["settings-firstTimeCrash-desc"]}</p>
|
||||
<p>
|
||||
{store.i18n?.["settings-firstTimeCrash-desc"] ??
|
||||
"Settings are not available on a first-time launch. Please restart."}
|
||||
</p>
|
||||
<br />
|
||||
<Button size={ButtonSizes.MAX} onClick={() => window.legcord.restart()}>
|
||||
Restart Legcord
|
||||
|
|
@ -529,9 +532,9 @@ export function SettingsPage() {
|
|||
</Header>
|
||||
<SwitchItem
|
||||
note={store.i18n["settings-noBundleUpdates-desc"]}
|
||||
value={noBundleUpdates().includes("shelter")}
|
||||
value={noBundleUpdates(settings).includes("shelter")}
|
||||
onChange={(e: boolean) => {
|
||||
const next = new Set(noBundleUpdates());
|
||||
const next = new Set(noBundleUpdates(settings));
|
||||
if (e) next.add("shelter");
|
||||
else next.delete("shelter");
|
||||
setConfig("noBundleUpdates", Array.from(next) as Settings["noBundleUpdates"], true);
|
||||
|
|
@ -541,9 +544,9 @@ export function SettingsPage() {
|
|||
</SwitchItem>
|
||||
<Show when={settings.mods.includes("vencord")}>
|
||||
<SwitchItem
|
||||
value={noBundleUpdates().includes("vencord")}
|
||||
value={noBundleUpdates(settings).includes("vencord")}
|
||||
onChange={(e: boolean) => {
|
||||
const next = new Set(noBundleUpdates());
|
||||
const next = new Set(noBundleUpdates(settings));
|
||||
if (e) next.add("vencord");
|
||||
else next.delete("vencord");
|
||||
setConfig("noBundleUpdates", Array.from(next) as Settings["noBundleUpdates"], true);
|
||||
|
|
@ -554,9 +557,9 @@ export function SettingsPage() {
|
|||
</Show>
|
||||
<Show when={settings.mods.includes("equicord")}>
|
||||
<SwitchItem
|
||||
value={noBundleUpdates().includes("equicord")}
|
||||
value={noBundleUpdates(settings).includes("equicord")}
|
||||
onChange={(e: boolean) => {
|
||||
const next = new Set(noBundleUpdates());
|
||||
const next = new Set(noBundleUpdates(settings));
|
||||
if (e) next.add("equicord");
|
||||
else next.delete("equicord");
|
||||
setConfig("noBundleUpdates", Array.from(next) as Settings["noBundleUpdates"], true);
|
||||
|
|
@ -567,9 +570,9 @@ export function SettingsPage() {
|
|||
</Show>
|
||||
<Show when={settings.mods.includes("custom")}>
|
||||
<SwitchItem
|
||||
value={noBundleUpdates().includes("custom")}
|
||||
value={noBundleUpdates(settings).includes("custom")}
|
||||
onChange={(e: boolean) => {
|
||||
const next = new Set(noBundleUpdates());
|
||||
const next = new Set(noBundleUpdates(settings));
|
||||
if (e) next.add("custom");
|
||||
else next.delete("custom");
|
||||
setConfig("noBundleUpdates", Array.from(next) as Settings["noBundleUpdates"], true);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ const {
|
|||
ui: { Button, Header, HeaderTags, ButtonSizes, TextBox, showToast, SwitchItem },
|
||||
plugin: { store },
|
||||
} = shelter;
|
||||
const settings = store.settings as Settings;
|
||||
export function ThemesPage() {
|
||||
const [downloadUrl, setDownloadUrl] = createSignal("");
|
||||
refreshThemes();
|
||||
|
|
@ -27,13 +26,14 @@ export function ThemesPage() {
|
|||
});
|
||||
}
|
||||
|
||||
const settings = () => store.settings as Settings;
|
||||
const t = store.i18n;
|
||||
return (
|
||||
<>
|
||||
<Header tag={HeaderTags.H1}>Themes</Header>
|
||||
<SwitchItem
|
||||
note={store.i18n["settings-quickCss-desc"]}
|
||||
value={settings.quickCss}
|
||||
value={settings().quickCss}
|
||||
onChange={(e: boolean) => {
|
||||
console.log("Toggled quick CSS", e);
|
||||
if (e) {
|
||||
|
|
@ -50,7 +50,7 @@ export function ThemesPage() {
|
|||
<Button
|
||||
size={ButtonSizes.LARGE}
|
||||
onClick={window.legcord.themes.openQuickCss}
|
||||
disabled={!settings.quickCss}
|
||||
disabled={!settings().quickCss}
|
||||
>
|
||||
{t["themes-openQuickCss"]}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ const {
|
|||
plugin: { store },
|
||||
} = shelter;
|
||||
|
||||
const settings = store.settings as Settings;
|
||||
|
||||
export let isRestartRequired = false;
|
||||
|
||||
export function setRestartRequired() {
|
||||
|
|
@ -21,7 +19,7 @@ export function refreshThemes() {
|
|||
}
|
||||
|
||||
export function setConfig<K extends keyof Settings>(key: K, value: Settings[K], shouldRestart?: boolean) {
|
||||
settings[key] = value;
|
||||
store.settings[key] = value;
|
||||
console.log(key, ":", store.settings[key]);
|
||||
if (shouldRestart) {
|
||||
isRestartRequired = true;
|
||||
|
|
@ -36,7 +34,7 @@ function removeMod(array: ValidMods[], filter: ValidMods) {
|
|||
|
||||
export function toggleMod(mod: ValidMods, enabled: boolean) {
|
||||
isRestartRequired = true;
|
||||
const currentMods = settings.mods;
|
||||
const currentMods = store.settings.mods;
|
||||
if (enabled) {
|
||||
if (mod === "vencord") {
|
||||
currentMods.push("vencord");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue