Merge overlays, move overlay to separate process (#44)

* refactor: merge two overlay offScreenBrowser into one

* Electron support for shared overlay

* Separate overlay into its own process

* fix: invalid overlay texture size

* Handle duplicate processes

* Remove logging

---------

Co-authored-by: pa <maplenagisa@gmail.com>
Co-authored-by: rs189 <35667100+rs189@users.noreply.github.com>
This commit is contained in:
Natsumi
2026-01-12 11:31:10 +13:00
committed by Natsumi
parent 9135adf6d1
commit d2fd205476
41 changed files with 1122 additions and 2108 deletions

View File

@@ -1,9 +1,6 @@
<template>
<div
id="x-app"
class="x-app x-app-type"
:class="{ background: appType === 'wrist' && config && config.backgroundEnabled }">
<template v-if="appType === 'wrist' && !vrState.isWristDisabled">
<div id="x-app" class="x-app x-app-type">
<div class="wrist" :class="{ background: config && config.backgroundEnabled }">
<div class="x-container" style="flex: 1">
<div class="x-friend-list" ref="list" style="color: #aaa">
<template v-if="config && config.minimalFeed">
@@ -1283,9 +1280,9 @@
<span style="display: inline-block">{{ t('vr.status.online') }} {{ onlineFriendCount }}</span>
<span style="display: inline-block; margin-left: 5px">{{ customInfo }}</span>
</div>
</template>
</div>
<!-- HMD Overlay -->
<template v-else-if="appType === 'hmd' && !vrState.isHmdDisabled">
<div class="hmd">
<svg class="np-progress-circle">
<circle
class="np-progress-circle-stroke"
@@ -1406,7 +1403,7 @@
d="M102.9,75l11.3-11.3c10.3-10.3,11.5-26.1,3.8-37.8l17.4-17.4L126.9,0l-17.4,17.4C97.9,9.7,82,11,71.8,21.2L60.5,32.5C102,74,60.8,32.9,102.9,75z"></path>
</svg>
</div>
</template>
</div>
</div>
</template>
@@ -1437,7 +1434,6 @@
const { t, locale } = useI18n();
const vrState = reactive({
appType: new URLSearchParams(window.location.search).has('wrist') ? 'wrist' : 'hmd',
appLanguage: 'en',
currentCulture: 'en-gb',
currentTime: new Date().toJSON(),
@@ -1513,10 +1509,8 @@
if (LINUX) {
updateVrElectronLoop();
}
if (vrState.appType === 'wrist') {
refreshCustomScript();
updateStatsLoop();
}
refreshCustomScript();
updateStatsLoop();
setDatetimeFormat();
nextTick(() => {
@@ -1614,25 +1608,17 @@
function nowPlayingUpdate(json) {
vrState.nowPlaying = JSON.parse(json);
if (vrState.appType === 'hmd') {
const circle = /** @type {SVGCircleElement | null} */ (
document.querySelector('.np-progress-circle-stroke')
);
const circle = /** @type {SVGCircleElement} */ (document.querySelector('.np-progress-circle-stroke'));
if (!circle) {
return;
}
if (vrState.lastLocation.progressPie && vrState.nowPlaying.percentage !== 0) {
circle.style.opacity = (0.5).toString();
const circumference = circle.getTotalLength();
circle.style.strokeDashoffset = (
circumference -
(vrState.nowPlaying.percentage / 100) * circumference
).toString();
} else {
circle.style.opacity = '0';
}
if (vrState.lastLocation.progressPie && vrState.nowPlaying.percentage !== 0) {
circle.style.opacity = (0.5).toString();
const circumference = circle.getTotalLength();
circle.style.strokeDashoffset = (
circumference -
(vrState.nowPlaying.percentage / 100) * circumference
).toString();
} else {
circle.style.opacity = '0';
}
updateFeedLength();
}
@@ -1647,7 +1633,7 @@
}
function updateFeedLength() {
if (vrState.appType === 'hmd' || vrState.wristFeed.length === 0) {
if (vrState.wristFeed.length === 0) {
return;
}
let length = 16;
@@ -1787,36 +1773,19 @@
async function updateVrElectronLoop() {
try {
if (vrState.appType === 'wrist') {
const wristOverlayQueue = await AppApiVr.GetExecuteVrFeedFunctionQueue();
if (wristOverlayQueue) {
wristOverlayQueue.forEach((item) => {
// item[0] is the function name, item[1] is already an object
const fullFunctionName = item[0];
const jsonArg = item[1];
const overlayQueue = await AppApiVr.GetExecuteVrOverlayFunctionQueue();
if (overlayQueue) {
overlayQueue.forEach((item) => {
// item[0] is the function name, item[1] is already an object
const fullFunctionName = item[0];
const jsonArg = item[1];
if (typeof window.$vr === 'object' && typeof window.$vr[fullFunctionName] === 'function') {
window.$vr[fullFunctionName](jsonArg);
} else {
console.error(`$vr.${fullFunctionName} is not defined or is not a function`);
}
});
}
} else {
const hmdOverlayQueue = await AppApiVr.GetExecuteVrOverlayFunctionQueue();
if (hmdOverlayQueue) {
hmdOverlayQueue.forEach((item) => {
// item[0] is the function name, item[1] is already an object
const fullFunctionName = item[0];
const jsonArg = item[1];
if (typeof window.$vr === 'object' && typeof window.$vr[fullFunctionName] === 'function') {
window.$vr[fullFunctionName](jsonArg);
} else {
console.error(`$vr.${fullFunctionName} is not defined or is not a function`);
}
});
}
if (typeof window.$vr === 'object' && typeof window.$vr[fullFunctionName] === 'function') {
window.$vr[fullFunctionName](jsonArg);
} else {
console.error(`$vr.${fullFunctionName} is not defined or is not a function`);
}
});
}
} catch (err) {
console.error(err);
@@ -2126,7 +2095,6 @@
}
const {
appType,
config,
wristFeed,
devices,

View File

@@ -240,6 +240,30 @@ button {
.x-app-type {
color: #fff;
width: 1024px;
height: 1536px;
position: relative;
overflow: hidden;
}
.wrist {
position: absolute;
top: 0px;
left: 0;
width: 512px;
height: 512px;
z-index: 20;
display: flex;
flex-direction: column;
}
.hmd {
position: absolute;
top: 512px;
left: 0;
width: 1024px;
height: 1024px;
z-index: 10;
}
.background {