Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option for custom startup animations #355

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
50d2b71
add option to disable the splash animation
ading2210 Jan 22, 2024
c18e0c2
reduce size of splash screen when animation is disabled
ading2210 Jan 22, 2024
454efff
add setting for custom splash animations
ading2210 Jan 22, 2024
1a828bf
avoid showing unloaded splash image
ading2210 Jan 22, 2024
e962e34
remove debug console.log
ading2210 Jan 23, 2024
9ff6653
Merge branch 'Vencord:main' into main
ading2210 Jan 24, 2024
f7da64a
don't put file path in custom url protocol
ading2210 Jan 24, 2024
c8b93fe
don't use deprecated registerFileProtocol
ading2210 Jan 24, 2024
7e733bf
Merge branch 'Vencord:main' into main
ading2210 Jan 29, 2024
804858f
add upstream changes
sz6084 May 8, 2024
0451ddf
Merge remote-tracking branch 'upstream/main'
ading2210 May 8, 2024
e6467ea
remove unrelated edit
ading2210 May 9, 2024
0a96d9e
Merge branch 'Vencord:main' into main
sz6084 May 12, 2024
2a3f158
Merge branch 'Vencord:main' into main
sz6084 May 18, 2024
9c0b22d
Merge branch 'Vencord:main' into main
sz6084 May 29, 2024
80e0fb7
Merge remote-tracking branch 'upstream/main'
ading2210 Jul 19, 2024
209d4cd
add splash animation preview in the vesktop settings
ading2210 Jul 19, 2024
3822fb1
fix preview image not updating when animation path is changed
ading2210 Jul 25, 2024
466488c
copy file to vesktop folder instead of storing full path
ading2210 Jul 25, 2024
415aa19
fix rmdir error if splash dir was previously unset
ading2210 Jul 26, 2024
d8248c8
Merge branch 'Vencord:main' into main
sz6084 Aug 29, 2024
4ac701f
Merge branch 'Vencord:main' into main
sz6084 Oct 7, 2024
17739bd
Merge branch 'main' into main
sz6084 Nov 6, 2024
85ec629
Merge branch 'Vencord:main' into main
sz6084 Dec 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 33 additions & 2 deletions src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -83,6 +84,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();

Expand Down
32 changes: 28 additions & 4 deletions src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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) => {
Expand Down
16 changes: 14 additions & 2 deletions src/main/splash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)");
Expand All @@ -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;
}
3 changes: 2 additions & 1 deletion src/preload/VesktopNative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/ScreenSharePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -801,4 +801,4 @@ function ModalComponent({
</Modals.ModalFooter>
</Modals.ModalRoot>
);
}
}
55 changes: 55 additions & 0 deletions src/renderer/components/settings/CustomSplashAnimation.tsx
Original file line number Diff line number Diff line change
@@ -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>

</>
);
};
2 changes: 2 additions & 0 deletions src/renderer/components/settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -118,6 +119,7 @@ const SettingsOptions: Record<string, Array<BooleanSetting | SettingsComponent>>
defaultValue: false
}
],
"Custom Splash Animation":[CustomSplashAnimation],
"Vencord Location": [VencordLocationPicker]
};

Expand Down
1 change: 1 addition & 0 deletions src/shared/IpcEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions src/shared/settings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface Settings {

splashTheming?: boolean;
splashColor?: string;
splashAnimationPath?: string;
splashBackground?: string;

spellCheckLanguages?: string[];
Expand Down
12 changes: 4 additions & 8 deletions static/views/splash.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,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>
</body>