Merge 4ac701f05a
into 5d675efb64
This commit is contained in:
commit
67e0048fef
11 changed files with 142 additions and 18 deletions
|
@ -44,6 +44,7 @@ export const VENCORD_SETTINGS_DIR = join(DATA_DIR, "settings");
|
|||
export const VENCORD_QUICKCSS_FILE = join(VENCORD_SETTINGS_DIR, "quickCss.css");
|
||||
export const VENCORD_SETTINGS_FILE = join(VENCORD_SETTINGS_DIR, "settings.json");
|
||||
export const VENCORD_THEMES_DIR = join(DATA_DIR, "themes");
|
||||
export const VESKTOP_SPLASH_DIR = join(DATA_DIR, "splash");
|
||||
|
||||
// needs to be inline require because of circular dependency
|
||||
// as otherwise "DATA_DIR" (which is used by ./settings) will be uninitialised
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
|
||||
import "./ipc";
|
||||
|
||||
import { app, BrowserWindow, nativeTheme } from "electron";
|
||||
import { join } from "path";
|
||||
import { app, BrowserWindow, nativeTheme, net, protocol, session } from "electron";
|
||||
import { autoUpdater } from "electron-updater";
|
||||
|
||||
import { DATA_DIR } from "./constants";
|
||||
import { DATA_DIR, VESKTOP_SPLASH_DIR } from "./constants";
|
||||
import { createFirstLaunchTour } from "./firstLaunch";
|
||||
import { createWindows, mainWin } from "./mainWindow";
|
||||
import { registerMediaPermissionsHandler } from "./mediaPermissions";
|
||||
|
@ -84,6 +85,36 @@ function init() {
|
|||
registerScreenShareHandler();
|
||||
registerMediaPermissionsHandler();
|
||||
|
||||
//register file handler so we can load the custom splash animation from the user's filesystem
|
||||
protocol.handle("splash-animation", () => {
|
||||
const { splashAnimationPath } = Settings.store;
|
||||
const fullPath = join(VESKTOP_SPLASH_DIR, splashAnimationPath as string);
|
||||
return net.fetch("file:///"+fullPath);
|
||||
});
|
||||
|
||||
//this patches the discord csp to allow the splash-animation:// protocol
|
||||
//the vencord:// protocol is already whitelisted, but the code for doing that is in the
|
||||
//vencord repo, not the vesktop one. hopefully in the future, the splash image functionality
|
||||
//can be added to the vencord:// protocol handler, or the vencord:// protocol handler can be moved here
|
||||
let otherHandler: any = null;
|
||||
session.defaultSession.webRequest.onHeadersReceived(({responseHeaders, resourceType}, callback) => {
|
||||
if (responseHeaders && resourceType === "mainFrame" && responseHeaders["content-security-policy"]) {
|
||||
let csp = responseHeaders["content-security-policy"][0];
|
||||
csp = csp.replace("img-src", "img-src splash-animation:");
|
||||
responseHeaders["content-security-policy"] = [csp];
|
||||
}
|
||||
if (otherHandler) {
|
||||
otherHandler({responseHeaders, resourceType}, callback);
|
||||
}
|
||||
else {
|
||||
callback({ cancel: false, responseHeaders });
|
||||
}
|
||||
});
|
||||
//we need to overwrite onHeadersReceived because normally electron only allows one handler to be active at a time
|
||||
session.defaultSession.webRequest.onHeadersReceived = (handler) => {
|
||||
otherHandler = handler;
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
|
||||
app.on("activate", () => {
|
||||
|
|
|
@ -8,16 +8,17 @@ if (process.platform === "linux") import("./venmic");
|
|||
|
||||
import { execFile } from "child_process";
|
||||
import { app, BrowserWindow, clipboard, dialog, nativeImage, RelaunchOptions, session, shell } from "electron";
|
||||
import { mkdirSync, readFileSync, watch } from "fs";
|
||||
import { open, readFile } from "fs/promises";
|
||||
import { mkdirSync, readFileSync, watch, existsSync } from "fs";
|
||||
import { open, readFile, copyFile, mkdir, rmdir } from "fs/promises";
|
||||
import { release } from "os";
|
||||
import { join } from "path";
|
||||
import { randomBytes } from "crypto";
|
||||
import { join, extname } from "path";
|
||||
import { debounce } from "shared/utils/debounce";
|
||||
|
||||
import { IpcEvents } from "../shared/IpcEvents";
|
||||
import { setBadgeCount } from "./appBadge";
|
||||
import { autoStart } from "./autoStart";
|
||||
import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./constants";
|
||||
import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR, VESKTOP_SPLASH_DIR } from "./constants";
|
||||
import { mainWin } from "./mainWindow";
|
||||
import { Settings, State } from "./settings";
|
||||
import { handle, handleSync } from "./utils/ipcWrappers";
|
||||
|
@ -126,6 +127,29 @@ handle(IpcEvents.SELECT_VENCORD_DIR, async (_e, value?: null) => {
|
|||
return "ok";
|
||||
});
|
||||
|
||||
handle(IpcEvents.SELECT_IMAGE_PATH, async () => {
|
||||
const res = await dialog.showOpenDialog(mainWin!, {
|
||||
properties: ["openFile"],
|
||||
filters: [
|
||||
{name: "Images", extensions: ["apng", "avif", "gif", "jpeg", "png", "svg", "webp"]}
|
||||
]
|
||||
});
|
||||
if (!res.filePaths.length) return "cancelled";
|
||||
|
||||
const originalPath = res.filePaths[0];
|
||||
const uuid = randomBytes(16).toString("hex");
|
||||
const imageName = "splash_" + uuid + extname(originalPath);
|
||||
const destPath = join(VESKTOP_SPLASH_DIR, imageName);
|
||||
|
||||
if (existsSync(VESKTOP_SPLASH_DIR)) {
|
||||
await rmdir(VESKTOP_SPLASH_DIR, {recursive: true});
|
||||
}
|
||||
await mkdir(VESKTOP_SPLASH_DIR, {recursive: true});
|
||||
await copyFile(originalPath, destPath);
|
||||
|
||||
return imageName;
|
||||
});
|
||||
|
||||
handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count));
|
||||
|
||||
handle(IpcEvents.CLIPBOARD_COPY_IMAGE, async (_, buf: ArrayBuffer, src: string) => {
|
||||
|
|
|
@ -12,6 +12,8 @@ import { ICON_PATH, VIEW_DIR } from "shared/paths";
|
|||
import { Settings } from "./settings";
|
||||
|
||||
export function createSplashWindow(startMinimized = false) {
|
||||
const { splashBackground, splashColor, splashTheming, splashAnimationPath } = Settings.store;
|
||||
|
||||
const splash = new BrowserWindow({
|
||||
...SplashProps,
|
||||
icon: ICON_PATH,
|
||||
|
@ -20,8 +22,6 @@ export function createSplashWindow(startMinimized = false) {
|
|||
|
||||
splash.loadFile(join(VIEW_DIR, "splash.html"));
|
||||
|
||||
const { splashBackground, splashColor, splashTheming } = Settings.store;
|
||||
|
||||
if (splashTheming) {
|
||||
if (splashColor) {
|
||||
const semiTransparentSplashColor = splashColor.replace("rgb(", "rgba(").replace(")", ", 0.2)");
|
||||
|
@ -35,5 +35,17 @@ export function createSplashWindow(startMinimized = false) {
|
|||
}
|
||||
}
|
||||
|
||||
if (splashAnimationPath) {
|
||||
splash.webContents.executeJavaScript(`
|
||||
document.getElementById("animation").src = "splash-animation://img";
|
||||
`);
|
||||
}
|
||||
else {
|
||||
splash.webContents.insertCSS(`img {image-rendering: pixelated}`)
|
||||
splash.webContents.executeJavaScript(`
|
||||
document.getElementById("animation").src = "../shiggy.gif";
|
||||
`);
|
||||
}
|
||||
|
||||
return splash;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@ export const VesktopNative = {
|
|||
fileManager: {
|
||||
showItemInFolder: (path: string) => invoke<void>(IpcEvents.SHOW_ITEM_IN_FOLDER, path),
|
||||
getVencordDir: () => sendSync<string | undefined>(IpcEvents.GET_VENCORD_DIR),
|
||||
selectVencordDir: (value?: null) => invoke<"cancelled" | "invalid" | "ok">(IpcEvents.SELECT_VENCORD_DIR, value)
|
||||
selectVencordDir: (value?: null) => invoke<"cancelled" | "invalid" | "ok">(IpcEvents.SELECT_VENCORD_DIR, value),
|
||||
selectImagePath: () => invoke<"cancelled" | string>(IpcEvents.SELECT_IMAGE_PATH)
|
||||
},
|
||||
settings: {
|
||||
get: () => sendSync<Settings>(IpcEvents.GET_SETTINGS),
|
||||
|
|
55
src/renderer/components/settings/CustomSplashAnimation.tsx
Normal file
55
src/renderer/components/settings/CustomSplashAnimation.tsx
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0
|
||||
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
|
||||
* Copyright (c) 2023 Vendicated and Vencord contributors
|
||||
*/
|
||||
|
||||
import { Button, Forms } from "@vencord/types/webpack/common";
|
||||
|
||||
import { SettingsComponent } from "./Settings";
|
||||
|
||||
export const CustomSplashAnimation: SettingsComponent = ({ settings }) => {
|
||||
return (
|
||||
<>
|
||||
|
||||
<Forms.FormText>
|
||||
{settings.splashAnimationPath ? (
|
||||
<div style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "16px"
|
||||
}}>
|
||||
{/* adding the Math.random() here ensures that a new image is fetched when the user changes the path */}
|
||||
<img src={"splash-animation:///" + Math.random()} width="64px" height="64px"></img>
|
||||
<p>The custom splash animation is enabled.</p>
|
||||
</div>
|
||||
) : (
|
||||
"A custom splash animation is not set."
|
||||
)}
|
||||
</Forms.FormText>
|
||||
<div className="vcd-location-btns" style={{marginBottom: 20}}>
|
||||
<Button
|
||||
size={Button.Sizes.SMALL}
|
||||
onClick={async () => {
|
||||
const choice = await VesktopNative.fileManager.selectImagePath();
|
||||
if (choice === "cancelled") return;
|
||||
settings.splashAnimationPath = choice;
|
||||
}}
|
||||
>
|
||||
Change
|
||||
</Button>
|
||||
<Button
|
||||
size={Button.Sizes.SMALL}
|
||||
color={Button.Colors.RED}
|
||||
onClick={() => {
|
||||
//todo: delete the image after resetting the path?
|
||||
settings.splashAnimationPath = undefined
|
||||
}}
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -16,6 +16,7 @@ import { DiscordBranchPicker } from "./DiscordBranchPicker";
|
|||
import { NotificationBadgeToggle } from "./NotificationBadgeToggle";
|
||||
import { VencordLocationPicker } from "./VencordLocationPicker";
|
||||
import { WindowsTransparencyControls } from "./WindowsTransparencyControls";
|
||||
import { CustomSplashAnimation } from "./CustomSplashAnimation";
|
||||
|
||||
interface BooleanSetting {
|
||||
key: keyof typeof Settings.store;
|
||||
|
@ -118,6 +119,7 @@ const SettingsOptions: Record<string, Array<BooleanSetting | SettingsComponent>>
|
|||
defaultValue: false
|
||||
}
|
||||
],
|
||||
"Custom Splash Animation":[CustomSplashAnimation],
|
||||
"Vencord Location": [VencordLocationPicker]
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ export const enum IpcEvents {
|
|||
|
||||
GET_VENCORD_DIR = "VCD_GET_VENCORD_DIR",
|
||||
SELECT_VENCORD_DIR = "VCD_SELECT_VENCORD_DIR",
|
||||
SELECT_IMAGE_PATH= "VCD_SELECT_IMAGE_PATH",
|
||||
|
||||
UPDATER_GET_DATA = "VCD_UPDATER_GET_DATA",
|
||||
UPDATER_DOWNLOAD = "VCD_UPDATER_DOWNLOAD",
|
||||
|
|
1
src/shared/settings.d.ts
vendored
1
src/shared/settings.d.ts
vendored
|
@ -24,6 +24,7 @@ export interface Settings {
|
|||
|
||||
splashTheming?: boolean;
|
||||
splashColor?: string;
|
||||
splashAnimationPath?: string;
|
||||
splashBackground?: string;
|
||||
|
||||
spellCheckLanguages?: string[];
|
||||
|
|
|
@ -25,19 +25,15 @@
|
|||
img {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<img
|
||||
draggable="false"
|
||||
src="../shiggy.gif"
|
||||
alt="shiggy"
|
||||
role="presentation"
|
||||
/>
|
||||
<!-- the data url is here to ensure there isn't an empty frame before the image is loaded -->
|
||||
<img id="animation" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
|
||||
draggable="false" alt="animation" role="presentation" />
|
||||
<p>Loading Vesktop...</p>
|
||||
</div>
|
||||
</body>
|
Reference in a new issue