From 6b2d402b8b32eac6fd79f9f4824e2e6cbfab04cb Mon Sep 17 00:00:00 2001 From: Natsumi Date: Thu, 30 Jan 2025 18:02:53 +1300 Subject: [PATCH] Misc fixes --- Dotnet/AppApi/Cef/Folders.cs | 41 +++--- src-electron/main.js | 35 +++--- src/app.js | 70 +++++++---- src/app.scss | 2 +- src/mixins/dialogs/settings.pug | 29 +++-- src/mixins/tabs/favorites.pug | 213 ++++++++++++++++---------------- src/repository/database.js | 11 +- src/theme.dark.scss | 15 +++ 8 files changed, 236 insertions(+), 180 deletions(-) diff --git a/Dotnet/AppApi/Cef/Folders.cs b/Dotnet/AppApi/Cef/Folders.cs index 0ec20fba..4e4cbd7f 100644 --- a/Dotnet/AppApi/Cef/Folders.cs +++ b/Dotnet/AppApi/Cef/Folders.cs @@ -22,24 +22,31 @@ namespace VRCX public override string GetVRChatCacheLocation() { var defaultPath = Path.Join(GetVRChatAppDataLocation(), "Cache-WindowsPlayer"); - - var json = ReadConfigFile(); - if (string.IsNullOrEmpty(json)) + try + { + var json = ReadConfigFile(); + if (string.IsNullOrEmpty(json)) + return defaultPath; + + var obj = JsonConvert.DeserializeObject(json); + if (obj["cache_directory"] == null) + return defaultPath; + + var cacheDir = (string)obj["cache_directory"]; + if (string.IsNullOrEmpty(cacheDir)) + return defaultPath; + + var cachePath = Path.Join(cacheDir, "Cache-WindowsPlayer"); + if (!Directory.Exists(cacheDir)) + return defaultPath; + + return cachePath; + } + catch (Exception e) + { + logger.Error(e); return defaultPath; - - var obj = JsonConvert.DeserializeObject(json); - if (obj["cache_directory"] == null) - return defaultPath; - - var cacheDir = (string)obj["cache_directory"]; - if (string.IsNullOrEmpty(cacheDir)) - return defaultPath; - - var cachePath = Path.Join(cacheDir, "Cache-WindowsPlayer"); - if (!Directory.Exists(cacheDir)) - return defaultPath; - - return cachePath; + } } public override string GetVRChatPhotosLocation() diff --git a/src-electron/main.js b/src-electron/main.js index 7fc77e8f..8d77547d 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -18,7 +18,6 @@ if (!isDotNetInstalled()) { app.quit(); return; } -console.log('DOTNET_ROOT:', process.env.DOTNET_ROOT); // get launch arguments const args = process.argv.slice(1); @@ -125,33 +124,37 @@ function relaunchWithArgs(args) { } const fullArgs = ['--ozone-platform-hint=auto', ...args]; - + let execPath = process.execPath; - + if (appImagePath) { execPath = appImagePath; fullArgs.unshift('--appimage-extract-and-run'); } - + console.log('Relaunching with args:', fullArgs); - + const child = spawn(execPath, fullArgs, { detached: true, stdio: 'inherit' }); - + child.unref(); app.exit(0); } function createWindow() { - if (process.platform === 'linux' && !process.argv.includes('--ozone-platform-hint=auto') && !x11) { + if ( + process.platform === 'linux' && + !process.argv.includes('--ozone-platform-hint=auto') && + !x11 + ) { relaunchWithArgs(process.argv.slice(1)); } app.commandLine.appendSwitch('enable-speech-dispatcher'); - + const x = parseInt(VRCXStorage.Get('VRCX_LocationX')) || 0; const y = parseInt(VRCXStorage.Get('VRCX_LocationY')) || 0; const width = parseInt(VRCXStorage.Get('VRCX_SizeWidth')) || 1920; @@ -395,6 +398,16 @@ async function installVRCX() { return; } + await createDesktopFile(); + dialog.showMessageBox({ + type: 'info', + title: 'VRCX', + message: 'VRCX has been installed successfully.', + detail: 'You can now find VRCX in your ~/Applications folder.' + }); +} + +async function createDesktopFile() { // Download the icon and save it to the target directory const iconUrl = 'https://raw.githubusercontent.com/vrcx-team/VRCX/master/VRCX.png'; @@ -430,12 +443,6 @@ StartupWMClass=VRCX console.error('Error downloading icon:', err); dialog.showErrorBox('VRCX', 'Failed to download the icon.'); }); - dialog.showMessageBox({ - type: 'info', - title: 'VRCX', - message: 'VRCX has been installed successfully.', - detail: 'You can now find VRCX in your ~/Applications folder.' - }); } function downloadIcon(url, targetPath) { diff --git a/src/app.js b/src/app.js index 4b02403e..8b04307c 100644 --- a/src/app.js +++ b/src/app.js @@ -7953,10 +7953,12 @@ console.log(`isLinux: ${LINUX}`); 'VRCX_feedTableVIPFilter', false ); - $app.data.gameLogTable.vip = await configRepository.getBool( - 'VRCX_gameLogTableVIPFilter', - false - ); + $app.data.gameLogTable.vip = false; + // gameLog loads before favorites + // await configRepository.getBool( + // 'VRCX_gameLogTableVIPFilter', + // false + // ); $app.data.gameLogTable.filter = JSON.parse( await configRepository.getString('VRCX_gameLogTableFilters', '[]') ); @@ -16639,12 +16641,14 @@ console.log(`isLinux: ${LINUX}`); }, cache_directory: { name: $t('dialog.config_json.cache_directory'), - default: '%AppData%\\..\\LocalLow\\VRChat\\VRChat' + default: '%AppData%\\..\\LocalLow\\VRChat\\VRChat', + folderBrowser: true }, picture_output_folder: { name: $t('dialog.config_json.picture_directory'), // my pictures folder - default: `%UserProfile%\\Pictures\\VRChat` + default: `%UserProfile%\\Pictures\\VRChat`, + folderBrowser: true }, // dynamic_bone_max_affected_transform_count: { // name: 'Dynamic Bones Limit Max Transforms (0 disable all transforms)', @@ -16676,6 +16680,20 @@ console.log(`isLinux: ${LINUX}`); } }; + $app.methods.openConfigFolderBrowser = async function (value) { + var oldPath = this.VRChatConfigFile[value]; + var newPath = await this.folderSelectorDialog(oldPath); + if (newPath) { + this.VRChatConfigFile[value] = newPath; + } + this.redrawVRChatConfigDialog(); + }; + + $app.methods.redrawVRChatConfigDialog = function () { + this.VRChatConfigDialog.visible = false; + this.VRChatConfigDialog.visible = true; + }; + $app.methods.saveVRChatConfigFile = function () { for (var item in this.VRChatConfigFile) { if (item === 'picture_output_split_by_date') { @@ -16760,11 +16778,13 @@ console.log(`isLinux: ${LINUX}`); $app.methods.setVRChatCameraResolution = function (res) { this.VRChatConfigFile.camera_res_height = res.height; this.VRChatConfigFile.camera_res_width = res.width; + this.redrawVRChatConfigDialog(); }; $app.methods.setVRChatScreenshotResolution = function (res) { this.VRChatConfigFile.screenshot_res_height = res.height; this.VRChatConfigFile.screenshot_res_width = res.width; + this.redrawVRChatConfigDialog(); }; $app.methods.getVRChatSpoutResolution = function () { @@ -16781,6 +16801,7 @@ console.log(`isLinux: ${LINUX}`); $app.methods.setVRChatSpoutResolution = function (res) { this.VRChatConfigFile.camera_spout_res_height = res.height; this.VRChatConfigFile.camera_spout_res_width = res.width; + this.redrawVRChatConfigDialog(); }; // Auto Launch Shortcuts @@ -21055,9 +21076,7 @@ console.log(`isLinux: ${LINUX}`); '' ); - $app.data.userGeneratedContentDialog = { - visible: false - }; + $app.data.folderSelectorDialogVisible = false; $app.methods.setUGCFolderPath = async function (path) { await configRepository.setString('VRCX_userGeneratedContentPath', path); @@ -21075,24 +21094,27 @@ console.log(`isLinux: ${LINUX}`); await AppApi.OpenUGCPhotosFolder(this.ugcFolderPath); }; - $app.methods.openUGCFolderSelector = async function () { - var D = this.userGeneratedContentDialog; - - if (D.visible) return; - - D.visible = true; - var newUGCFolder; - if (LINUX) { - newUGCFolder = await window.electron.openDirectoryDialog(); - } else { - newUGCFolder = await AppApi.OpenFolderSelectorDialog( - this.ugcFolderPath - ); + $app.methods.folderSelectorDialog = async function (oldPath) { + if (this.folderSelectorDialogVisible) return; + if (!oldPath) { + oldPath = ''; } - D.visible = false; + this.folderSelectorDialogVisible = true; + var newFolder = ''; + if (LINUX) { + newFolder = await window.electron.openDirectoryDialog(); + } else { + newFolder = await AppApi.OpenFolderSelectorDialog(oldPath); + } - await this.setUGCFolderPath(newUGCFolder); + this.folderSelectorDialogVisible = false; + return newFolder; + }; + + $app.methods.openUGCFolderSelector = async function () { + var path = await this.folderSelectorDialog(this.ugcFolderPath); + await this.setUGCFolderPath(path); }; // avatar database provider diff --git a/src/app.scss b/src/app.scss index 1179d359..5f5165fa 100644 --- a/src/app.scss +++ b/src/app.scss @@ -951,7 +951,7 @@ i.x-status-icon.red { } .x-text-added { - color: rgb(76, 255, 80); + color: rgb(35, 188, 35); background-color: rgba(76, 255, 80, 0.2); padding: 2px 2px; border-radius: 4px; diff --git a/src/mixins/dialogs/settings.pug b/src/mixins/dialogs/settings.pug index 33020182..cda123ac 100644 --- a/src/mixins/dialogs/settings.pug +++ b/src/mixins/dialogs/settings.pug @@ -37,18 +37,23 @@ mixin settings div(style='margin-top: 10px') span(style='margin-right: 5px') {{ $t('dialog.config_json.delete_old_cache') }} el-button(size='small' style='margin-left: 5px' icon='el-icon-folder-delete' @click='sweepVRChatCache()') {{ $t('dialog.config_json.sweep_cache') }} - div(style='display: inline-block; margin-top: 10px' v-for='(item, value) in VRChatConfigList' :key='value') - span(v-text='item.name' style='word-break: keep-all') - | : - el-input( - v-model='VRChatConfigFile[value]' - :placeholder='item.default' - size='mini' - :type='item.type ? item.type : "text"' - :min='item.min' - :max='item.max' - style='margin-top: 5px') - br + div(style='display: block; margin-top: 10px' v-for='(item, value) in VRChatConfigList' :key='value') + span(style='word-break: keep-all') {{ item.name }}: + div(style='display: flex') + el-button( + v-if='item.folderBrowser' + size='mini' + icon='el-icon-folder-opened' + @click='openConfigFolderBrowser(value)') + el-input( + v-model='VRChatConfigFile[value]' + :placeholder='item.default' + size='mini' + :type='item.type ? item.type : "text"' + :min='item.min' + :max='item.max' + @change='redrawVRChatConfigDialog' + style='flex: 1; margin-top: 5px') div(style='display: inline-block; margin-top: 10px') span {{ $t('dialog.config_json.camera_resolution') }} br diff --git a/src/mixins/tabs/favorites.pug b/src/mixins/tabs/favorites.pug index 31a78cae..ad620948 100644 --- a/src/mixins/tabs/favorites.pug +++ b/src/mixins/tabs/favorites.pug @@ -27,6 +27,7 @@ mixin favoritesTab el-radio-group(v-model='sortFavorites' @change='saveSortFavoritesOption') el-radio(:label='false') {{ $t('view.settings.appearance.appearance.sort_favorite_by_name') }} el-radio(:label='true') {{ $t('view.settings.appearance.appearance.sort_favorite_by_date') }} + span(style='display: block; margin-top: 30px') {{ $t('view.favorite.avatars.vrchat_favorites') }} el-collapse(style='border: 0') el-collapse-item(v-for='group in API.favoriteFriendGroups' :key='group.name') template(slot='title') @@ -75,25 +76,25 @@ mixin favoritesTab :link='false') span(v-else v-text='favorite.ref.statusDescription') template(v-if='editFavoritesMode') - 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-dropdown( + trigger='click' + @click.native.stop + size='mini' + style='margin-left: 5px') + el-tooltip( + placement='left' + :content='$t("view.favorite.move_tooltip")' + :disabled='hideTooltips') el-button(type='default' icon='el-icon-back' size='mini' circle) - el-dropdown-menu(#default='dropdown') - template( - v-if='groupAPI.name !== group.name' - v-for='groupAPI in API.favoriteFriendGroups' - :key='groupAPI.name') - el-dropdown-item( - style='display: block; margin: 10px 0' - @click.native='moveFavorite(favorite.ref, groupAPI, "friend")' - :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) + el-dropdown-menu(#default='dropdown') + template( + v-if='groupAPI.name !== group.name' + v-for='groupAPI in API.favoriteFriendGroups' + :key='groupAPI.name') + el-dropdown-item( + style='display: block; margin: 10px 0' + @click.native='moveFavorite(favorite.ref, groupAPI, "friend")' + :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) el-button(type='text' size='mini' @click.stop style='margin-left: 5px') el-checkbox(v-model='favorite.$selected') template(v-else) @@ -168,7 +169,7 @@ mixin favoritesTab .avatar .detail span(v-text='favorite.id') - span(style='display: block; margin-top: 20px') {{ $t('view.favorite.worlds.vrchat_favorites') }} + span(style='display: block; margin-top: 20px') {{ $t('view.favorite.worlds.vrchat_favorites') }} el-collapse(style='border: 0') el-collapse-item(v-for='group in API.favoriteWorldGroups' :key='group.name') template(slot='title') @@ -182,24 +183,20 @@ mixin favoritesTab :type='userFavoriteWorldsStatusForFavTab(group.visibility)' effect='plain') {{ group.visibility.charAt(0).toUpperCase() + group.visibility.slice(1) }} span(style='color: #909399; font-size: 12px; margin-left: 10px') {{ group.count }}/{{ group.capacity }} - el-tooltip( - placement='top' - :content='$t("view.favorite.visibility_tooltip")' - :disabled='hideTooltips') - el-dropdown( - trigger='click' - @click.native.stop - size='mini' - style='margin-left: 10px') + el-dropdown(trigger='click' @click.native.stop size='mini' style='margin-left: 10px') + el-tooltip( + placement='top' + :content='$t("view.favorite.visibility_tooltip")' + :disabled='hideTooltips') el-button(type='default' icon='el-icon-view' size='mini' circle) - el-dropdown-menu(#default='dropdown') - el-dropdown-item( - v-if='group.visibility !== visibility' - v-for='visibility in worldGroupVisibilityOptions' - :key='visibility' - style='display: block; margin: 10px 0' - v-text='visibility.charAt(0).toUpperCase() + visibility.slice(1)' - @click.native='changeWorldGroupVisibility(group.name, visibility)') + el-dropdown-menu(#default='dropdown') + el-dropdown-item( + v-if='group.visibility !== visibility' + v-for='visibility in worldGroupVisibilityOptions' + :key='visibility' + style='display: block; margin: 10px 0' + v-text='visibility.charAt(0).toUpperCase() + visibility.slice(1)' + @click.native='changeWorldGroupVisibility(group.name, visibility)') el-tooltip( placement='top' :content='$t("view.favorite.rename_tooltip")' @@ -235,25 +232,25 @@ mixin favoritesTab span.extra(v-if='favorite.ref.occupants') {{ favorite.ref.authorName }} ({{ favorite.ref.occupants }}) span.extra(v-else v-text='favorite.ref.authorName') template(v-if='editFavoritesMode') - 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-dropdown( + trigger='click' + @click.native.stop + size='mini' + style='margin-left: 5px') + el-tooltip( + placement='left' + :content='$t("view.favorite.move_tooltip")' + :disabled='hideTooltips') el-button(type='default' icon='el-icon-back' size='mini' circle) - el-dropdown-menu(#default='dropdown') - template( - v-if='groupAPI.name !== group.name' - v-for='groupAPI in API.favoriteWorldGroups' - :key='groupAPI.name') - el-dropdown-item( - style='display: block; margin: 10px 0' - @click.native='moveFavorite(favorite.ref, groupAPI, "world")' - :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) + el-dropdown-menu(#default='dropdown') + template( + v-if='groupAPI.name !== group.name' + v-for='groupAPI in API.favoriteWorldGroups' + :key='groupAPI.name') + el-dropdown-item( + style='display: block; margin: 10px 0' + @click.native='moveFavorite(favorite.ref, groupAPI, "world")' + :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) el-button(type='text' size='mini' @click.stop style='margin-left: 5px') el-checkbox(v-model='favorite.$selected') template(v-else) @@ -370,24 +367,24 @@ mixin favoritesTab span.extra(v-if='favorite.occupants') {{ favorite.authorName }} ({{ favorite.occupants }}) span.extra(v-else v-text='favorite.authorName') template(v-if='editFavoritesMode') - el-tooltip( - placement='left' - :content='$t("view.favorite.copy_tooltip")' - :disabled='hideTooltips') - el-dropdown( - trigger='click' - @click.native.stop - size='mini' - style='margin-left: 5px') - el-button(type='default' icon='el-icon-s-order' size='mini' circle) - el-dropdown-menu(#default='dropdown') - template( - v-for='groupAPI in API.favoriteWorldGroups' - :key='groupAPI.name') - el-dropdown-item( - style='display: block; margin: 10px 0' - @click.native='addFavoriteWorld(favorite, groupAPI, true)' - :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) + el-dropdown( + trigger='click' + @click.native.stop + size='mini' + style='margin-left: 5px') + el-tooltip( + placement='left' + :content='$t("view.favorite.copy_tooltip")' + :disabled='hideTooltips') + el-button(type='default' icon='el-icon-back' size='mini' circle) + el-dropdown-menu(#default='dropdown') + template( + v-for='groupAPI in API.favoriteWorldGroups' + :key='groupAPI.name') + el-dropdown-item( + style='display: block; margin: 10px 0' + @click.native='addFavoriteWorld(favorite, groupAPI, true)' + :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) template(v-else) el-tooltip( placement='left' @@ -511,25 +508,25 @@ mixin favoritesTab span.name(v-text='favorite.ref.name') span.extra(v-text='favorite.ref.authorName') template(v-if='editFavoritesMode') - el-tooltip( - placement='top' - :content='$t("view.favorite.move_tooltip")' - :disabled='hideTooltips') - el-dropdown( - trigger='click' - @click.native.stop - size='mini' - style='margin-left: 5px') + el-dropdown( + trigger='click' + @click.native.stop + size='mini' + style='margin-left: 5px') + el-tooltip( + placement='top' + :content='$t("view.favorite.move_tooltip")' + :disabled='hideTooltips') el-button(type='default' icon='el-icon-back' size='mini' circle) - el-dropdown-menu(#default='dropdown') - template( - v-if='groupAPI.name !== group.name' - v-for='groupAPI in API.favoriteAvatarGroups' - :key='groupAPI.name') - el-dropdown-item( - style='display: block; margin: 10px 0' - @click.native='moveFavorite(favorite.ref, groupAPI, "avatar")' - :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) + el-dropdown-menu(#default='dropdown') + template( + v-if='groupAPI.name !== group.name' + v-for='groupAPI in API.favoriteAvatarGroups' + :key='groupAPI.name') + el-dropdown-item( + style='display: block; margin: 10px 0' + @click.native='moveFavorite(favorite.ref, groupAPI, "avatar")' + :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) el-button(type='text' size='mini' @click.stop style='margin-left: 5px') el-checkbox(v-model='favorite.$selected') template(v-else) @@ -701,24 +698,24 @@ mixin favoritesTab span.name(v-text='favorite.name') span.extra(v-text='favorite.authorName') template(v-if='editFavoritesMode') - el-tooltip( - placement='left' - :content='$t("view.favorite.copy_tooltip")' - :disabled='hideTooltips') - el-dropdown( - trigger='click' - @click.native.stop - size='mini' - style='margin-left: 5px') - el-button(type='default' icon='el-icon-s-order' size='mini' circle) - el-dropdown-menu(#default='dropdown') - template( - v-for='groupAPI in API.favoriteAvatarGroups' - :key='groupAPI.name') - el-dropdown-item( - style='display: block; margin: 10px 0' - @click.native='addFavoriteAvatar(favorite, groupAPI, true)' - :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) + el-dropdown( + trigger='click' + @click.native.stop + size='mini' + style='margin-left: 5px') + el-tooltip( + placement='left' + :content='$t("view.favorite.copy_tooltip")' + :disabled='hideTooltips') + el-button(type='default' icon='el-icon-back' size='mini' circle) + el-dropdown-menu(#default='dropdown') + template( + v-for='groupAPI in API.favoriteAvatarGroups' + :key='groupAPI.name') + el-dropdown-item( + style='display: block; margin: 10px 0' + @click.native='addFavoriteAvatar(favorite, groupAPI, true)' + :disabled='groupAPI.count >= groupAPI.capacity') {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) template(v-else) el-tooltip( placement='left' diff --git a/src/repository/database.js b/src/repository/database.js index 6a4b1ab9..45777d6b 100644 --- a/src/repository/database.js +++ b/src/repository/database.js @@ -1660,10 +1660,13 @@ class Database { let vipQuery = ''; if (vipList.length > 0) { vipQuery = 'AND user_id IN ('; - vipList.forEach((vip, i) => { - vipQuery += `'${vip.replaceAll("'", "''")}', `; - }); - vipQuery += "'')"; + for (var i = 0; i < vipList.length; i++) { + vipQuery += `'${vipList[i].replaceAll("'", "''")}'`; + if (i < vipList.length - 1) { + vipQuery += ', '; + } + } + vipQuery += ')'; } var location = true; var onplayerjoined = true; diff --git a/src/theme.dark.scss b/src/theme.dark.scss index 926d5ef1..78c85b4a 100644 --- a/src/theme.dark.scss +++ b/src/theme.dark.scss @@ -417,3 +417,18 @@ button { .el-color-picker__panel { background-color: #222; } + +.x-text-removed { + text-decoration: line-through; + color: #ff4444; + background-color: rgba(255, 0, 0, 0.2); + padding: 2px 2px; + border-radius: 4px; +} + +.x-text-added { + color: rgb(76, 255, 80); + background-color: rgba(76, 255, 80, 0.2); + padding: 2px 2px; + border-radius: 4px; +}