improve vr ui

This commit is contained in:
pa
2026-03-16 01:12:04 +09:00
parent 63be5d2f7a
commit 7c3af2ba6f
2 changed files with 167 additions and 49 deletions

View File

@@ -2,7 +2,7 @@
<div id="x-app" class="flex w-screen h-screen overflow-hidden cursor-default x-app-type"> <div id="x-app" class="flex w-screen h-screen overflow-hidden cursor-default x-app-type">
<div class="wrist" :class="{ background: config && config.backgroundEnabled }"> <div class="wrist" :class="{ background: config && config.backgroundEnabled }">
<div class="x-container" style="flex: 1"> <div class="x-container" style="flex: 1">
<div class="x-friend-list" ref="list" style="color: #aaa"> <div class="x-friend-list" ref="list" style="color: var(--vr-text-secondary)">
<template v-if="config && config.minimalFeed"> <template v-if="config && config.minimalFeed">
<template <template
v-for="(feed, index) in wristFeed" v-for="(feed, index) in wristFeed"
@@ -637,7 +637,7 @@
<span class="extra flex items-center"> <span class="extra flex items-center">
<span class="time">{{ formatDate(feed.created_at) }}</span> <span class="time">{{ formatDate(feed.created_at) }}</span>
<span class="name" v-text="feed.displayName"></span> <span class="name" v-text="feed.displayName"></span>
<span style="margin-left: 5px; margin-right: 5px">has logged in</span> <span class="vr-mx">has logged in</span>
<template v-if="feed.worldName"> <template v-if="feed.worldName">
to to
<VrLocation <VrLocation
@@ -736,7 +736,7 @@
class="name" class="name"
v-text="feed.displayName" v-text="feed.displayName"
:style="{ color: feed.tagColour }"></span> :style="{ color: feed.tagColour }"></span>
<span style="margin-left: 5px; margin-right: 5px">changed video to</span> <span class="vr-mx">changed video to</span>
<template v-if="feed.videoName"> <template v-if="feed.videoName">
<span v-text="feed.videoName"></span> <span v-text="feed.videoName"></span>
</template> </template>
@@ -991,7 +991,7 @@
class="name" class="name"
v-text="feed.displayName" v-text="feed.displayName"
:style="{ color: feed.tagColour }"></span> :style="{ color: feed.tagColour }"></span>
<span style="margin-left: 5px; margin-right: 5px">changed into avatar</span> <span class="vr-mx">changed into avatar</span>
<template v-if="feed.releaseStatus === 'public'"> <template v-if="feed.releaseStatus === 'public'">
<i class="x-user-status online"></i> <i class="x-user-status online"></i>
</template> </template>
@@ -1149,7 +1149,7 @@
</template> </template>
</div> </div>
</div> </div>
<div class="x-containerbottom"> <div v-if="devices.length" class="x-containerbottom">
<div style="display: flex; flex-direction: row; flex-wrap: wrap"> <div style="display: flex; flex-direction: row; flex-wrap: wrap">
<div <div
class="tracker-container" class="tracker-container"
@@ -1298,8 +1298,8 @@
<span v-if="feed.isMaster">👑</span><span v-if="feed.isModerator"></span <span v-if="feed.isMaster">👑</span><span v-if="feed.isModerator"></span
><strong class="name" v-text="feed.displayName" :style="{ color: feed.colour }"></strong> ><strong class="name" v-text="feed.displayName" :style="{ color: feed.colour }"></strong>
<template v-if="feed.type === 'ChangeAvatar'"> <template v-if="feed.type === 'ChangeAvatar'">
<span style="margin-left: 10px; color: #a3a3a3">ChangeAvatar</span> <span style="margin-left: 10px; color: var(--vr-text-secondary)">ChangeAvatar</span>
<span v-if="!feed.inCache" style="color: #aaa; margin-left: 10px" <span v-if="!feed.inCache" style="color: var(--vr-text-muted); margin-left: 10px"
><Loader2 class="is-loading inline-block h-4 w-4" /> ><Loader2 class="is-loading inline-block h-4 w-4" />
</span> </span>
<span v-text="feed.avatar.name" style="margin-left: 10px"></span> <span v-text="feed.avatar.name" style="margin-left: 10px"></span>
@@ -1310,12 +1310,12 @@
> >
<span <span
v-else-if="feed.avatar.releaseStatus === 'private'" v-else-if="feed.avatar.releaseStatus === 'private'"
style="margin-left: 10px; color: #e6a23c" style="margin-left: 10px; color: var(--status-askme)"
>(Private)</span >(Private)</span
> >
</template> </template>
<template v-else-if="feed.type === 'ChangeStatus'"> <template v-else-if="feed.type === 'ChangeStatus'">
<span style="margin-left: 10px; color: #a3a3a3">ChangeStatus</span> <span style="margin-left: 10px; color: var(--vr-text-secondary)">ChangeStatus</span>
<span v-if="feed.status !== feed.previousStatus"> <span v-if="feed.status !== feed.previousStatus">
<i <i
class="x-user-status" class="x-user-status"
@@ -1335,15 +1335,15 @@
style="margin-left: 10px"></span> style="margin-left: 10px"></span>
</template> </template>
<template v-else-if="feed.type === 'ChangeGroup'"> <template v-else-if="feed.type === 'ChangeGroup'">
<span style="margin-left: 10px; color: #a3a3a3">ChangeGroup</span> <span style="margin-left: 10px; color: var(--vr-text-secondary)">ChangeGroup</span>
<span v-text="feed.groupName" style="margin-left: 10px"></span> <span v-text="feed.groupName" style="margin-left: 10px"></span>
</template> </template>
<template v-else-if="feed.type === 'ChatBoxMessage'"> <template v-else-if="feed.type === 'ChatBoxMessage'">
<span style="margin-left: 10px; color: #a3a3a3">ChatBox</span> <span style="margin-left: 10px; color: var(--vr-text-secondary)">ChatBox</span>
<span v-text="feed.text" style="margin-left: 10px; white-space: normal"></span> <span v-text="feed.text" style="margin-left: 10px; white-space: normal"></span>
</template> </template>
<template v-else-if="feed.type === 'PortalSpawn'"> <template v-else-if="feed.type === 'PortalSpawn'">
<span style="margin-left: 10px; color: #a3a3a3">PortalSpawn</span> <span style="margin-left: 10px; color: var(--vr-text-secondary)">PortalSpawn</span>
<VrLocation <VrLocation
:location="feed.location" :location="feed.location"
:hint="feed.worldName" :hint="feed.worldName"
@@ -1352,7 +1352,7 @@
style="margin-left: 10px"></VrLocation> style="margin-left: 10px"></VrLocation>
</template> </template>
<template v-else-if="feed.type === 'OnPlayerJoined'"> <template v-else-if="feed.type === 'OnPlayerJoined'">
<span style="margin-left: 10px; color: #a3a3a3">has joined</span> <span style="margin-left: 10px; color: var(--vr-text-secondary)">has joined</span>
<span <span
v-if="feed.platform === 'Desktop'" v-if="feed.platform === 'Desktop'"
style="color: var(--status-joinme); margin-left: 10px" style="color: var(--status-joinme); margin-left: 10px"
@@ -1368,23 +1368,23 @@
style="color: var(--platform-quest); margin-left: 10px" style="color: var(--platform-quest); margin-left: 10px"
>Android</span >Android</span
> >
<span v-else-if="feed.platform === 'iOS'" style="color: #c7c7ce; margin-left: 10px" <span v-else-if="feed.platform === 'iOS'" style="color: var(--platform-ios); margin-left: 10px"
>iOS</span >iOS</span
> >
<span v-if="!feed.inCache" style="color: #aaa; margin-left: 10px" <span v-if="!feed.inCache" style="color: var(--vr-text-muted); margin-left: 10px"
><Download class="inline-block h-4 w-4" /> ><Download class="inline-block h-4 w-4" />
</span> </span>
<span v-text="feed.avatar.name" style="margin-left: 10px"></span> <span v-text="feed.avatar.name" style="margin-left: 10px"></span>
</template> </template>
<template v-else-if="feed.type === 'SpawnEmoji'"> <template v-else-if="feed.type === 'SpawnEmoji'">
<span style="margin-left: 10px; color: #a3a3a3">SpawnEmoji</span> <span style="margin-left: 10px; color: var(--vr-text-secondary)">SpawnEmoji</span>
<span v-text="feed.text" style="margin-left: 10px"></span> <span v-text="feed.text" style="margin-left: 10px"></span>
</template> </template>
<span <span
v-else-if="feed.color === 'yellow'" v-else-if="feed.color === 'yellow'"
v-text="feed.text" v-text="feed.text"
style="color: yellow; margin-left: 10px"></span> style="color: yellow; margin-left: 10px"></span>
<span v-else style="margin-left: 10px; color: #a3a3a3" v-text="feed.text"></span> <span v-else style="margin-left: 10px; color: var(--vr-text-secondary)" v-text="feed.text"></span>
<template v-if="feed.combo > 1"> <template v-if="feed.combo > 1">
<span class="combo" style="margin-left: 10px">x{{ feed.combo }}</span> <span class="combo" style="margin-left: 10px">x{{ feed.combo }}</span>
</template> </template>
@@ -1690,7 +1690,7 @@
if (vrState.wristFeed.length === 0) { if (vrState.wristFeed.length === 0) {
return; return;
} }
let length = 16; let length = 19;
if (!vrState.config.hideDevicesFromFeed) { if (!vrState.config.hideDevicesFromFeed) {
length -= 2; length -= 2;
if (vrState.deviceCount > 8) { if (vrState.deviceCount > 8) {

View File

@@ -22,9 +22,7 @@ body {
margin: 0; margin: 0;
} }
/* Font variables are shared from ../styles/fonts.css */
:root { :root {
/* VRChat Status Colors (duplicated from globals.css for VR panel independence) */
--status-online: #67c23a; --status-online: #67c23a;
--status-joinme: #00b8ff; --status-joinme: #00b8ff;
--status-askme: #ff9500; --status-askme: #ff9500;
@@ -33,10 +31,26 @@ body {
--status-offline: #909399; --status-offline: #909399;
--status-offline-alt: #808080; --status-offline-alt: #808080;
/* Platform Colors */
--platform-pc: #0078d4; --platform-pc: #0078d4;
--platform-quest: #3ddc84; --platform-quest: #3ddc84;
--platform-ios: #8e8e93; --platform-ios: #8e8e93;
--vr-bg: #18181b;
--vr-bg-surface: #27272a;
--vr-text: #e4e4e7;
--vr-text-secondary: #a1a1aa;
--vr-text-muted: #71717a;
--vr-text-name: #d4d4d8;
--vr-text-friend: #fafafa;
--vr-text-favorite: #fbbf24;
--vr-border: rgba(255, 255, 255, 0.06);
--vr-border-strong: rgba(255, 255, 255, 0.12);
--vr-radius: 8px;
--vr-font-xs: 14px;
--vr-font-sm: 16px;
--vr-font-base: 18px;
--vr-font-lg: 20px;
} }
body { body {
font-family: font-family:
@@ -242,6 +256,9 @@ button {
z-index: 20; z-index: 20;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border-radius: var(--vr-radius);
border: 1px solid var(--vr-border-strong);
overflow: hidden;
} }
.hmd { .hmd {
@@ -254,22 +271,27 @@ button {
} }
.background { .background {
background: #1f1f1f; background: var(--vr-bg);
text-shadow: none; text-shadow: none;
} }
.x-container { .x-container {
position: relative; position: relative;
flex: none; flex: none;
padding: 2px 10px 0 10px; padding: 6px 10px 2px 10px;
overflow: hidden; overflow: hidden;
} }
.x-containerbottom { .x-containerbottom {
padding: 0px 10px; padding: 3px 10px 3px;
overflow: hidden; overflow: hidden;
font-size: 20px; font-size: var(--vr-font-base);
white-space: nowrap; white-space: nowrap;
border-top: 1px solid var(--vr-border-strong);
color: var(--vr-text-secondary);
font-weight: 400;
letter-spacing: 0.01em;
line-height: 1.4;
} }
.x-containerbottom span { .x-containerbottom span {
@@ -277,10 +299,21 @@ button {
overflow: hidden; overflow: hidden;
} }
.x-containerbottom .vue-marquee-text-component {
font-weight: 500;
color: var(--vr-text);
}
.x-containerbottom > br ~ span {
font-size: var(--vr-font-sm);
color: var(--vr-text-muted);
}
.np-progress-bar { .np-progress-bar {
width: 0%; width: 0%;
height: 2px; height: 3px;
background-color: white; background: linear-gradient(90deg, rgba(255,255,255,0.6), rgba(255,255,255,0.9));
border-radius: 2px;
} }
.np-progress-circle { .np-progress-circle {
@@ -302,27 +335,40 @@ button {
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 18px; font-size: var(--vr-font-base);
color: var(--vr-text);
font-weight: 400;
line-height: 1.25;
}
.x-friend-item:nth-child(even) {
background: rgba(255, 255, 255, 0.015);
} }
.x-friend-item .time { .x-friend-item .time {
margin-right: 5px; margin-right: 6px;
color: var(--vr-text-muted);
font-size: var(--vr-font-xs);
font-weight: 300;
font-variant-numeric: tabular-nums;
opacity: 0.9;
flex-shrink: 0;
} }
.x-friend-item .name { .x-friend-item .name {
font-weight: bold; font-weight: 600;
} }
.item .name { .item .name {
color: #c5c5c5; color: var(--vr-text-name);
} }
.friend .name { .friend .name {
color: #fff; color: var(--vr-text-friend);
} }
.favorite .name { .favorite .name {
color: #ff0; color: var(--vr-text-favorite);
} }
.x-friend-item > .avatar { .x-friend-item > .avatar {
@@ -361,11 +407,12 @@ button {
} }
.x-friend-item > .detail > .name { .x-friend-item > .detail > .name {
font-weight: bold; font-weight: 600;
} }
.x-friend-item > .detail > .extra { .x-friend-item > .detail > .extra {
font-weight: normal; font-weight: 400;
color: var(--vr-text-secondary);
} }
i.x-user-status { i.x-user-status {
@@ -435,7 +482,7 @@ i.x-user-status.busy {
} }
.hud-feed .combo { .hud-feed .combo {
color: #aaa; color: var(--vr-text-muted);
} }
.hud-timeout .item { .hud-timeout .item {
@@ -461,19 +508,6 @@ i.x-user-status.busy {
bottom: 0; bottom: 0;
} }
.tracker-container {
flex: 1 1 auto;
text-align: center;
line-height: 18px;
width: 55px;
}
.tracker-device img {
display: inline-block;
height: 32px;
transition: all 0.25s linear;
}
.tracker-warning { .tracker-warning {
color: #fcfb00; color: #fcfb00;
} }
@@ -489,3 +523,87 @@ i.x-user-status.busy {
.tracker-error img { .tracker-error img {
filter: saturate(160%) brightness(88%) hue-rotate(161deg); filter: saturate(160%) brightness(88%) hue-rotate(161deg);
} }
.vr-bottom-row {
display: flex;
align-items: center;
gap: 5px;
flex-wrap: wrap;
}
.vr-bottom-row > span {
display: inline-block;
}
.vr-bottom-right {
margin-left: auto;
}
.vr-text-muted {
color: var(--vr-text-muted);
}
.vr-mx {
margin-left: 5px;
margin-right: 5px;
}
.x-containerbottom:first-of-type {
border-top: 1px solid var(--vr-border);
padding: 6px 10px 4px;
background: rgba(255, 255, 255, 0.01);
}
.x-friend-item .lucide {
width: 16px !important;
height: 16px !important;
min-width: 16px;
color: var(--vr-text-muted);
flex-shrink: 0;
margin-right: 6px !important;
margin-left: 0 !important;
position: relative;
top: 1px;
opacity: 0.8;
}
.x-friend-item .lucide + .lucide {
margin-left: -2px !important;
}
.x-friend-item .lucide.mx-1 {
margin-left: 2px !important;
margin-right: 2px !important;
opacity: 0.5;
}
.tracker-container {
flex: 1 1 auto;
text-align: center;
line-height: 16px;
width: 48px;
font-size: 13px;
color: var(--vr-text-secondary);
font-weight: 500;
font-variant-numeric: tabular-nums;
padding: 1px 0;
}
.tracker-device {
display: flex;
flex-direction: column;
align-items: center;
gap: 1px;
}
.tracker-device img {
display: inline-block;
height: 20px;
transition: all 0.25s linear;
opacity: 0.8;
}
.tracker-device span {
font-size: 13px;
letter-spacing: 0.02em;
}