Compare commits

...

2 commits
v1.0.5 ... main

Author SHA1 Message Date
MiTHRAL
1e3f165857 v1.0.7
All checks were successful
Build and Release Sanctum / Build App (push) Successful in 1m55s
2026-05-05 20:50:53 -04:00
MiTHRAL
8a9d621456 v1.0.6
Some checks failed
Build and Release Sanctum / Build App (push) Has been cancelled
2026-05-05 20:48:42 -04:00
4 changed files with 49 additions and 7 deletions

View file

@ -60,6 +60,7 @@
let globalObserver = null; let globalObserver = null;
let refreshTimer = null; let refreshTimer = null;
let lastVoiceState = null; let lastVoiceState = null;
let lastMemberIdentityKey = "";
let leaveWatchdog = null; let leaveWatchdog = null;
const recentRowActivity = new Map(); const recentRowActivity = new Map();
@ -87,6 +88,7 @@
leaveWatchdog = null; leaveWatchdog = null;
recentRowActivity.clear(); recentRowActivity.clear();
lastVoiceState = null; lastVoiceState = null;
lastMemberIdentityKey = "";
playLeave(); playLeave();
console.debug("[VCSounds] self left"); console.debug("[VCSounds] self left");
const overlayApi = window.native?.overlay; const overlayApi = window.native?.overlay;
@ -508,6 +510,18 @@
}; };
} }
function memberIdentityKey(members) {
return members
.map((member) =>
[
String(member?.name || "").trim().toLowerCase(),
String(member?.avatarUrl || "").trim().toLowerCase(),
].join(":"),
)
.sort()
.join("|");
}
function publishVoiceState() { function publishVoiceState() {
const overlayApi = window.native?.overlay; const overlayApi = window.native?.overlay;
if (!overlayApi || typeof overlayApi.setVoiceState !== "function") return; if (!overlayApi || typeof overlayApi.setVoiceState !== "function") return;
@ -515,7 +529,28 @@
pruneRowActivity(); pruneRowActivity();
const next = collectVoiceState(); const next = collectVoiceState();
const voiceState = inVoice ? next : null; const voiceState = inVoice ? next : null;
const nextMemberKey = memberIdentityKey(next.members);
const nextKey = JSON.stringify(voiceState); const nextKey = JSON.stringify(voiceState);
const memberChanged = nextMemberKey !== lastMemberIdentityKey;
if (memberChanged && inVoice && !initialising && lastMemberIdentityKey) {
const previousMembers = new Set(
lastMemberIdentityKey
.split("|")
.map((entry) => entry.trim())
.filter(Boolean),
);
const currentMembers = new Set(
nextMemberKey
.split("|")
.map((entry) => entry.trim())
.filter(Boolean),
);
const added = [...currentMembers].some((entry) => !previousMembers.has(entry));
const removed = [...previousMembers].some((entry) => !currentMembers.has(entry));
if (added) playJoin();
if (removed) playLeave();
}
lastMemberIdentityKey = nextMemberKey;
if (nextKey === lastVoiceState) return; if (nextKey === lastVoiceState) return;
lastVoiceState = nextKey; lastVoiceState = nextKey;

View file

@ -27,9 +27,9 @@
<control>pointing</control> <control>pointing</control>
</supports> </supports>
<releases> <releases>
<release date="2026-05-05" version="1.0.5"> <release date="2026-05-05" version="1.0.7">
<description> <description>
<p>Gameplay overlay and improved game presence support.</p> <p>Fixed a main-process bootstrap race and improved VC sounds / game presence behavior.</p>
</description> </description>
</release> </release>
<release date="2026-04-22" version="1.0.0"> <release date="2026-04-22" version="1.0.0">

View file

@ -1,8 +1,8 @@
{ {
"name": "sanctum", "name": "sanctum",
"productName": "Sanctum", "productName": "Sanctum",
"version": "1.0.5", "version": "1.0.7",
"aviaVersion": "1.0.5", "aviaVersion": "1.0.7",
"main": ".vite/build/main.js", "main": ".vite/build/main.js",
"repository": "https://git.mithraic.cloud/ad3laid3/sanctum", "repository": "https://git.mithraic.cloud/ad3laid3/sanctum",
"scripts": { "scripts": {

View file

@ -46,8 +46,12 @@ const acquiredLock = app.requestSingleInstanceLock();
const loadInject = () => { const loadInject = () => {
if (!mainWindow) return; if (!mainWindow) return;
mainWindow.webContents.on("dom-ready", async () => { const wc = mainWindow.webContents;
wc.removeAllListeners("dom-ready");
wc.once("dom-ready", async () => {
try { try {
if (mainWindow.isDestroyed() || wc.isDestroyed()) return;
const builtInLocalPlugins = [ const builtInLocalPlugins = [
{ {
id: "sanctum-vcsounds", id: "sanctum-vcsounds",
@ -58,13 +62,15 @@ const loadInject = () => {
}, },
]; ];
await mainWindow.webContents.executeJavaScript( await wc.executeJavaScript(
`window.__SANCTUM_BUILTIN_LOCAL_PLUGINS__ = ${JSON.stringify( `window.__SANCTUM_BUILTIN_LOCAL_PLUGINS__ = ${JSON.stringify(
builtInLocalPlugins, builtInLocalPlugins,
)};`, )};`,
true, true,
); );
if (mainWindow.isDestroyed() || wc.isDestroyed()) return;
const plugins: string[] = [ const plugins: string[] = [
"inject.js", "inject.js",
"LocalPlugins.js", "LocalPlugins.js",
@ -84,9 +90,10 @@ const loadInject = () => {
]; ];
for (const plugin of plugins) { for (const plugin of plugins) {
if (mainWindow.isDestroyed() || wc.isDestroyed()) return;
const pluginPath: string = path.join(__dirname, plugin); const pluginPath: string = path.join(__dirname, plugin);
const pluginCode: string = fs.readFileSync(pluginPath, "utf8"); const pluginCode: string = fs.readFileSync(pluginPath, "utf8");
await mainWindow.webContents.executeJavaScript(pluginCode, true); await wc.executeJavaScript(pluginCode, true);
} }
} catch { } catch {
/* empty */ /* empty */