diff --git a/AppApi.cs b/AppApi.cs index 503c7b03..aa55eecc 100644 --- a/AppApi.cs +++ b/AppApi.cs @@ -143,8 +143,53 @@ namespace VRCX } } - var cachePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"Low\VRChat\VRChat"; - return cachePath; + return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"Low\VRChat\VRChat"; + } + + public string GetVRChatPhotosLocation() + { + var json = ReadConfigFile(); + if (!string.IsNullOrEmpty(json)) + { + var obj = JsonConvert.DeserializeObject(json); + if (obj["picture_output_folder"] != null) + { + var photosDir = (string)obj["picture_output_folder"]; + if (!string.IsNullOrEmpty(photosDir) && Directory.Exists(photosDir)) + { + return photosDir; + } + } + } + + return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "VRChat"); + } + + public string GetVRChatScreenshotsLocation() + { + // program files steam userdata screenshots + var steamPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Steam\userdata"); + var screenshotPath = string.Empty; + var latestWriteTime = DateTime.MinValue; + if (!Directory.Exists(steamPath)) + return screenshotPath; + + var steamUserDirs = Directory.GetDirectories(steamPath); + foreach (var steamUserDir in steamUserDirs) + { + var screenshotDir = Path.Combine(steamUserDir, @"760\remote\438100\screenshots"); + if (!Directory.Exists(screenshotDir)) + continue; + + var lastWriteTime = File.GetLastWriteTime(screenshotDir); + if (lastWriteTime <= latestWriteTime) + continue; + + latestWriteTime = lastWriteTime; + screenshotPath = screenshotDir; + } + + return screenshotPath; } /// @@ -896,7 +941,7 @@ namespace VRCX openFileDialog.FilterIndex = 1; openFileDialog.RestoreDirectory = true; - var initialPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "VRChat"); + var initialPath = GetVRChatPhotosLocation(); if (Directory.Exists(initialPath)) { openFileDialog.InitialDirectory = initialPath; @@ -1013,7 +1058,7 @@ namespace VRCX public void GetLastScreenshot() { // Get the last screenshot taken by VRChat - var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "VRChat"); + var path = GetVRChatPhotosLocation(); if (!Directory.Exists(path)) return; @@ -1044,6 +1089,56 @@ namespace VRCX })); } } + + public bool OpenVrcxAppDataFolder() + { + var path = Program.AppDataDirectory; + if (!Directory.Exists(path)) + return false; + + OpenFolderAndSelectItem(path, true); + return true; + } + + public bool OpenVrcAppDataFolder() + { + var path = GetVRChatAppDataLocation(); + if (!Directory.Exists(path)) + return false; + + OpenFolderAndSelectItem(path, true); + return true; + } + + public bool OpenVrcPhotosFolder() + { + var path = GetVRChatPhotosLocation(); + if (!Directory.Exists(path)) + return false; + + OpenFolderAndSelectItem(path, true); + return true; + } + + public bool OpenVrcScreenshotsFolder() + { + var path = GetVRChatScreenshotsLocation(); + if (!Directory.Exists(path)) + return false; + + OpenFolderAndSelectItem(path, true); + return true; + } + + public bool OpenCrashVrcCrashDumps() + { + var path = Path.Combine(Path.GetTempPath(), "VRChat", "VRChat", "Crashes"); + if (!Directory.Exists(path)) + return false; + + OpenFolderAndSelectItem(path, true); + return true; + } /// /// Opens the folder containing user-defined shortcuts, if it exists. diff --git a/html/src/app.js b/html/src/app.js index e00b0b69..a9af25d8 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -2175,6 +2175,10 @@ speechSynthesis.getVoices(); API.actuallyGetCurrentLocation = async function () { let gameLogLocation = $app.lastLocation.location; + if (gameLogLocation.startsWith('local')) { + console.warn('PWI: local test mode', 'test_world'); + return 'test_world'; + } if (gameLogLocation === 'traveling') { gameLogLocation = $app.lastLocationDestination; } @@ -2913,7 +2917,7 @@ speechSynthesis.getVoices(); if ( json.unityPackages?.length > 0 && unityPackages.length > 0 && - !json.unityPackages.assetUrl + !json.unityPackages[0].assetUrl ) { ref.unityPackages = unityPackages; } @@ -5304,12 +5308,15 @@ speechSynthesis.getVoices(); $app.methods.openExternalLink = function (link) { this.$confirm(`${link}`, 'Open External Link', { - confirmButtonText: 'Confirm', - cancelButtonText: 'Cancel', + distinguishCancelAndClose: true, + confirmButtonText: 'Open', + cancelButtonText: 'Copy', type: 'info', callback: (action) => { if (action === 'confirm') { AppApi.OpenLink(link); + } else if (action === 'cancel') { + this.copyLink(link); } } }); @@ -5663,6 +5670,8 @@ speechSynthesis.getVoices(); // on Location change remove OnPlayerLeft if (ctx.type === 'LocationDestination') { currentUserLeaveTime = Date.parse(ctx.created_at); + var currentUserLeaveTimeOffset = + currentUserLeaveTime + 5 * 1000; for (var k = w - 1; k > -1; k--) { var feedItem = wristArr[k]; if ( @@ -5670,7 +5679,7 @@ speechSynthesis.getVoices(); Date.parse(feedItem.created_at) >= currentUserLeaveTime && Date.parse(feedItem.created_at) <= - currentUserLeaveTime + 5 * 1000 + currentUserLeaveTimeOffset ) { wristArr.splice(k, 1); w--; @@ -5680,13 +5689,14 @@ speechSynthesis.getVoices(); // on Location change remove OnPlayerJoined if (ctx.type === 'Location') { locationJoinTime = Date.parse(ctx.created_at); + var locationJoinTimeOffset = locationJoinTime + 20 * 1000; for (var k = w - 1; k > -1; k--) { var feedItem = wristArr[k]; if ( feedItem.type === 'OnPlayerJoined' && Date.parse(feedItem.created_at) >= locationJoinTime && Date.parse(feedItem.created_at) <= - locationJoinTime + 20 * 1000 + locationJoinTimeOffset ) { wristArr.splice(k, 1); w--; @@ -5755,8 +5765,12 @@ speechSynthesis.getVoices(); } } } + // when too many user joins happen at once when switching instances + // the "w" counter maxes out and wont add any more entries + // until the onJoins are cleared by "Location" + // e.g. if a "VideoPlay" occurs between "OnPlayerJoined" and "Location" it wont be added if ( - w < 20 && + w < 50 && wristFilter[ctx.type] && (wristFilter[ctx.type] === 'On' || wristFilter[ctx.type] === 'Everyone' || @@ -11059,6 +11073,26 @@ speechSynthesis.getVoices(); playerCount: 0, pendingLeave: 0 }); + } else if (data.Parameters[245][0] === 21) { + var portalId = data.Parameters[245][1]; + var userId = data.Parameters[245][2]; + var playerCount = data.Parameters[245][3]; + var shortName = data.Parameters[245][5]; + var worldName = ''; + this.addPhotonPortalSpawn( + gameLogDate, + userId, + shortName, + worldName + ); + this.photonLobbyActivePortals.set(portalId, { + userId, + shortName, + worldName, + created_at: Date.parse(gameLogDate), + playerCount: 0, + pendingLeave: 0 + }); } else if (data.Parameters[245][0] === 22) { var portalId = data.Parameters[245][1]; var text = 'DeletedPortal'; @@ -11244,6 +11278,10 @@ speechSynthesis.getVoices(); if (L.groupId) { groupName = await this.getGroupName(L.groupId); } + if (!worldName) { + // eslint-disable-next-line no-param-reassign + worldName = await this.getWorldName(location); + } // var newShortName = instance.json.shortName; // var portalType = 'Secure'; // if (shortName === newShortName) { @@ -11328,8 +11366,6 @@ speechSynthesis.getVoices(); } if (data.avatarEyeHeight < 0) { text = 'Photon bot has joined, invalid avatarEyeHeight'; - } else if (data.user.last_platform === 'android' && !data.inVRMode) { - var text = 'User joined as Quest in desktop mode'; } else if ( data.user.last_platform === 'android' && platforms.length > 0 && @@ -11782,6 +11818,9 @@ speechSynthesis.getVoices(); ) { url = new URL(url.searchParams.get('url')); } + if (videoUrl.startsWith('https://u2b.cx/')) { + url = new URL(videoUrl.substring(15)); + } var id1 = url.pathname; var id2 = url.searchParams.get('v'); if (id1 && id1.length === 12) { @@ -11794,6 +11833,7 @@ speechSynthesis.getVoices(); } if (id2 && id2.length === 11) { // https://www.youtube.com/watch?v= + // https://music.youtube.com/watch?v= youtubeVideoId = id2; } if (this.youTubeApi && youtubeVideoId) { @@ -12994,7 +13034,7 @@ speechSynthesis.getVoices(); $app.applyFavorite('avatar', args.ref.id); }); - $app.methods.applyFavorite = function (type, objectId, sortTop) { + $app.methods.applyFavorite = async function (type, objectId, sortTop) { var favorite = API.cachedFavoritesByObjectId.get(objectId); var ctx = this.favoriteObjects.get(objectId); if (typeof favorite !== 'undefined') { @@ -13060,6 +13100,7 @@ speechSynthesis.getVoices(); this.sortFavoriteFriends = true; } } + // else too bad } else if (type === 'world') { var ref = API.cachedWorlds.get(objectId); if (typeof ref !== 'undefined') { @@ -13070,6 +13111,27 @@ speechSynthesis.getVoices(); ctx.name = ref.name; this.sortFavoriteWorlds = true; } + } else { + // try fetch from local world favorites + var world = await database.getCachedWorldById(objectId); + if (world) { + ctx.ref = world; + ctx.name = world.name; + ctx.deleted = true; + this.sortFavoriteWorlds = true; + } + if (!world) { + // try fetch from local world history + var worldName = + await database.getGameLogWorldNameByWorldId( + objectId + ); + if (worldName) { + ctx.name = worldName; + ctx.deleted = true; + this.sortFavoriteWorlds = true; + } + } } } else if (type === 'avatar') { var ref = API.cachedAvatars.get(objectId); @@ -13081,6 +13143,17 @@ speechSynthesis.getVoices(); ctx.name = ref.name; this.sortFavoriteAvatars = true; } + } else { + // try fetch from local avatar history + var avatar = await database.getCachedAvatarById( + objectId + ); + if (avatar) { + ctx.ref = avatar; + ctx.name = avatar.name; + ctx.deleted = true; + this.sortFavoriteAvatars = true; + } } } } @@ -15196,6 +15269,17 @@ speechSynthesis.getVoices(); }); }; + $app.methods.showGroupDialogShortCode = function (shortCode) { + API.groupStrictsearch({ query: shortCode }).then((args) => { + for (var group of args.json) { + if (`${group.shortCode}.${group.discriminator}` === shortCode) { + this.showGroupDialog(group.id); + } + } + return args; + }); + }; + $app.methods.directAccessParse = function (input) { if (!input) { return false; @@ -15219,19 +15303,12 @@ speechSynthesis.getVoices(); this.showGroupDialog(groupId); return true; } - } else if (input.startsWith('https://vrc.group/')) { + } else if ( + input.startsWith('https://vrc.group/') || + /^[A-Za-z0-9]{3,6}\.[0-9]{4}$/g.test(input) + ) { var shortCode = input.substring(18); - API.groupStrictsearch({ query: shortCode }).then((args) => { - for (var group of args.json) { - if ( - `${group.shortCode}.${group.discriminator}` === - shortCode - ) { - this.showGroupDialog(group.id); - } - } - return args; - }); + this.showGroupDialogShortCode(shortCode); return true; } else if ( input.substring(0, 4) === 'usr_' || @@ -19034,7 +19111,8 @@ speechSynthesis.getVoices(); $app.data.setWorldTagsDialog = { visible: false, - tags: [], + authorTags: [], + contentTags: [], debugAllowed: false, avatarScalingDisabled: false }; @@ -19044,10 +19122,14 @@ speechSynthesis.getVoices(); var D = this.setWorldTagsDialog; D.visible = true; var oldTags = this.worldDialog.ref.tags; - var tags = []; + var authorTags = []; + var contentTags = []; oldTags.forEach((tag) => { - if (tag.includes('author_tag_')) { - tags.unshift(tag.substring(11)); + if (tag.startsWith('author_tag_')) { + authorTags.unshift(tag.substring(11)); + } + if (tag.startsWith('content_')) { + contentTags.unshift(tag.substring(8)); } if (tag === 'debug_allowed') { D.debugAllowed = true; @@ -19056,18 +19138,25 @@ speechSynthesis.getVoices(); D.avatarScalingDisabled = true; } }); - D.tags = tags.toString(); + D.authorTags = authorTags.toString(); + D.contentTags = contentTags.toString(); }; $app.methods.saveSetWorldTagsDialog = function () { var D = this.setWorldTagsDialog; - var oldTags = D.tags.split(','); + var authorTags = D.authorTags.trim().split(','); + var contentTags = D.contentTags.trim().split(','); var tags = []; - oldTags.forEach((tag) => { + authorTags.forEach((tag) => { if (tag) { tags.unshift(`author_tag_${tag}`); } }); + contentTags.forEach((tag) => { + if (tag) { + tags.unshift(`content_${tag}`); + } + }); if (D.debugAllowed) { tags.unshift('debug_allowed'); } @@ -19434,6 +19523,14 @@ speechSynthesis.getVoices(); this.copyToClipboard(text); }; + $app.methods.copyLink = function (text) { + this.$message({ + message: 'Link copied to clipboard', + type: 'success' + }); + this.copyToClipboard(text); + }; + // #endregion // #region | App: VRCPlus Icons @@ -22223,6 +22320,9 @@ speechSynthesis.getVoices(); break; } } + if (!assetUrl) { + assetUrl = ref.assetUrl; + } var id = extractFileId(assetUrl); var version = parseInt(extractFileVersion(assetUrl), 10); if (!id || !version) { @@ -24326,7 +24426,7 @@ speechSynthesis.getVoices(); case 'offline': case 'private': case 'traveling': - case 'local': + case instanceId.startsWith('local'): case '': return false; } diff --git a/html/src/index.pug b/html/src/index.pug index 2029f17f..b1b298c4 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -1407,8 +1407,11 @@ html el-checkbox(v-model="setWorldTagsDialog.avatarScalingDisabled") {{ $t('dialog.set_world_tags.avatar_scaling_disabled') }} el-checkbox(v-model="setWorldTagsDialog.debugAllowed") {{ $t('dialog.set_world_tags.enable_debugging') }} div(style='font-size:12px;margin-top:10px') - | {{ $t('dialog.set_world_tags.seprator') }} #[br] - el-input(type="textarea" v-model="setWorldTagsDialog.tags" size="mini" show-word-limit :autosize="{ minRows:2, maxRows:5 }" placeholder="" style="margin-top:10px") + | {{ $t('dialog.set_world_tags.author_tags') }} #[br] + el-input(type="textarea" v-model="setWorldTagsDialog.authorTags" size="mini" show-word-limit :autosize="{ minRows:2, maxRows:5 }" placeholder="" style="margin-top:10px") + div(style='font-size:12px;margin-top:10px') + | {{ $t('dialog.set_world_tags.content_tags') }} #[br] + el-input(type="textarea" v-model="setWorldTagsDialog.contentTags" size="mini" show-word-limit :autosize="{ minRows:2, maxRows:5 }" placeholder="" style="margin-top:10px") template(#footer) div(style="display:flex") el-button(size="small" @click="setWorldTagsDialog.visible = false") {{ $t('dialog.set_world_tags.cancel') }} diff --git a/html/src/localization/strings/en.json b/html/src/localization/strings/en.json index 80de6358..ae5bbcdb 100644 --- a/html/src/localization/strings/en.json +++ b/html/src/localization/strings/en.json @@ -102,7 +102,9 @@ "visibility_tooltip": "Change Visibility", "rename_tooltip": "Rename", "clear_tooltip": "Clear", - "delete_tooltip": "Delete" + "delete_tooltip": "Delete", + "unavailable_tooltip": "Unavailable", + "sort_by": "Sort By" }, "friend_log": { "filter_placeholder": "Filter", @@ -376,6 +378,7 @@ "header": "Advanced", "launch_options": "Launch Options", "screenshot_metadata": "Screenshot Metadata", + "common_folders": "Common Folders", "pending_offline": { "header": "Pending Offline", "description": "Delay before marking user as offline (fixes false positives)", @@ -938,7 +941,8 @@ "header": "Set World Tags", "avatar_scaling_disabled": "Disable avatar scaling", "enable_debugging": "Enable world debugging for others", - "seprator": "Enter tags comma separated", + "author_tags": "Author Tags (comma separated)", + "content_tags": "Content Tags (comma separated)", "cancel": "Cancel", "save": "Save" }, diff --git a/html/src/mixins/tabs/favorites.pug b/html/src/mixins/tabs/favorites.pug index de816332..52909c57 100644 --- a/html/src/mixins/tabs/favorites.pug +++ b/html/src/mixins/tabs/favorites.pug @@ -13,6 +13,9 @@ mixin favoritesTab() el-collapse(v-if="$refs.menu && $refs.menu.activeIndex === 'favorite' && $refs.favoriteTabRef && $refs.favoriteTabRef.currentName === '0'" style="border:0") el-button(size="small" @click="showFriendExportDialog") {{ $t('view.favorite.export') }} el-button(size="small" @click="showFriendImportDialog") {{ $t('view.favorite.import') }} + 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") el-collapse-item(v-for="group in API.favoriteFriendGroups" :key="group.name") template(slot="title") span(v-text="group.displayName" style="font-weight:bold;font-size:14px;margin-left:10px") @@ -50,6 +53,9 @@ mixin favoritesTab() el-collapse(v-if="$refs.menu && $refs.menu.activeIndex === 'favorite' && $refs.favoriteTabRef && $refs.favoriteTabRef.currentName === '1'" style="border:0") el-button(size="small" @click="showWorldExportDialog") {{ $t('view.favorite.export') }} el-button(size="small" @click="showWorldImportDialog") {{ $t('view.favorite.import') }} + 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.vrchat_favorites') }} el-collapse-item(v-for="group in API.favoriteWorldGroups" :key="group.name") template(slot="title") @@ -79,6 +85,8 @@ mixin favoritesTab() el-button(type="text" size="mini" @click.stop style="margin-left:5px") el-checkbox(v-model="favorite.$selected") template(v-else-if="favorite.ref") + el-tooltip(v-if="favorite.deleted" placement="left" :content="$t('view.favorite.unavailable_tooltip')") + i.el-icon-warning(style="color:#f56c6c;margin-left:5px") el-tooltip(placement="left" :content="$t('view.favorite.move_tooltip')" :disabled="hideTooltips") el-dropdown(trigger="click" @click.native.stop size="mini" style="margin-left:5px") el-button(type="default" icon="el-icon-back" size="mini" circle) @@ -89,6 +97,8 @@ mixin favoritesTab() el-button(@click.stop="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") template(v-else) span(v-text="favorite.name || favorite.id") + el-tooltip(v-if="favorite.deleted" placement="left" :content="$t('view.favorite.unavailable_tooltip')") + i.el-icon-warning(style="color:#f56c6c;margin-left:5px") el-button(type="text" icon="el-icon-close" size="mini" @click.stop="deleteFavorite(favorite.id)" style="margin-left:5px") span(style="display:block;margin-top:20px") {{ $t('view.favorite.worlds.local_favorites') }} el-button(size="small" @click="promptNewLocalWorldFavoriteGroup" style="display:block;margin-top:10px") {{ $t('view.favorite.worlds.new_group') }} @@ -119,6 +129,9 @@ mixin favoritesTab() el-collapse(v-if="$refs.menu && $refs.menu.activeIndex === 'favorite' && $refs.favoriteTabRef && $refs.favoriteTabRef.currentName === '2'" style="border:0") el-button(size="small" @click="showAvatarExportDialog") {{ $t('view.favorite.export') }} el-button(size="small" @click="showAvatarImportDialog") {{ $t('view.favorite.import') }} + 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") el-collapse-item(v-for="group in API.favoriteAvatarGroups" :key="group.name") template(slot="title") span(v-text="group.displayName" style="font-weight:bold;font-size:14px;margin-left:10px") @@ -140,6 +153,8 @@ mixin favoritesTab() el-button(type="text" size="mini" @click.stop style="margin-left:5px") el-checkbox(v-model="favorite.$selected") template(v-else-if="favorite.ref") + el-tooltip(v-if="favorite.deleted" placement="left" :content="$t('view.favorite.unavailable_tooltip')") + i.el-icon-warning(style="color:#f56c6c;margin-left:5px") el-tooltip(placement="left" :content="$t('view.favorite.move_tooltip')" :disabled="hideTooltips") el-dropdown(trigger="click" @click.native.stop size="mini" style="margin-left:5px") el-button(type="default" icon="el-icon-back" size="mini" circle) diff --git a/html/src/mixins/tabs/playerList.pug b/html/src/mixins/tabs/playerList.pug index ad12fdf1..37117fcc 100644 --- a/html/src/mixins/tabs/playerList.pug +++ b/html/src/mixins/tabs/playerList.pug @@ -25,7 +25,9 @@ mixin playerListTab() | {{ $t('dialog.world.tags.cache') }} br location-world(:locationobject="currentInstanceLocation" :currentuserid="API.currentUser.id") - instance-info(:location="currentInstanceLocation.tag" :instance="currentInstanceWorld.instance" :friendcount="lastLocation.friendList.size" :updateelement="updateInstanceInfo") + span(v-if="lastLocation.playerList.size > 0" style="margin-left:5px") + | {{ lastLocation.playerList.size }} + | #[template(v-if="lastLocation.friendList.size > 0") ({{ lastLocation.friendList.size }})] |  ― #[timer(v-if="lastLocation.date" :epoch="lastLocation.date")] div(style="margin-top:5px") span(v-show="currentInstanceWorld.ref.name !== currentInstanceWorld.ref.description" v-text="currentInstanceWorld.ref.description" style="font-size:12px;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2") diff --git a/html/src/mixins/tabs/settings.pug b/html/src/mixins/tabs/settings.pug index a8254e3d..e2413ddf 100644 --- a/html/src/mixins/tabs/settings.pug +++ b/html/src/mixins/tabs/settings.pug @@ -379,6 +379,16 @@ mixin settingsTab() el-button(size="small" icon="el-icon-s-operation" @click="showVRChatConfig()") VRChat config.json el-button(size="small" icon="el-icon-s-operation" @click="showLaunchOptions()") {{ $t('view.settings.advanced.advanced.launch_options') }} el-button(size="small" icon="el-icon-picture" @click="showScreenshotMetadataDialog()") {{ $t('view.settings.advanced.advanced.screenshot_metadata') }} + //- Advanced | Common Folders + div.options-container + span.header {{ $t('view.settings.advanced.advanced.common_folders') }} + div.options-container-item(style="margin-top:15px") + el-button-group + el-button(size="small" icon="el-icon-folder" @click="AppApi.OpenVrcxAppDataFolder()") AppData (VRCX) + el-button(size="small" icon="el-icon-folder" @click="AppApi.OpenVrcAppDataFolder()") AppData + el-button(size="small" icon="el-icon-folder" @click="AppApi.OpenVrcPhotosFolder()") Photos + el-button(size="small" icon="el-icon-folder" @click="AppApi.OpenVrcScreenshotsFolder()") Screenshots + el-button(size="small" icon="el-icon-folder" @click="AppApi.OpenCrashVrcCrashDumps()") Crash Dumps //- Advanced | Primary Password div.options-container //- Advanced | Primary Password Header diff --git a/html/src/repository/database.js b/html/src/repository/database.js index b76606de..110e5e00 100644 --- a/html/src/repository/database.js +++ b/html/src/repository/database.js @@ -1842,6 +1842,20 @@ class Database { return date; } + async getGameLogWorldNameByWorldId(worldId) { + var worldName = ''; + await sqliteService.execute( + (dbRow) => { + worldName = dbRow[0]; + }, + 'SELECT world_name FROM gamelog_location WHERE world_id = @worldId ORDER BY id DESC LIMIT 1', + { + '@worldId': worldId + } + ); + return worldName; + } + async getModeration(userId) { var row = {}; await sqliteService.execute( @@ -2165,6 +2179,33 @@ class Database { return data; } + async getCachedAvatarById(id) { + var data = null; + await sqliteService.execute( + (dbRow) => { + data = { + id: dbRow[0], + // added_at: dbRow[1], + authorId: dbRow[2], + authorName: dbRow[3], + created_at: dbRow[4], + description: dbRow[5], + imageUrl: dbRow[6], + name: dbRow[7], + releaseStatus: dbRow[8], + thumbnailImageUrl: dbRow[9], + updated_at: dbRow[10], + version: dbRow[11] + }; + }, + `SELECT * FROM cache_avatar WHERE id = @id`, + { + '@id': id + } + ); + return data; + } + clearAvatarHistory() { sqliteService.executeNonQuery( `DELETE FROM ${Database.userPrefix}_avatar_history` @@ -2276,6 +2317,33 @@ class Database { return data; } + async getCachedWorldById(id) { + var data = null; + await sqliteService.execute( + (dbRow) => { + data = { + id: dbRow[0], + // added_at: dbRow[1], + authorId: dbRow[2], + authorName: dbRow[3], + created_at: dbRow[4], + description: dbRow[5], + imageUrl: dbRow[6], + name: dbRow[7], + releaseStatus: dbRow[8], + thumbnailImageUrl: dbRow[9], + updated_at: dbRow[10], + version: dbRow[11] + }; + }, + `SELECT * FROM cache_world WHERE id = @id`, + { + '@id': id + } + ); + return data; + } + async fixGameLogTraveling() { var travelingList = []; await sqliteService.execute((dbRow) => {