diff --git a/Dotnet/AppApi/AppApiVr.cs b/Dotnet/AppApi/AppApiVr.cs index 82adf4c83..a4f611aba 100644 --- a/Dotnet/AppApi/AppApiVr.cs +++ b/Dotnet/AppApi/AppApiVr.cs @@ -9,6 +9,8 @@ public class AppApiVr { public static readonly AppApiVr Instance; + private readonly PerformanceCounter _uptime = new PerformanceCounter("System", "System Up Time"); + static AppApiVr() { Instance = new AppApiVr(); @@ -45,9 +47,8 @@ public string[][] GetVRDevices() /// The number of milliseconds that the system has been running. public double GetUptime() { - using var uptime = new PerformanceCounter("System", "System Up Time"); - uptime.NextValue(); - return TimeSpan.FromSeconds(uptime.NextValue()).TotalMilliseconds; + _uptime.NextValue(); + return TimeSpan.FromSeconds(_uptime.NextValue()).TotalMilliseconds; } /// diff --git a/Dotnet/AppApi/Folders.cs b/Dotnet/AppApi/Folders.cs index a65d92237..74a7683f1 100644 --- a/Dotnet/AppApi/Folders.cs +++ b/Dotnet/AppApi/Folders.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using Newtonsoft.Json; @@ -170,6 +171,7 @@ public void OpenFolderAndSelectItem(string path, bool isFolder = false) var result = WinApi.SHParseDisplayName(folderPath, IntPtr.Zero, out pidlFolder, 0, out psfgaoOut); if (result != 0) { + OpenFolderAndSelectItemFallback(path); return; } @@ -178,6 +180,7 @@ public void OpenFolderAndSelectItem(string path, bool isFolder = false) { // Free the PIDL we allocated earlier if we failed to parse the display name of the file. Marshal.FreeCoTaskMem(pidlFolder); + OpenFolderAndSelectItemFallback(path); return; } @@ -189,6 +192,10 @@ public void OpenFolderAndSelectItem(string path, bool isFolder = false) // It can select multiple items, but we only need to select one. WinApi.SHOpenFolderAndSelectItems(pidlFolder, (uint)files.Length, files, 0); } + catch + { + OpenFolderAndSelectItemFallback(path); + } finally { // Free the PIDLs we allocated earlier @@ -196,5 +203,21 @@ public void OpenFolderAndSelectItem(string path, bool isFolder = false) Marshal.FreeCoTaskMem(pidlFile); } } + + public void OpenFolderAndSelectItemFallback(string path) + { + if (!File.Exists(path) && !Directory.Exists(path)) + return; + + if (Directory.Exists(path)) + { + Process.Start("explorer.exe", path); + } + else + { + // open folder with file highlighted + Process.Start("explorer.exe", $"/select,\"{path}\""); + } + } } } \ No newline at end of file diff --git a/Dotnet/LogWatcher.cs b/Dotnet/LogWatcher.cs index 8f813d873..ef83a1a85 100644 --- a/Dotnet/LogWatcher.cs +++ b/Dotnet/LogWatcher.cs @@ -1157,7 +1157,7 @@ private bool ParseOscFailedToStart(FileInfo fileInfo, LogContext logContext, str { // 2023.09.26 04:12:57 Warning - Could not Start OSC: Address already in use - if (string.Compare(line, offset, "Could not Start OSC: ", 0, 21, StringComparison.Ordinal) != 0) + if (string.Compare(line, offset, "VRChat could not start OSC server: ", 0, 21, StringComparison.Ordinal) != 0) return false; AppendLog(new[] diff --git a/html/src/app.js b/html/src/app.js index 0c00f6d12..2952f1c88 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -8135,7 +8135,7 @@ speechSynthesis.getVoices(); ); this.isFriendsGroup2 = await configRepository.getBool( 'VRCX_isFriendsGroupActive', - true + false ); this.isFriendsGroup3 = await configRepository.getBool( 'VRCX_isFriendsGroupOffline', @@ -26836,7 +26836,51 @@ speechSynthesis.getVoices(); $app.getLocalWorldFavorites(); }); - // pending offline timer + $app.data.worldFavoriteSearch = ''; + $app.data.worldFavoriteSearchResults = []; + + $app.methods.searchWorldFavorites = function () { + var search = this.worldFavoriteSearch.toLowerCase(); + if (search.length < 3) { + this.worldFavoriteSearchResults = []; + return; + } + + var results = []; + for (var i = 0; i < this.localWorldFavoriteGroups.length; ++i) { + var group = this.localWorldFavoriteGroups[i]; + if (!this.localWorldFavorites[group]) { + continue; + } + for (var j = 0; j < this.localWorldFavorites[group].length; ++j) { + var ref = this.localWorldFavorites[group][j]; + if ( + ref.name.toLowerCase().includes(search) || + ref.authorName.toLowerCase().includes(search) + ) { + results.push(ref); + } + } + } + + for (var i = 0; i < this.favoriteWorlds.length; ++i) { + var ref = this.favoriteWorlds[i].ref; + if (!ref) { + continue; + } + if ( + ref.name.toLowerCase().includes(search) || + ref.authorName.toLowerCase().includes(search) + ) { + results.push(ref); + } + } + + this.worldFavoriteSearchResults = results; + }; + + // #endregion + // #region | App: pending offline timer $app.methods.promptSetPendingOffline = function () { this.$prompt( @@ -28135,26 +28179,22 @@ speechSynthesis.getVoices(); D.memberRoles.push(role); } } - if (D.inGroup) { - API.getAllGroupPosts({ - groupId - }).then((args2) => { - if (groupId === args2.params.groupId) { - for (var post of args2.posts) { - post.title = this.replaceBioSymbols( - post.title - ); - post.text = this.replaceBioSymbols( - post.text - ); - } - if (args2.posts.length > 0) { - D.announcement = args2.posts[0]; - } - D.posts = args2.posts; - this.updateGroupPostSearch(); + API.getAllGroupPosts({ + groupId + }).then((args2) => { + if (groupId === args2.params.groupId) { + for (var post of args2.posts) { + post.title = this.replaceBioSymbols(post.title); + post.text = this.replaceBioSymbols(post.text); } - }); + if (args2.posts.length > 0) { + D.announcement = args2.posts[0]; + } + D.posts = args2.posts; + this.updateGroupPostSearch(); + } + }); + if (D.inGroup) { API.getGroupInstances({ groupId }).then((args3) => { diff --git a/html/src/index.pug b/html/src/index.pug index 27958f937..a7fc87193 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -1033,7 +1033,7 @@ html timer(:epoch="user.$travelingToTime") span.extra(v-else) timer(:epoch="user.$location_at") - .x-friend-item(v-if="groupDialog.ref.membershipStatus === 'member'" style="width:100%;cursor:default") + .x-friend-item(style="width:100%;cursor:default") .detail span.name {{ $t('dialog.group.info.announcement') }} span(style="display:block" v-text="groupDialog.announcement.title") @@ -2361,7 +2361,7 @@ html el-button(type="default" @click="deleteVRCPlusIcon(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogIconsLoading") span(slot="label") {{ $t('dialog.gallery_icons.emojis') }} - span(style="color:#909399;font-size:12px;margin-left:5px") {{ emojiTable.length }}/5 + span(style="color:#909399;font-size:12px;margin-left:5px") {{ emojiTable.length }}/9 input(type="file" accept="image/*" @change="onFileChangeEmoji" id="EmojiUploadButton" style="display:none") el-button-group(style="margin-right:10px") el-button(type="default" size="small" @click="refreshEmojiTable" icon="el-icon-refresh") {{ $t('dialog.gallery_icons.refresh') }} diff --git a/html/src/localization/en/en.json b/html/src/localization/en/en.json index e608adb28..6f9163d46 100644 --- a/html/src/localization/en/en.json +++ b/html/src/localization/en/en.json @@ -85,6 +85,7 @@ }, "worlds": { "header": "Worlds", + "search": "Search", "vrchat_favorites": "VRChat Favorites", "local_favorites": "Local Favorites", "new_group": "New Group" diff --git a/html/src/mixins/tabs/favorites.pug b/html/src/mixins/tabs/favorites.pug index 83e162ee8..8b51f0b68 100644 --- a/html/src/mixins/tabs/favorites.pug +++ b/html/src/mixins/tabs/favorites.pug @@ -58,6 +58,23 @@ mixin favoritesTab() div(style="display:inline-block;float:right;font-size:13px;margin-right:10px") span.name(style="margin-right:5px") {{ $t('view.favorite.sort_by') }} el-switch(v-model="sortFavorites" :inactive-text="$t('view.settings.appearance.appearance.sort_favorite_by_name')" :active-text="$t('view.settings.appearance.appearance.sort_favorite_by_date')" @change="saveSortFavoritesOption") + span(style="display:block;margin-top:20px") {{ $t('view.favorite.worlds.search') }} + el-input(v-model="worldFavoriteSearch" @input="searchWorldFavorites" clearable size="mini" :placeholder="$t('view.favorite.worlds.search')" style="width:300px;margin-top:10px") + .x-friend-list(style="margin-top:10px") + div(style="display:inline-block;width:300px;margin-right:15px" v-for="favorite in worldFavoriteSearchResults" :key="favorite.id" @click="showWorldDialog(favorite.id)") + .x-friend-item + template(v-if="favorite.name") + .avatar + img(v-lazy="favorite.thumbnailImageUrl") + .detail + span.name(v-text="favorite.name") + span.extra(v-if="favorite.occupants") {{ favorite.authorName }} ({{ favorite.occupants }}) + span.extra(v-else v-text="favorite.authorName") + template(v-else) + .avatar + .detail + span(v-text="favorite.id") + span(style="display:block;margin-top:20px") {{ $t('view.favorite.worlds.vrchat_favorites') }} el-collapse-item(v-for="group in API.favoriteWorldGroups" :key="group.name") template(slot="title")