mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-07 13:43:03 -04:00
Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
commit
3e9e1722fd
14 changed files with 124 additions and 60 deletions
|
@ -20,15 +20,12 @@
|
||||||
/// <reference path="../src/globals.d.ts" />
|
/// <reference path="../src/globals.d.ts" />
|
||||||
|
|
||||||
import monacoHtmlLocal from "file://monacoWin.html?minify";
|
import monacoHtmlLocal from "file://monacoWin.html?minify";
|
||||||
import monacoHtmlCdn from "file://../src/main/monacoWin.html?minify";
|
|
||||||
import * as DataStore from "../src/api/DataStore";
|
import * as DataStore from "../src/api/DataStore";
|
||||||
import { debounce } from "../src/utils";
|
import { debounce, localStorage } from "../src/utils";
|
||||||
import { EXTENSION_BASE_URL } from "../src/utils/web-metadata";
|
import { EXTENSION_BASE_URL } from "../src/utils/web-metadata";
|
||||||
import { getTheme, Theme } from "../src/utils/discord";
|
import { getTheme, Theme } from "../src/utils/discord";
|
||||||
import { Settings } from "../src/Vencord";
|
import { Settings } from "../src/Vencord";
|
||||||
|
import { getStylusWebStoreUrl } from "@utils/web";
|
||||||
// Discord deletes this so need to store in variable
|
|
||||||
const { localStorage } = window;
|
|
||||||
|
|
||||||
// listeners for ipc.on
|
// listeners for ipc.on
|
||||||
const cssListeners = new Set<(css: string) => void>();
|
const cssListeners = new Set<(css: string) => void>();
|
||||||
|
@ -76,6 +73,14 @@ window.VencordNative = {
|
||||||
addThemeChangeListener: NOOP,
|
addThemeChangeListener: NOOP,
|
||||||
openFile: NOOP_ASYNC,
|
openFile: NOOP_ASYNC,
|
||||||
async openEditor() {
|
async openEditor() {
|
||||||
|
if (IS_USERSCRIPT) {
|
||||||
|
const shouldOpenWebStore = confirm("QuickCSS is not supported on the Userscript. You can instead use the Stylus extension.\n\nDo you want to open the Stylus web store page?");
|
||||||
|
if (shouldOpenWebStore) {
|
||||||
|
window.open(getStylusWebStoreUrl(), "_blank");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const features = `popup,width=${Math.min(window.innerWidth, 1000)},height=${Math.min(window.innerHeight, 1000)}`;
|
const features = `popup,width=${Math.min(window.innerWidth, 1000)},height=${Math.min(window.innerHeight, 1000)}`;
|
||||||
const win = open("about:blank", "VencordQuickCss", features);
|
const win = open("about:blank", "VencordQuickCss", features);
|
||||||
if (!win) {
|
if (!win) {
|
||||||
|
@ -91,7 +96,7 @@ window.VencordNative = {
|
||||||
? "vs-light"
|
? "vs-light"
|
||||||
: "vs-dark";
|
: "vs-dark";
|
||||||
|
|
||||||
win.document.write(IS_EXTENSION ? monacoHtmlLocal : monacoHtmlCdn);
|
win.document.write(monacoHtmlLocal);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ const defines = stringifyValues({
|
||||||
IS_UPDATER_DISABLED,
|
IS_UPDATER_DISABLED,
|
||||||
IS_WEB: false,
|
IS_WEB: false,
|
||||||
IS_EXTENSION: false,
|
IS_EXTENSION: false,
|
||||||
|
IS_USERSCRIPT: false,
|
||||||
VERSION,
|
VERSION,
|
||||||
BUILD_TIMESTAMP
|
BUILD_TIMESTAMP
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,6 +43,7 @@ const commonOptions = {
|
||||||
define: stringifyValues({
|
define: stringifyValues({
|
||||||
IS_WEB: true,
|
IS_WEB: true,
|
||||||
IS_EXTENSION: false,
|
IS_EXTENSION: false,
|
||||||
|
IS_USERSCRIPT: false,
|
||||||
IS_STANDALONE: true,
|
IS_STANDALONE: true,
|
||||||
IS_DEV,
|
IS_DEV,
|
||||||
IS_REPORTER,
|
IS_REPORTER,
|
||||||
|
@ -108,6 +109,7 @@ const buildConfigs = [
|
||||||
inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])],
|
inject: ["browser/GMPolyfill.js", ...(commonOptions?.inject || [])],
|
||||||
define: {
|
define: {
|
||||||
...commonOptions.define,
|
...commonOptions.define,
|
||||||
|
IS_USERSCRIPT: "true",
|
||||||
window: "unsafeWindow",
|
window: "unsafeWindow",
|
||||||
},
|
},
|
||||||
outfile: "dist/Vencord.user.js",
|
outfile: "dist/Vencord.user.js",
|
||||||
|
|
|
@ -153,7 +153,11 @@ async function init() {
|
||||||
|
|
||||||
if (!IS_WEB && !IS_UPDATER_DISABLED) {
|
if (!IS_WEB && !IS_UPDATER_DISABLED) {
|
||||||
runUpdateCheck();
|
runUpdateCheck();
|
||||||
setInterval(runUpdateCheck, 1000 * 60 * 30); // 30 minutes
|
|
||||||
|
// this tends to get really annoying, so only do this if the user has auto-update without notification enabled
|
||||||
|
if (Settings.autoUpdate && !Settings.autoUpdateNotification) {
|
||||||
|
setInterval(runUpdateCheck, 1000 * 60 * 30); // 30 minutes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_DEV) {
|
if (IS_DEV) {
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.visual-refresh .vc-notification-root {
|
||||||
|
background-color: var(--background-base-low);
|
||||||
|
}
|
||||||
|
|
||||||
.vc-notification-root:not(.vc-notification-log-wrapper > .vc-notification-root) {
|
.vc-notification-root:not(.vc-notification-log-wrapper > .vc-notification-root) {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 2147483647;
|
z-index: 2147483647;
|
||||||
|
|
3
src/globals.d.ts
vendored
3
src/globals.d.ts
vendored
|
@ -29,11 +29,12 @@ declare global {
|
||||||
* replace: "IS_WEB?foo:bar"
|
* replace: "IS_WEB?foo:bar"
|
||||||
* // GOOD
|
* // GOOD
|
||||||
* replace: IS_WEB ? "foo" : "bar"
|
* replace: IS_WEB ? "foo" : "bar"
|
||||||
* // also good
|
* // also okay
|
||||||
* replace: `${IS_WEB}?foo:bar`
|
* replace: `${IS_WEB}?foo:bar`
|
||||||
*/
|
*/
|
||||||
export var IS_WEB: boolean;
|
export var IS_WEB: boolean;
|
||||||
export var IS_EXTENSION: boolean;
|
export var IS_EXTENSION: boolean;
|
||||||
|
export var IS_USERSCRIPT: boolean;
|
||||||
export var IS_STANDALONE: boolean;
|
export var IS_STANDALONE: boolean;
|
||||||
export var IS_UPDATER_DISABLED: boolean;
|
export var IS_UPDATER_DISABLED: boolean;
|
||||||
export var IS_DEV: boolean;
|
export var IS_DEV: boolean;
|
||||||
|
|
|
@ -30,7 +30,10 @@ export function serializeErrors(func: (...args: any[]) => any) {
|
||||||
ok: false,
|
ok: false,
|
||||||
error: e instanceof Error ? {
|
error: e instanceof Error ? {
|
||||||
// prototypes get lost, so turn error into plain object
|
// prototypes get lost, so turn error into plain object
|
||||||
...e
|
...e,
|
||||||
|
message: e.message,
|
||||||
|
name: e.name,
|
||||||
|
stack: e.stack
|
||||||
} : e
|
} : e
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { get } from "@main/utils/simpleGet";
|
import { fetchBuffer, fetchJson } from "@main/utils/http";
|
||||||
import { IpcEvents } from "@shared/IpcEvents";
|
import { IpcEvents } from "@shared/IpcEvents";
|
||||||
import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent";
|
import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent";
|
||||||
import { ipcMain } from "electron";
|
import { ipcMain } from "electron";
|
||||||
|
@ -30,8 +30,8 @@ import { ASAR_FILE, serializeErrors } from "./common";
|
||||||
const API_BASE = `https://api.github.com/repos/${gitRemote}`;
|
const API_BASE = `https://api.github.com/repos/${gitRemote}`;
|
||||||
let PendingUpdate: string | null = null;
|
let PendingUpdate: string | null = null;
|
||||||
|
|
||||||
async function githubGet(endpoint: string) {
|
async function githubGet<T = any>(endpoint: string) {
|
||||||
return get(API_BASE + endpoint, {
|
return fetchJson<T>(API_BASE + endpoint, {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: "application/vnd.github+json",
|
Accept: "application/vnd.github+json",
|
||||||
// "All API requests MUST include a valid User-Agent header.
|
// "All API requests MUST include a valid User-Agent header.
|
||||||
|
@ -45,9 +45,8 @@ async function calculateGitChanges() {
|
||||||
const isOutdated = await fetchUpdates();
|
const isOutdated = await fetchUpdates();
|
||||||
if (!isOutdated) return [];
|
if (!isOutdated) return [];
|
||||||
|
|
||||||
const res = await githubGet(`/compare/${gitHash}...HEAD`);
|
const data = await githubGet(`/compare/${gitHash}...HEAD`);
|
||||||
|
|
||||||
const data = JSON.parse(res.toString("utf-8"));
|
|
||||||
return data.commits.map((c: any) => ({
|
return data.commits.map((c: any) => ({
|
||||||
// github api only sends the long sha
|
// github api only sends the long sha
|
||||||
hash: c.sha.slice(0, 7),
|
hash: c.sha.slice(0, 7),
|
||||||
|
@ -57,9 +56,8 @@ async function calculateGitChanges() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchUpdates() {
|
async function fetchUpdates() {
|
||||||
const release = await githubGet("/releases/latest");
|
const data = await githubGet("/releases/latest");
|
||||||
|
|
||||||
const data = JSON.parse(release.toString());
|
|
||||||
const hash = data.name.slice(data.name.lastIndexOf(" ") + 1);
|
const hash = data.name.slice(data.name.lastIndexOf(" ") + 1);
|
||||||
if (hash === gitHash)
|
if (hash === gitHash)
|
||||||
return false;
|
return false;
|
||||||
|
@ -74,7 +72,7 @@ async function fetchUpdates() {
|
||||||
async function applyUpdates() {
|
async function applyUpdates() {
|
||||||
if (!PendingUpdate) return true;
|
if (!PendingUpdate) return true;
|
||||||
|
|
||||||
const data = await get(PendingUpdate);
|
const data = await fetchBuffer(PendingUpdate);
|
||||||
originalWriteFileSync(__dirname, data);
|
originalWriteFileSync(__dirname, data);
|
||||||
|
|
||||||
PendingUpdate = null;
|
PendingUpdate = null;
|
||||||
|
|
|
@ -24,7 +24,7 @@ import { join } from "path";
|
||||||
|
|
||||||
import { DATA_DIR } from "./constants";
|
import { DATA_DIR } from "./constants";
|
||||||
import { crxToZip } from "./crxToZip";
|
import { crxToZip } from "./crxToZip";
|
||||||
import { get } from "./simpleGet";
|
import { fetchBuffer } from "./http";
|
||||||
|
|
||||||
const extensionCacheDir = join(DATA_DIR, "ExtensionCache");
|
const extensionCacheDir = join(DATA_DIR, "ExtensionCache");
|
||||||
|
|
||||||
|
@ -69,13 +69,14 @@ export async function installExt(id: string) {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const url = `https://clients2.google.com/service/update2/crx?response=redirect&acceptformat=crx2,crx3&x=id%3D${id}%26uc&prodversion=${process.versions.chrome}`;
|
const url = `https://clients2.google.com/service/update2/crx?response=redirect&acceptformat=crx2,crx3&x=id%3D${id}%26uc&prodversion=${process.versions.chrome}`;
|
||||||
|
|
||||||
const buf = await get(url, {
|
const buf = await fetchBuffer(url, {
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent": `Electron ${process.versions.electron} ~ Equicord (https://github.com/Equicord/Equicord)`
|
"User-Agent": `Electron ${process.versions.electron} ~ Equicord (https://github.com/Equicord/Equicord)`
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await extract(crxToZip(buf), extDir).catch(console.error);
|
await extract(crxToZip(buf), extDir)
|
||||||
|
.catch(err => console.error(`Failed to extract extension ${id}`, err));
|
||||||
}
|
}
|
||||||
|
|
||||||
session.defaultSession.loadExtension(extDir);
|
session.defaultSession.loadExtension(extDir);
|
||||||
|
|
70
src/main/utils/http.ts
Normal file
70
src/main/utils/http.ts
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2022 Vendicated and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createWriteStream } from "original-fs";
|
||||||
|
import { Readable } from "stream";
|
||||||
|
import { finished } from "stream/promises";
|
||||||
|
|
||||||
|
type Url = string | URL;
|
||||||
|
|
||||||
|
export async function checkedFetch(url: Url, options?: RequestInit) {
|
||||||
|
try {
|
||||||
|
var res = await fetch(url, options);
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof Error && err.cause) {
|
||||||
|
err = err.cause;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`${options?.method ?? "GET"} ${url} failed: ${err}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = `${options?.method ?? "GET"} ${url}: ${res.status} ${res.statusText}`;
|
||||||
|
try {
|
||||||
|
const reason = await res.text();
|
||||||
|
message += `\n${reason}`;
|
||||||
|
} catch { }
|
||||||
|
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchJson<T = any>(url: Url, options?: RequestInit) {
|
||||||
|
const res = await checkedFetch(url, options);
|
||||||
|
return res.json() as Promise<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchBuffer(url: Url, options?: RequestInit) {
|
||||||
|
const res = await checkedFetch(url, options);
|
||||||
|
const buf = await res.arrayBuffer();
|
||||||
|
|
||||||
|
return Buffer.from(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downloadToFile(url: Url, path: string, options?: RequestInit) {
|
||||||
|
const res = await checkedFetch(url, options);
|
||||||
|
if (!res.body) {
|
||||||
|
throw new Error(`Download ${url}: response body is empty`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error weird type conflict
|
||||||
|
const body = Readable.fromWeb(res.body);
|
||||||
|
await finished(body.pipe(createWriteStream(path)));
|
||||||
|
}
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Vencord, a modification for Discord's desktop app
|
|
||||||
* Copyright (c) 2022 Vendicated and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import https from "https";
|
|
||||||
|
|
||||||
export function get(url: string, options: https.RequestOptions = {}) {
|
|
||||||
return new Promise<Buffer>((resolve, reject) => {
|
|
||||||
https.get(url, options, res => {
|
|
||||||
const { statusCode, statusMessage, headers } = res;
|
|
||||||
if (statusCode! >= 400)
|
|
||||||
return void reject(`${statusCode}: ${statusMessage} - ${url}`);
|
|
||||||
if (statusCode! >= 300)
|
|
||||||
return void resolve(get(headers.location!, options));
|
|
||||||
|
|
||||||
const chunks = [] as Buffer[];
|
|
||||||
res.on("error", reject);
|
|
||||||
|
|
||||||
res.on("data", chunk => chunks.push(chunk));
|
|
||||||
res.once("end", () => resolve(Buffer.concat(chunks)));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -111,7 +111,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Changes the indicator to keep the user object when creating the list of typing users
|
// Changes the indicator to keep the user object when creating the list of typing users
|
||||||
match: /\.map\((\i)=>\i\.\i\.getName\(\i,\i\.id,\1\)\)/,
|
match: /\.map\((\i)=>\i\.\i\.getName\(\i(?:\.guild_id)?,\i\.id,\1\)\)/,
|
||||||
replace: ""
|
replace: ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,7 +39,7 @@ async function initSystemValues() {
|
||||||
createStyle("vencord-os-theme-values").textContent = `:root{${variables}}`;
|
createStyle("vencord-os-theme-values").textContent = `:root{${variables}}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function toggle(isEnabled: boolean) {
|
async function toggle(isEnabled: boolean) {
|
||||||
if (!style) {
|
if (!style) {
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
style = createStyle("vencord-custom-css");
|
style = createStyle("vencord-custom-css");
|
||||||
|
@ -92,6 +92,8 @@ async function initThemes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
if (IS_USERSCRIPT) return;
|
||||||
|
|
||||||
initSystemValues();
|
initSystemValues();
|
||||||
initThemes();
|
initThemes();
|
||||||
|
|
||||||
|
@ -104,9 +106,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
if (!IS_WEB) {
|
if (!IS_WEB) {
|
||||||
VencordNative.quickCss.addThemeChangeListener(initThemes);
|
VencordNative.quickCss.addThemeChangeListener(initThemes);
|
||||||
}
|
}
|
||||||
});
|
}, { once: true });
|
||||||
|
|
||||||
export function initQuickCssThemeStore() {
|
export function initQuickCssThemeStore() {
|
||||||
|
if (IS_USERSCRIPT) return;
|
||||||
|
|
||||||
initThemes();
|
initThemes();
|
||||||
|
|
||||||
let currentTheme = ThemeStore.theme;
|
let currentTheme = ThemeStore.theme;
|
||||||
|
|
|
@ -53,3 +53,11 @@ export function chooseFile(mimeTypes: string) {
|
||||||
setImmediate(() => document.body.removeChild(input));
|
setImmediate(() => document.body.removeChild(input));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getStylusWebStoreUrl() {
|
||||||
|
const isChromium = (navigator as any).userAgentData?.brands?.some(b => b.brand === "Chromium");
|
||||||
|
|
||||||
|
return isChromium
|
||||||
|
? "https://chromewebstore.google.com/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne"
|
||||||
|
: "https://addons.mozilla.org/firefox/addon/styl-us/";
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue