diff --git a/AssetBundleCacher.cs b/AssetBundleCacher.cs index 4040ad3f..a6ca564a 100644 --- a/AssetBundleCacher.cs +++ b/AssetBundleCacher.cs @@ -179,8 +179,8 @@ namespace VRCX using (var stream = File.OpenRead(DownloadTempLocation)) { var hashBytes = sha256.ComputeHash(stream); - var hashString = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant(); - if (hashString != hash[0]) + var hashString = BitConverter.ToString(hashBytes).Replace("-", ""); + if (!hashString.Equals(hash[0], StringComparison.OrdinalIgnoreCase)) { logger.Error($"Updater: Hash check failed file:{hashString} remote:{hash[0]}"); // can't delete file yet because it's in use diff --git a/VRCXVR.cs b/VRCXVR.cs index 200fad57..3c4361a4 100644 --- a/VRCXVR.cs +++ b/VRCXVR.cs @@ -305,6 +305,8 @@ namespace VRCX var sb = new StringBuilder(256); var state = new VRControllerState_t(); + var poses = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; + system.GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin.TrackingUniverseStanding, 0, poses); for (var i = 0u; i < OpenVR.k_unMaxTrackedDeviceCount; ++i) { var devClass = system.GetTrackedDeviceClass(i); @@ -393,7 +395,8 @@ namespace VRCX isCharging ? "charging" : "discharging", - (batteryPercentage * 100).ToString() + (batteryPercentage * 100).ToString(), + poses[i].eTrackingResult.ToString() }; _deviceListLock.EnterWriteLock(); try diff --git a/html/src/app.js b/html/src/app.js index eac24bac..a7036cd7 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -108,9 +108,12 @@ speechSynthesis.getVoices(); this.Set(key, JSON.stringify(value)); }; - workerTimers.setInterval(function () { - VRCXStorage.Flush(); - }, 5 * 60 * 1000); + workerTimers.setInterval( + () => { + VRCXStorage.Flush(); + }, + 5 * 60 * 1000 + ); // #endregion // #region | Init: Noty, Vue, Vue-Markdown, ElementUI, VueI18n, VueLazyLoad, Vue filters, dark stylesheet @@ -5485,10 +5488,39 @@ speechSynthesis.getVoices(); pendingUpdate: false }; + $app.data.updateSharedFeedTimer = null; + $app.data.updateSharedFeedPending = false; + $app.data.updateSharedFeedPendingForceUpdate = false; $app.methods.updateSharedFeed = function (forceUpdate) { if (!this.friendLogInitStatus) { return; } + if (this.updateSharedFeedTimer) { + if (forceUpdate) { + this.updateSharedFeedPendingForceUpdate = true; + } + this.updateSharedFeedPending = true; + } else { + this.updateSharedExecute(forceUpdate); + this.updateSharedFeedTimer = setTimeout(() => { + if (this.updateSharedFeedPending) { + this.updateSharedExecute( + this.updateSharedFeedPendingForceUpdate + ); + } + this.updateSharedFeedTimer = null; + }, 150); + } + }; + + $app.methods.updateSharedExecute = function (forceUpdate) { + this.updateSharedFeedDebounce(forceUpdate); + this.updateSharedFeedTimer = null; + this.updateSharedFeedPending = false; + this.updateSharedFeedPendingForceUpdate = false; + }; + + $app.methods.updateSharedFeedDebounce = function (forceUpdate) { this.updateSharedFeedGameLog(forceUpdate); this.updateSharedFeedFeedTable(forceUpdate); this.updateSharedFeedNotificationTable(forceUpdate); @@ -5684,6 +5716,14 @@ speechSynthesis.getVoices(); } } } + // add tag colour + var tagColour = ''; + if (ctx.userId) { + var tagRef = this.customUserTags.get(ctx.userId); + if (typeof tagRef !== 'undefined') { + tagColour = tagRef.colour; + } + } // BlockedOnPlayerJoined, BlockedOnPlayerLeft, MutedOnPlayerJoined, MutedOnPlayerLeft if (ctx.type === 'OnPlayerJoined' || ctx.type === 'OnPlayerLeft') { for (var ref of this.playerModerationTable.data) { @@ -5725,6 +5765,7 @@ speechSynthesis.getVoices(); ) { wristArr.push({ ...ctx, + tagColour, isFriend, isFavorite }); @@ -6043,6 +6084,12 @@ speechSynthesis.getVoices(); } var isFriend = this.friends.has(ctx.userId); var isFavorite = API.cachedFavoritesByObjectId.has(ctx.userId); + // add tag colour + var tagColour = ''; + var tagRef = this.customUserTags.get(ctx.userId); + if (typeof tagRef !== 'undefined') { + tagColour = tagRef.colour; + } if ( w < 20 && wristFilter[ctx.type] && @@ -6051,7 +6098,8 @@ speechSynthesis.getVoices(); wristArr.push({ ...ctx, isFriend, - isFavorite + isFavorite, + tagColour }); ++w; } @@ -7828,7 +7876,9 @@ speechSynthesis.getVoices(); $app.methods.getAvatarMemo = async function (avatarId) { try { return await database.getAvatarMemoDB(avatarId); - } catch (err) {console.error(err);} + } catch (err) { + console.error(err); + } return { avatarId: '', editedAt: '', @@ -10121,6 +10171,13 @@ speechSynthesis.getVoices(); break; } if (entry) { + // add tag colour + if (entry.userId) { + var tagRef = this.customUserTags.get(entry.userId); + if (typeof tagRef !== 'undefined') { + entry.tagColour = tagRef.colour; + } + } this.queueGameLogNoty(entry); this.addGameLog(entry); } @@ -10523,7 +10580,7 @@ speechSynthesis.getVoices(); var isFavorite = API.cachedFavoritesByObjectId.has(userId); var colour = ''; var tagRef = this.customUserTags.get(userId); - if (typeof tagRef !== 'undefined' && tagRef.colour) { + if (typeof tagRef !== 'undefined') { colour = tagRef.colour; } var feed = { @@ -16348,7 +16405,32 @@ speechSynthesis.getVoices(); } }); + $app.data.updatePlayerListTimer = null; + $app.data.updatePlayerListPending = false; $app.methods.getCurrentInstanceUserList = function () { + if (!this.friendLogInitStatus) { + return; + } + if (this.updatePlayerListTimer) { + this.updatePlayerListPending = true; + } else { + this.updatePlayerListExecute(); + this.updatePlayerListTimer = setTimeout(() => { + if (this.updatePlayerListPending) { + this.updatePlayerListExecute(); + } + this.updatePlayerListTimer = null; + }, 150); + } + }; + + $app.methods.updatePlayerListExecute = function () { + this.updatePlayerListDebounce(); + this.updatePlayerListTimer = null; + this.updatePlayerListPending = false; + }; + + $app.methods.updatePlayerListDebounce = function () { var users = []; var pushUser = function (ref) { var photonId = ''; @@ -17880,7 +17962,7 @@ speechSynthesis.getVoices(); $app.data.ignoreAvatarMemoSave = false; - $app.watch['avatarDialog.memo'] = function (value) { + $app.watch['avatarDialog.memo'] = function () { if (this.ignoreAvatarMemoSave) { this.ignoreAvatarMemoSave = false; return; @@ -17889,7 +17971,7 @@ speechSynthesis.getVoices(); if (D.visible === false) { return; } - this.saveAvatarMemo(D.id, value == null ? D.memo : value); + this.saveAvatarMemo(D.id, D.memo); }; API.$on('LOGOUT', function () { @@ -21586,19 +21668,17 @@ speechSynthesis.getVoices(); } var name = ref.displayName; if (ref.statusDescription) { - var statusRegex = - /(?:^|\n*)(?:(?:[^\n:])*(?::|˸|discord)[\t\v\f\r]*)?([^\n]*(#|#)(?: )?\d{4})/gi.exec( - ref.statusDescription - ); + var statusRegex = /(?:discord|dc|dis)(?: |=|:|˸|;)(.*)/gi.exec( + ref.statusDescription + ); if (statusRegex) { discord = statusRegex[1]; } } if (!discord && ref.bio) { - var bioRegex = - /(?:^|\n*)(?:(?:[^\n:])*(?::|˸|discord)[\t\v\f\r]*)?([^\n]*(#|#)(?: )?\d{4})/gi.exec( - ref.bio - ); + var bioRegex = /(?:discord|dc|dis)(?: |=|:|˸|;)(.*)/gi.exec( + ref.bio + ); if (bioRegex) { discord = bioRegex[1]; } @@ -21606,10 +21686,7 @@ speechSynthesis.getVoices(); if (!discord) { continue; } - discord = discord.replace('#', '#'); - if (discord.substring(0, 1) === '#') { - discord = `${_(name)}${_(discord)}`; - } + discord = discord.trim(); lines.push(`${_(name)},${_(discord)}`); } this.discordNamesContent = lines.join('\n'); @@ -21717,6 +21794,11 @@ speechSynthesis.getVoices(); name: $t('dialog.config_json.cache_directory'), default: '%AppData%\\..\\LocalLow\\VRChat\\vrchat' }, + picture_output_folder: { + name: $t('dialog.config_json.picture_directory'), + // my pictures folder + default: `%UserProfile%\\Pictures\\VRChat` + }, // dynamic_bone_max_affected_transform_count: { // name: 'Dynamic Bones Limit Max Transforms (0 disable all transforms)', // default: '32', @@ -21747,7 +21829,12 @@ speechSynthesis.getVoices(); $app.methods.saveVRChatConfigFile = function () { for (var item in this.VRChatConfigFile) { - if (this.VRChatConfigFile[item] === '') { + if (item === 'picture_output_split_by_date') { + // this one is default true, it's special + if (this.VRChatConfigFile[item]) { + delete this.VRChatConfigFile[item]; + } + } else if (this.VRChatConfigFile[item] === '') { delete this.VRChatConfigFile[item]; } else if ( typeof this.VRChatConfigFile[item] === 'boolean' && @@ -23417,6 +23504,7 @@ speechSynthesis.getVoices(); } }); API.cachedAvatarNames = new Map(); + this.customUserTags = new Map(); this.updateInstanceInfo = 0; }; @@ -23569,6 +23657,7 @@ speechSynthesis.getVoices(); ref.$customTag = data.Tag; ref.$customTagColour = data.TagColour; } + this.updateSharedFeed(true); }; $app.methods.eventVrcxMessage = function (data) { diff --git a/html/src/index.pug b/html/src/index.pug index 7dd42017..2029f17f 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -582,6 +582,7 @@ html el-tag.x-tag-platform-quest(v-if="worldDialog.isQuest" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Quest el-tag.x-tag-platform-ios(v-if="worldDialog.isIos" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") iOS el-tag(v-if="worldDialog.avatarScalingDisabled" type="warning" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") {{ $t('dialog.world.tags.avatar_scaling_disabled') }} + el-tag(v-if="worldDialog.ref.unityPackageUrl" type="success" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") {{ $t('dialog.world.tags.future_proofing') }} el-tag(type="info" effect="plain" size="mini" v-text="worldDialog.fileSize" style="margin-right:5px;margin-top:5px") el-tag.x-link(v-if="worldDialog.inCache" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px" @click="openFolderGeneric(worldDialog.cachePath)") span(v-text="worldDialog.cacheSize") @@ -757,6 +758,7 @@ html el-tag(v-if="avatarDialog.ref.releaseStatus === 'public'" type="success" effect="plain" size="mini" style="margin-right:5px") {{ $t('dialog.avatar.tags.public') }} el-tag(v-else type="danger" effect="plain" size="mini" style="margin-right:5px") {{ $t('dialog.avatar.tags.private') }} el-tag(v-if="avatarDialog.isQuestFallback" type="info" effect="plain" size="mini" style="margin-right:5px") {{ $t('dialog.avatar.tags.fallback') }} + el-tag(v-if="avatarDialog.ref.unityPackageUrl" type="success" effect="plain" size="mini" style="margin-right:5px") {{ $t('dialog.avatar.tags.future_proofing') }} el-tag(v-if="avatarDialog.fileSize" type="info" effect="plain" size="mini" v-text="avatarDialog.fileSize" style="margin-right:5px") el-tag.x-link(v-if="avatarDialog.inCache" type="info" effect="plain" size="mini" @click="openFolderGeneric(avatarDialog.cachePath)") span(v-text="avatarDialog.cacheSize") @@ -1383,6 +1385,7 @@ html span #[span(v-text="getVRChatScreenshotResolution()")] #[i.el-icon-arrow-down.el-icon--right] el-dropdown-menu(#default="dropdown") el-dropdown-item(v-for="row in VRChatScreenshotResolutions" :key="row.index" v-text="row.name" :command="row") + el-checkbox(v-model="VRChatConfigFile.picture_output_split_by_date" style="margin-top:5px;display:block" :checked="true") {{ $t('dialog.config_json.picture_sort_by_date') }} el-checkbox(v-model="VRChatConfigFile.disableRichPresence" style="margin-top:5px;display:block") {{ $t('dialog.config_json.disable_discord_presence') }} template(#footer) el-button(size="small" @click="openExternalLink('https://docs.vrchat.com/docs/configuration-file')") {{ $t('dialog.config_json.vrchat_docs') }} diff --git a/html/src/localization/strings/en.json b/html/src/localization/strings/en.json index 0592426a..80de6358 100644 --- a/html/src/localization/strings/en.json +++ b/html/src/localization/strings/en.json @@ -634,6 +634,7 @@ "public": "Public", "private": "Private", "avatar_scaling_disabled": "Avatar Scaling Disabled", + "future_proofing": "Future Proofing", "labs": "Labs", "cache": "Cache" }, @@ -701,6 +702,7 @@ "public": "Public", "private": "Private", "fallback": "Fallback", + "future_proofing": "Future Proofing", "cache": "Cache" }, "labels": { @@ -915,9 +917,11 @@ "max_cache_size": "Max Cache Size [GB] (min 20)", "cache_expiry_delay": "Cache Expiry [Days] (30 - 150)", "cache_directory": "Custom Cache Folder Location", + "picture_directory": "Custom Picture Folder Location", "fpv_steadycam_fov": "First-Person Steadycam FOV", "camera_resolution": "Camera Resolution", "screenshot_resolution": "Screenshot Resolution", + "picture_sort_by_date": "Sort pictures into folders by date", "disable_discord_presence": "Disable Discord Rich Presence", "vrchat_docs": "VRChat Docs", "cancel": "Cancel", @@ -932,7 +936,7 @@ }, "set_world_tags": { "header": "Set World Tags", - "avatar_scaling_disabled": "Avatar Scaling Disabled", + "avatar_scaling_disabled": "Disable avatar scaling", "enable_debugging": "Enable world debugging for others", "seprator": "Enter tags comma separated", "cancel": "Cancel", diff --git a/html/src/localization/strings/ja.json b/html/src/localization/strings/ja.json index 15bad562..4870b7f9 100644 --- a/html/src/localization/strings/ja.json +++ b/html/src/localization/strings/ja.json @@ -736,7 +736,7 @@ "last_updated": "最終更新日時", "version": "バージョン", "platform": "プラットフォーム", - "memo":"メモ (VRCX)", + "memo": "メモ (VRCX)", "memo_placeholder": "クリックしてメモを追加" }, "json": { diff --git a/html/src/localization/strings/zh_CN.json b/html/src/localization/strings/zh_CN.json index 2499459b..8a48a035 100644 --- a/html/src/localization/strings/zh_CN.json +++ b/html/src/localization/strings/zh_CN.json @@ -708,7 +708,7 @@ "last_updated": "最后更新", "version": "版本", "platform": "平台", - "memo":"VRCX 本地备忘信息", + "memo": "VRCX 本地备忘信息", "memo_placeholder": "点击添加备忘录" }, "json": { diff --git a/html/src/vr.js b/html/src/vr.js index dc366c05..d8b476db 100644 --- a/html/src/vr.js +++ b/html/src/vr.js @@ -795,6 +795,23 @@ Vue.component('marquee-text', MarqueeText); } }; + $app.methods.trackingResultToClass = function (deviceStatus) { + switch (deviceStatus) { + case 'Uninitialized': + case 'Calibrating_OutOfRange': + case 'Fallback_RotationOnly': + return 'tracker-error'; + + case 'Calibrating_InProgress': + case 'Running_OutOfRange': + return 'tracker-warning'; + + case 'Running_OK': + default: + return ''; + } + }; + $app = new Vue($app); window.$app = $app; })(); diff --git a/html/src/vr.pug b/html/src/vr.pug index af83536b..34b1662f 100644 --- a/html/src/vr.pug +++ b/html/src/vr.pug @@ -48,12 +48,12 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | ▶️ #[span.name(v-text="feed.displayName")] + | ▶️ #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] div(v-else-if="feed.type === 'OnPlayerLeft'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra span.time {{ feed.created_at | formatDate }} - | ◀️ #[span.name(v-text="feed.displayName")] + | ◀️ #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] div(v-else-if="feed.type === 'OnPlayerJoining'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra @@ -69,7 +69,7 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | 🎵 #[span.name(v-if="feed.displayName" v-text="feed.displayName" style="margin-right:5px")] + | 🎵 #[span.name(v-if="feed.displayName" v-text="feed.displayName" style="margin-right:5px" :style="{'color':feed.tagColour}")] template(v-if="feed.videoName") | #[span(v-text="feed.videoName")] template(v-else) @@ -149,7 +149,7 @@ html span.extra span.time {{ feed.created_at | formatDate }} template(v-if="feed.displayName") - | ✨ #[span.name(v-text="feed.displayName" style="margin-right:5px")] + | ✨ #[span.name(v-text="feed.displayName" style="margin-right:5px" :style="{'color':feed.tagColour}")] | #[location(:location="feed.instanceId" :hint="feed.worldName" :grouphint="feed.groupName")] template(v-else) | ✨ User has spawned a portal @@ -157,7 +157,7 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | 🧍 #[span.name(v-text="feed.displayName" style="margin-right:5px")] + | 🧍 #[span.name(v-text="feed.displayName" style="margin-right:5px" :style="{'color':feed.tagColour}")] template(v-if="feed.releaseStatus === 'public'") | #[i.x-user-status.online] template(v-else) @@ -169,7 +169,7 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | 💬 #[span.name(v-text="feed.displayName")] #[span(v-text="feed.text")] + | 💬 #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] #[span(v-text="feed.text")] div(v-else-if="feed.type === 'Event'" class="x-friend-item") .detail span.extra @@ -179,7 +179,7 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | 🟠 #[span.name(v-text="feed.message")] #[span.name(v-text="feed.displayName")] + | 🟠 #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] #[span.name(v-text="feed.message")] div(v-else-if="feed.type === 'BlockedOnPlayerJoined'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra @@ -204,22 +204,22 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | 🚫 #[span.name(v-text="feed.displayName")] + | 🚫 #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] div(v-else-if="feed.type === 'Unblocked'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra span.time {{ feed.created_at | formatDate }} - | ⭕ #[span.name(v-text="feed.displayName")] + | ⭕ #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] div(v-else-if="feed.type === 'Muted'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra span.time {{ feed.created_at | formatDate }} - | 🔇 #[span.name(v-text="feed.displayName")] + | 🔇 #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] div(v-else-if="feed.type === 'Unmuted'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra span.time {{ feed.created_at | formatDate }} - | 🎤 #[span.name(v-text="feed.displayName")] + | 🎤 #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] template(v-else) template(v-for="feed in wristFeed") .x-friend-item(v-if="feed.type === 'GPS'" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") @@ -258,12 +258,12 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | #[span.name(v-text="feed.displayName")] has joined + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] has joined div(v-else-if="feed.type === 'OnPlayerLeft'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra span.time {{ feed.created_at | formatDate }} - | #[span.name(v-text="feed.displayName")] has left + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] has left div(v-else-if="feed.type === 'OnPlayerJoining'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra @@ -278,7 +278,7 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | #[span.name(v-text="feed.displayName")] + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] span(style="margin-left:5px;margin-right:5px") changed video to template(v-if="feed.videoName") | #[span(v-text="feed.videoName")] @@ -359,7 +359,7 @@ html span.extra span.time {{ feed.created_at | formatDate }} template(v-if="feed.displayName") - | #[span.name(v-text="feed.displayName")] has spawned a portal to + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] has spawned a portal to | #[location(:location="feed.instanceId" :hint="feed.worldName" :grouphint="feed.groupName" style="margin-left:5px")] template(v-else) | User has spawned a portal @@ -367,7 +367,7 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | #[span.name(v-text="feed.displayName")] + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] span(style="margin-left:5px;margin-right:5px") changed into avatar template(v-if="feed.releaseStatus === 'public'") | #[i.x-user-status.online] @@ -380,7 +380,7 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | #[span.name(v-text="feed.displayName")] said #[span(v-text="feed.text")] + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] said #[span(v-text="feed.text")] div(v-else-if="feed.type === 'Event'" class="x-friend-item") .detail span.extra @@ -390,7 +390,7 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | External: #[span.name(v-text="feed.message")] #[span.name(v-text="feed.displayName")] + | External: #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] #[span.name(v-text="feed.message")] div(v-else-if="feed.type === 'BlockedOnPlayerJoined'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra @@ -415,58 +415,58 @@ html .detail span.extra span.time {{ feed.created_at | formatDate }} - | #[span.name(v-text="feed.displayName")] has blocked you + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] has blocked you div(v-else-if="feed.type === 'Unblocked'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra span.time {{ feed.created_at | formatDate }} - | #[span.name(v-text="feed.displayName")] has unblocked you + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] has unblocked you div(v-else-if="feed.type === 'Muted'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra span.time {{ feed.created_at | formatDate }} - | #[span.name(v-text="feed.displayName")] has muted you + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] has muted you div(v-else-if="feed.type === 'Unmuted'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }") .detail span.extra span.time {{ feed.created_at | formatDate }} - | #[span.name(v-text="feed.displayName")] has unmuted you + | #[span.name(v-text="feed.displayName" :style="{'color':feed.tagColour}")] has unmuted you .x-containerbottom div(style="display:flex;flex-direction:row;flex-wrap:wrap") div(v-for="device in devices" class="tracker-container") - template(v-if="device[0] === 'leftController'") - img(v-if="device[1] !== 'connected'" src="images/left_controller_status_off.png" class="tracker-device") - img(v-else-if="device[2] === 'charging'" src="images/left_controller_status_ready_charging.png" class="tracker-device") - img(v-else-if="device[3] < 20" src="images/left_controller_status_ready_low.png" class="tracker-device") - img(v-else src="images/left_controller_status_ready.png" class="tracker-device") + div(v-if="device[0] === 'leftController'" class="tracker-device" :class="trackingResultToClass(device[4])") + img(v-if="device[1] !== 'connected'" src="images/left_controller_status_off.png" class="tracker-device" :class="trackingResultToClass(device[4])") + img(v-else-if="device[2] === 'charging'" src="images/left_controller_status_ready_charging.png") + img(v-else-if="device[3] < 20" src="images/left_controller_status_ready_low.png") + img(v-else src="images/left_controller_status_ready.png") span {{ device[3] }}% - template(v-else-if="device[0] === 'rightController'") - img(v-if="device[1] !== 'connected'" src="images/right_controller_status_off.png" class="tracker-device") - img(v-else-if="device[2] === 'charging'" src="images/right_controller_status_ready_charging.png" class="tracker-device") - img(v-else-if="device[3] < 20" src="images/right_controller_status_ready_low.png" class="tracker-device") - img(v-else src="images/right_controller_status_ready.png" class="tracker-device") + div(v-else-if="device[0] === 'rightController'" class="tracker-device" :class="trackingResultToClass(device[4])") + img(v-if="device[1] !== 'connected'" src="images/right_controller_status_off.png") + img(v-else-if="device[2] === 'charging'" src="images/right_controller_status_ready_charging.png") + img(v-else-if="device[3] < 20" src="images/right_controller_status_ready_low.png") + img(v-else src="images/right_controller_status_ready.png") span {{ device[3] }}% - template(v-else-if="device[0] === 'controller'") - img(v-if="device[1] !== 'connected'" src="images/controller_status_off.png" class="tracker-device") - img(v-else-if="device[2] === 'charging'" src="images/controller_status_ready_charging.png" class="tracker-device") - img(v-else-if="device[3] < 20" src="images/controller_status_ready_low.png" class="tracker-device") - img(v-else src="images/controller_status_ready.png" class="tracker-device") + div(v-else-if="device[0] === 'controller'" class="tracker-device" :class="trackingResultToClass(device[4])") + img(v-if="device[1] !== 'connected'" src="images/controller_status_off.png") + img(v-else-if="device[2] === 'charging'" src="images/controller_status_ready_charging.png") + img(v-else-if="device[3] < 20" src="images/controller_status_ready_low.png") + img(v-else src="images/controller_status_ready.png") span {{ device[3] }}% - template(v-else-if="device[0] === 'tracker'") - img(v-if="device[1] !== 'connected'" src="images/tracker_status_off.png" class="tracker-device") - img(v-else-if="device[2] === 'charging'" src="images/tracker_status_ready_charging.png" class="tracker-device") - img(v-else-if="device[3] < 20" src="images/tracker_status_ready_low.png" class="tracker-device") - img(v-else src="images/tracker_status_ready.png" class="tracker-device") + div(v-else-if="device[0] === 'tracker'" class="tracker-device" :class="trackingResultToClass(device[4])") + img(v-if="device[1] !== 'connected'" src="images/tracker_status_off.png") + img(v-else-if="device[2] === 'charging'" src="images/tracker_status_ready_charging.png") + img(v-else-if="device[3] < 20" src="images/tracker_status_ready_low.png") + img(v-else src="images/tracker_status_ready.png") span {{ device[3] }}% - template(v-else-if="device[0] === 'base'") - img(v-if="device[1] !== 'connected'" src="images/base_status_off.png" class="tracker-device") - img(v-else src="images/base_status_ready.png" class="tracker-device") + div(v-else-if="device[0] === 'base'" class="tracker-device" :class="trackingResultToClass(device[4])") + img(v-if="device[1] !== 'connected'" src="images/base_status_off.png") + img(v-else src="images/base_status_ready.png") span(v-if="device[3] !== 100") {{ device[3] }}x - template(v-else) - img(v-if="device[1] !== 'connected'" src="images/other_status_off.png" class="tracker-device") - img(v-else-if="device[2] === 'charging'" src="images/other_status_ready_charging.png" class="tracker-device") - img(v-else-if="device[3] < 20" src="images/other_status_ready_low.png" class="tracker-device") - img(v-else src="images/other_status_ready.png" class="tracker-device") + div(v-else class="tracker-device" :class="trackingResultToClass(device[4])") + img(v-if="device[1] !== 'connected'" src="images/other_status_off.png") + img(v-else-if="device[2] === 'charging'" src="images/other_status_ready_charging.png") + img(v-else-if="device[3] < 20" src="images/other_status_ready_low.png") + img(v-else src="images/other_status_ready.png") span {{ device[3] }}% .x-containerbottom template(v-if="nowPlaying.playing") diff --git a/html/src/vr.scss b/html/src/vr.scss index 6c941de9..dcdb25ea 100644 --- a/html/src/vr.scss +++ b/html/src/vr.scss @@ -178,8 +178,13 @@ button { font-family: 'Noto Sans JP', 'Noto Sans KR', 'Noto Sans TC', 'Noto Sans SC', 'Meiryo UI', 'Malgun Gothic', 'Segoe UI', sans-serif; line-height: normal; - text-shadow: #000 0px 0px 3px, #000 0px 0px 3px, #000 0px 0px 3px, - #000 0px 0px 3px, #000 0px 0px 3px, #000 0px 0px 3px; + text-shadow: + #000 0px 0px 3px, + #000 0px 0px 3px, + #000 0px 0px 3px, + #000 0px 0px 3px, + #000 0px 0px 3px, + #000 0px 0px 3px; } .x-app { @@ -411,4 +416,21 @@ i.x-user-status.busy { .tracker-device img { width: 32px; height: 32px; + transition: all 0.25s linear; +} + +.tracker-warning { + color: #fcfb00; +} + +.tracker-warning img { + filter: saturate(250%) brightness(151%) hue-rotate(221deg); +} + +.tracker-error { + color: #fd4444; +} + +.tracker-error img { + filter: saturate(160%) brightness(88%) hue-rotate(161deg); }