16 Commits

Author SHA1 Message Date
Vendicated
cc62903b9c bump to v0.4.2 2023-10-27 00:43:02 +02:00
Vendicated
b17370cc7b add arm64 venmic binary 2023-10-27 00:42:50 +02:00
Vendicated
886d02f7c3 screenaudio: show better error if glibcxx too old 2023-10-27 00:27:35 +02:00
Nico
0cad71f6ae fix: adjust hiding download button to new discord update (#176) 2023-10-26 23:23:31 +02:00
Vendicated
b5eac15b42 Use correct OS in U-Agent ~ ~should fix captchas 2023-10-26 22:07:35 +02:00
rini
19c3112d52 fix spellcheck patch (#169) 2023-10-25 20:57:08 +02:00
Vendicated
1c308d0e2c Bump to v0.4.1 2023-10-25 00:32:06 +02:00
Vendicated
7f6db5eeda Linux ScreenAudio: Remove Duplicates 2023-10-25 00:31:53 +02:00
Vendicated
10b38e5b41 make updater window close button close proper window 2023-10-25 00:30:42 +02:00
wearr
28282d1d76 Use local shiggy gif for splash (#157)
Co-authored-by: wearrrrr <contact@wearr.dev>
Co-authored-by: V <vendicated@riseup.net>
2023-10-25 00:25:17 +02:00
MiMillieuh
e1512b72f4 Fix : VM class for AppImage has broken Dekstop integrations (#160) 2023-10-25 00:24:49 +02:00
AAGaming
46a2314173 fix turnary soup in main window options (#164) 2023-10-25 00:24:37 +02:00
Vendicated
e6dc026708 Fix for latest canary 2023-10-24 23:12:22 +02:00
Lewis Crichton
cac307d1fc ci: pin wgr to new version (#163) 2023-10-23 17:44:54 +00:00
Ryan Cao
4b8f374856 feat: allow disabling updates check (#155)
Co-authored-by: V <vendicated@riseup.net>
2023-10-22 17:10:25 +02:00
Jack
e6cc11fc0e Build arm64 Linux packages (#151) 2023-10-22 16:53:58 +02:00
20 changed files with 177 additions and 79 deletions

View File

@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Submit package to Winget Community Repo
uses: vedantmgoyal2009/winget-releaser@52ef3f3028ed79a9606d7678d0a88d295bc0c690 # v2
uses: vedantmgoyal2009/winget-releaser@e68d386d5d6a1cef8cb0fb5e62b77ebcb83e7d58 # v2
with:
identifier: Vencord.Vesktop
token: ${{ secrets.WINGET_PAT }}

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@ node_modules
.env
.DS_Store
.idea/
.pnpm-store/

View File

@@ -1,6 +1,6 @@
{
"name": "VencordDesktop",
"version": "0.4.0",
"version": "0.4.2",
"private": true,
"description": "",
"keywords": [],
@@ -26,7 +26,7 @@
"arrpc": "github:OpenAsar/arrpc#89f4da610ccfac93f461826a446a17cd3b23953d"
},
"optionalDependencies": {
"@vencord/venmic": "^1.4.0"
"@vencord/venmic": "^1.6.0"
},
"devDependencies": {
"@fal-works/esbuild-plugin-global-externals": "^2.1.2",
@@ -73,10 +73,34 @@
"category": "Network",
"maintainer": "vendicated+vesktop@riseup.net",
"target": [
"deb",
"tar.gz",
"rpm",
"AppImage"
{
"target": "deb",
"arch": [
"x64",
"arm64"
]
},
{
"target": "tar.gz",
"arch": [
"x64",
"arm64"
]
},
{
"target": "rpm",
"arch": [
"x64",
"arm64"
]
},
{
"target": "AppImage",
"arch": [
"x64",
"arm64"
]
}
],
"desktop": {
"Name": "Vesktop",
@@ -84,7 +108,8 @@
"Type": "Application",
"Categories": "Network;InstantMessaging;Chat;",
"Keywords": "discord;vencord;electron;chat;",
"WMClass": "VencordDesktop"
"WMClass": "VencordDesktop",
"StartupWMClass": "VencordDesktop"
}
},
"mac": {

21
pnpm-lock.yaml generated
View File

@@ -11,8 +11,8 @@ dependencies:
optionalDependencies:
'@vencord/venmic':
specifier: ^1.4.0
version: 1.4.0
specifier: ^1.6.0
version: 1.6.0
devDependencies:
'@fal-works/esbuild-plugin-global-externals':
@@ -53,7 +53,7 @@ devDependencies:
version: 9.0.0(eslint@8.51.0)
eslint-import-resolver-alias:
specifier: ^1.1.2
version: 1.1.2(eslint-plugin-import@2.28.1)
version: 1.1.2(eslint-plugin-import@2.29.0)
eslint-plugin-license-header:
specifier: ^0.6.0
version: 0.6.0
@@ -960,8 +960,8 @@ packages:
type-fest: 3.13.1
dev: true
/@vencord/venmic@1.4.0:
resolution: {integrity: sha512-rGmO4oCLrIVSLwhRH4Qib8XWFW6hcELZhSR3+NeXVV4nwVf302g1FwhUaQXk9B//HQOieCsORf2o5e2vEmBA8w==}
/@vencord/venmic@1.6.0:
resolution: {integrity: sha512-Agh5+gDiHpqsSrrxyazeU+1JmZD286QoKj41t/omw6EmtSS8EPiENQSn7eXmXt/ooSEfa9qoXEG+Hn6hXb3rvw==}
engines: {node: '>=14.15'}
os: [linux]
requiresBuild: true
@@ -2040,13 +2040,13 @@ packages:
eslint: 8.51.0
dev: true
/eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.28.1):
/eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.29.0):
resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==}
engines: {node: '>= 4'}
peerDependencies:
eslint-plugin-import: '>=1.4.0'
dependencies:
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)
eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)
dev: true
/eslint-import-resolver-node@0.3.9:
@@ -2088,8 +2088,8 @@ packages:
- supports-color
dev: true
/eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.7.5)(eslint@8.51.0):
resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==}
/eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.7.5)(eslint@8.51.0):
resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==}
engines: {node: '>=4'}
peerDependencies:
'@typescript-eslint/parser': '*'
@@ -2108,7 +2108,7 @@ packages:
eslint: 8.51.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-node@0.3.9)(eslint@8.51.0)
has: 1.0.4
hasown: 2.0.0
is-core-module: 2.13.1
is-glob: 4.0.3
minimatch: 3.1.2
@@ -2780,6 +2780,7 @@ packages:
/has@1.0.4:
resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==}
engines: {node: '>= 0.4.0'}
requiresBuild: true
dev: true
/hasown@2.0.0:

View File

@@ -34,12 +34,23 @@ async function createContext(options: BuildOptions) {
contexts.push(await context(options));
}
await Promise.all([
process.platform === "linux" &&
async function copyVenmic() {
if (process.platform !== "linux") return;
return Promise.all([
copyFile(
"./node_modules/@vencord/venmic/prebuilds/venmic-addon-linux-x64/node-napi-v7.node",
"./static/dist/venmic.node"
).catch(() => console.warn("Failed to copy venmic. Building without venmic support")),
"./static/dist/venmic-x64.node"
),
copyFile(
"./node_modules/@vencord/venmic/prebuilds/venmic-addon-linux-arm64/node-napi-v7.node",
"./static/dist/venmic-arm64.node"
)
]).catch(() => console.warn("Failed to copy venmic. Building without venmic support"));
}
await Promise.all([
copyVenmic(),
createContext({
...NodeCommonOpts,
entryPoints: ["src/main/index.ts"],

View File

@@ -25,3 +25,12 @@ export const MIN_WIDTH = 940;
export const MIN_HEIGHT = 500;
export const DEFAULT_WIDTH = 1280;
export const DEFAULT_HEIGHT = 720;
const UserAgents = {
darwin: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
windows:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
};
export const UserAgent = UserAgents[process.platform] || UserAgents.windows;

View File

@@ -7,7 +7,7 @@
if (process.platform === "linux") import("./virtmic");
import { execFile } from "child_process";
import { app, dialog, RelaunchOptions, session, shell } from "electron";
import { app, BrowserWindow, dialog, RelaunchOptions, session, shell } from "electron";
import { mkdirSync, readFileSync, watch } from "fs";
import { open, readFile } from "fs/promises";
import { release } from "os";
@@ -71,7 +71,7 @@ handle(IpcEvents.FOCUS, () => {
});
handle(IpcEvents.CLOSE, e => {
mainWin.close();
(BrowserWindow.fromWebContents(e.sender) ?? e.sender).close();
});
handle(IpcEvents.MINIMIZE, e => {

View File

@@ -24,7 +24,15 @@ import type { SettingsStore } from "shared/utils/SettingsStore";
import { ICON_PATH } from "../shared/paths";
import { createAboutWindow } from "./about";
import { initArRPC } from "./arrpc";
import { DATA_DIR, DEFAULT_HEIGHT, DEFAULT_WIDTH, MIN_HEIGHT, MIN_WIDTH, VENCORD_FILES_DIR } from "./constants";
import {
DATA_DIR,
DEFAULT_HEIGHT,
DEFAULT_WIDTH,
MIN_HEIGHT,
MIN_WIDTH,
UserAgent,
VENCORD_FILES_DIR
} from "./constants";
import { Settings, VencordSettings } from "./settings";
import { createSplashWindow } from "./splash";
import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally";
@@ -278,6 +286,28 @@ function getWindowBoundsOptions(): BrowserWindowConstructorOptions {
return options;
}
function getDarwinOptions(): BrowserWindowConstructorOptions {
const options = {
titleBarStyle: "hiddenInset"
} as BrowserWindowConstructorOptions;
const { splashTheming, splashBackground } = Settings.store;
const { macosTranslucency } = VencordSettings.store;
if (macosTranslucency) {
options.vibrancy = "sidebar";
options.backgroundColor = "#ffffff00";
} else {
if (splashTheming) {
options.backgroundColor = splashBackground;
} else {
options.backgroundColor = nativeTheme.shouldUseDarkColors ? "#313338" : "#ffffff";
}
}
return options;
}
function initWindowBoundsListeners(win: BrowserWindow) {
const saveState = () => {
Settings.store.maximized = win.isMaximized();
@@ -342,10 +372,9 @@ function createMainWindow() {
removeSettingsListeners();
removeVencordSettingsListeners();
const { staticTitle, transparencyOption, splashTheming, splashBackground, enableMenu, discordWindowsTitleBar } =
Settings.store;
const { staticTitle, transparencyOption, enableMenu, discordWindowsTitleBar } = Settings.store;
const { frameless, macosTranslucency } = VencordSettings.store;
const { frameless } = VencordSettings.store;
const noFrame = frameless === true || (process.platform === "win32" && discordWindowsTitleBar === true);
@@ -361,28 +390,14 @@ function createMainWindow() {
},
icon: ICON_PATH,
frame: !noFrame,
...(transparencyOption && transparencyOption !== "none"
? {
backgroundColor: "#00000000",
backgroundMaterial: transparencyOption,
transparent: true
}
: {}),
...(staticTitle ? { title: "Vesktop" } : {}),
...(macosTranslucency
? {
vibrancy: "sidebar",
backgroundColor: "#ffffff00"
}
: {
backgroundColor: splashTheming
? splashBackground
: nativeTheme.shouldUseDarkColors
? "#313338"
: "#ffffff",
transparent: false
}),
...(process.platform === "darwin" ? { titleBarStyle: "hiddenInset" } : {}),
...(transparencyOption &&
transparencyOption !== "none" && {
backgroundColor: "#00000000",
backgroundMaterial: transparencyOption,
transparent: true
}),
...(staticTitle && { title: "Vesktop" }),
...(process.platform === "darwin" && getDarwinOptions()),
...getWindowBoundsOptions(),
autoHideMenuBar: enableMenu
}));
@@ -409,9 +424,7 @@ function createMainWindow() {
initSettingsListeners(win);
initSpellCheck(win);
win.webContents.setUserAgent(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
);
win.webContents.setUserAgent(UserAgent);
const subdomain =
Settings.store.discordBranch === "canary" || Settings.store.discordBranch === "ptb"

View File

@@ -11,6 +11,7 @@ import { STATIC_DIR } from "shared/paths";
let initialized = false;
let patchBay: import("@vencord/venmic").PatchBay | undefined;
let isGlibcxxToOld = false;
function getRendererAudioServicePid() {
return (
@@ -25,10 +26,13 @@ function obtainVenmic() {
if (!initialized) {
initialized = true;
try {
const { PatchBay } = require(join(STATIC_DIR, "dist/venmic.node")) as typeof import("@vencord/venmic");
const { PatchBay } = require(
join(STATIC_DIR, `dist/venmic-${process.arch}.node`)
) as typeof import("@vencord/venmic");
patchBay = new PatchBay();
} catch (e) {
} catch (e: any) {
console.error("Failed to initialise venmic. Make sure you're using pipewire", e);
isGlibcxxToOld = (e?.stack || e?.message || "").toLowerCase().includes("glibc");
}
}
@@ -37,10 +41,14 @@ function obtainVenmic() {
ipcMain.handle(IpcEvents.VIRT_MIC_LIST, () => {
const audioPid = getRendererAudioServicePid();
return obtainVenmic()
const list = obtainVenmic()
?.list()
.filter(s => s["application.process.id"] !== audioPid)
.map(s => s["application.name"]);
return list
? { ok: true, targets: [...new Set(list)] } // Remove duplicates
: { ok: false, isGlibcxxToOld };
});
ipcMain.handle(

View File

@@ -61,7 +61,8 @@ export const VesktopNative = {
},
/** only available on Linux. */
virtmic: {
list: () => invoke<string[] | null>(IpcEvents.VIRT_MIC_LIST),
list: () =>
invoke<{ ok: false; isGlibcxxToOld: boolean } | { ok: true; targets: string[] }>(IpcEvents.VIRT_MIC_LIST),
start: (target: string) => invoke<void>(IpcEvents.VIRT_MIC_START, target),
startSystem: () => invoke<void>(IpcEvents.VIRT_MIC_START_SYSTEM),
stop: () => invoke<void>(IpcEvents.VIRT_MIC_STOP)

View File

@@ -15,15 +15,19 @@ let NotificationSettingsStore: any;
export function setBadge() {
if (Settings.store.appBadge === false) return;
const mentionCount = GuildReadStateStore.getTotalMentionCount();
const pendingRequests = RelationshipStore.getPendingCount();
const hasUnread = GuildReadStateStore.hasAnyUnread();
const disableUnreadBadge = NotificationSettingsStore.getDisableUnreadBadge();
try {
const mentionCount = GuildReadStateStore.getTotalMentionCount();
const pendingRequests = RelationshipStore.getPendingCount();
const hasUnread = GuildReadStateStore.hasAnyUnread();
const disableUnreadBadge = NotificationSettingsStore.getDisableUnreadBadge();
let totalCount = mentionCount + pendingRequests;
if (!totalCount && hasUnread && !disableUnreadBadge) totalCount = -1;
let totalCount = mentionCount + pendingRequests;
if (!totalCount && hasUnread && !disableUnreadBadge) totalCount = -1;
VesktopNative.app.setBadgeCount(totalCount);
VesktopNative.app.setBadgeCount(totalCount);
} catch (e) {
console.error(e);
}
}
let toFind = 3;

View File

@@ -240,19 +240,30 @@ function AudioSourcePickerLinux({
audioSource?: string;
setAudioSource(s: string): void;
}) {
const [sources, _, loading] = useAwaiter(() => VesktopNative.virtmic.list(), { fallbackValue: [] });
const allSources = sources ? ["None", "Entire System", ...sources] : null;
const [sources, _, loading] = useAwaiter(() => VesktopNative.virtmic.list(), {
fallbackValue: { ok: true, targets: [] }
});
const allSources = sources.ok ? ["None", "Entire System", ...sources.targets] : null;
return (
<section>
<Forms.FormTitle>Audio</Forms.FormTitle>
{loading && <Forms.FormTitle>Loading Audio sources...</Forms.FormTitle>}
{allSources === null && (
<Forms.FormTitle>
Failed to retrieve Audio Sources. If you would like to stream with Audio, make sure you're using
Pipewire, not Pulseaudio
</Forms.FormTitle>
)}
{!sources.ok &&
(sources.isGlibcxxToOld ? (
<Forms.FormText>
Failed to retrieve Audio Sources because your c++ library is too old to run venmic. If you would
like to stream with Audio, see{" "}
<a href="https://gist.github.com/Vendicated/b655044ffbb16b2716095a448c6d827a" target="_blank">
this guide
</a>
</Forms.FormText>
) : (
<Forms.FormText>
Failed to retrieve Audio Sources. If you would like to stream with Audio, make sure you're using
Pipewire, not Pulseaudio
</Forms.FormText>
))}
{allSources && (
<Select

View File

@@ -47,7 +47,8 @@ export default function SettingsUi() {
"openLinksWithElectron",
"Open Links in app (experimental)",
"Opens links in a new Vesktop window instead of your web browser"
]
],
["checkUpdates", "Check for updates", "Automatically check for Vesktop updates", true]
];
const switches = allSwitches.filter(isTruthy);

View File

@@ -8,7 +8,7 @@ import "./hideGarbage.css";
import { waitFor } from "@vencord/types/webpack";
import { isFirstRun, localStorage } from "./utils";
import { isFirstRun, isWindows, localStorage } from "./utils";
// Make clicking Notifications focus the window
const originalSetOnClick = Object.getOwnPropertyDescriptor(Notification.prototype, "onclick")!.set!;
@@ -31,3 +31,14 @@ if (isFirstRun) {
m.setDesktopType("all");
});
}
// FIXME: Remove eventually.
// Originally, Vencord always used a Windows user agent. This seems to cause captchas
// Now, we use a platform specific UA - HOWEVER, discord FOR SOME REASON????? caches
// device props in localStorage. This code fixes their cache to properly update the platform in SuperProps
if (!isWindows)
try {
const deviceProperties = localStorage.getItem("deviceProperties");
if (deviceProperties && JSON.parse(deviceProperties).os === "Windows")
localStorage.removeItem("deviceProperties");
} catch {}

View File

@@ -1,5 +1,5 @@
/* Download Desktop button in guilds list */
[class|=listItem]:has([data-list-item-id=guildsnav___app-download-button]),
[class|=listItem]:has(+ [class|=listItem] [data-list-item-id=guildsnav___app-download-button]) {
[class^=listItem_]:has([data-list-item-id=guildsnav___app-download-button]),
[class^=listItem_]:has(+ [class^=listItem_] [data-list-item-id=guildsnav___app-download-button]) {
display: none;
}

View File

@@ -22,7 +22,7 @@ addPatch({
find: ".enableSpellCheck)",
replacement: {
// if (isDesktop) { DiscordNative.onSpellcheck(openMenu(props)) } else { e.preventDefault(); openMenu(props) }
match: /else\{(.{1,3})\.preventDefault\(\);(.{1,3}\(.{1,3}\))\}(?<=:(.{1,3})\.enableSpellCheck\).+?)/,
match: /else (.{1,3})\.preventDefault\(\),(.{1,3}\(.{1,3}\))(?<=:(.{1,3})\.enableSpellCheck\).+?)/,
// ... else { $self.onSlateContext(() => openMenu(props)) }
replace: "else {$self.onSlateContext($1, $3?.enableSpellCheck, () => $2)}"
}

View File

@@ -24,6 +24,7 @@ export interface Settings {
windowBounds?: Rectangle;
disableMinSize?: boolean;
checkUpdates?: boolean;
skippedUpdate?: string;
firstLaunch?: boolean;

View File

@@ -77,7 +77,8 @@ function isOutdated(oldVersion: string, newVersion: string) {
}
export async function checkUpdates() {
// if (IS_DEV) return;
if (Settings.store.checkUpdates === false) return;
try {
const raw = await githubGet("/repos/Vencord/Vesktop/releases/latest");
const data = JSON.parse(raw.toString("utf-8")) as ReleaseData;

BIN
static/shiggy.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -32,7 +32,7 @@
<div class="wrapper">
<img
draggable="false"
src="https://cdn.discordapp.com/emojis/1024751291504791654.gif?size=512"
src="../shiggy.gif"
alt="shiggy"
role="presentation"
/>