diff --git a/html/package-lock.json b/html/package-lock.json index 6a492929..fa5a76b5 100644 --- a/html/package-lock.json +++ b/html/package-lock.json @@ -35,8 +35,10 @@ "vue-data-tables": "^3.4.5", "vue-i18n": "^8.28.2", "vue-lazyload": "^1.3.4", + "vue-loader": "^15.11.1", "vue-markdown": "^2.2.4", "vue-marquee-text-component": "^1.2.0", + "vue-template-compiler": "^2.6.14", "webpack": "^5.96.1", "webpack-cli": "^5.1.4", "worker-timers": "^8.0.11", @@ -2204,6 +2206,93 @@ "undici-types": "~6.20.0" } }, + "node_modules/@vue/component-compiler-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", + "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", + "dev": true, + "dependencies": { + "consolidate": "^0.15.1", + "hash-sum": "^1.0.2", + "lru-cache": "^4.1.2", + "merge-source-map": "^1.1.0", + "postcss": "^7.0.36", + "postcss-selector-parser": "^6.0.2", + "source-map": "~0.6.1", + "vue-template-es2015-compiler": "^1.9.0" + }, + "optionalDependencies": { + "prettier": "^1.18.2 || ^2.0.0" + } + }, + "node_modules/@vue/component-compiler-utils/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/@vue/component-compiler-utils/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/@vue/component-compiler-utils/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@vue/component-compiler-utils/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@vue/component-compiler-utils/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "optional": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/@vue/component-compiler-utils/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -2630,6 +2719,12 @@ "node": "*" } }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -2891,6 +2986,19 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/consolidate": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", + "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", + "deprecated": "Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog", + "dev": true, + "dependencies": { + "bluebird": "^3.1.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/constantinople": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", @@ -3054,6 +3162,12 @@ "node": ">=4" } }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -3873,6 +3987,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", + "dev": true + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -4547,6 +4667,15 @@ "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", "dev": true }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -5100,6 +5229,12 @@ "asap": "~2.0.3" } }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, "node_modules/pug": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz", @@ -6151,6 +6286,12 @@ "npm": ">= 3.0.0" } }, + "node_modules/vue-hot-reload-api": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", + "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", + "dev": true + }, "node_modules/vue-i18n": { "version": "8.28.2", "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.28.2.tgz", @@ -6163,6 +6304,34 @@ "integrity": "sha512-K0frbPQJuvFHVpdl/ov5CqCR/CHWeLGs8E8V1d/09DIETqBjeGhC1fLMmwUy3Go2Yd/VX610AZ7Mdn4B54592Q==", "dev": true }, + "node_modules/vue-loader": { + "version": "15.11.1", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.11.1.tgz", + "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==", + "dev": true, + "dependencies": { + "@vue/component-compiler-utils": "^3.1.0", + "hash-sum": "^1.0.2", + "loader-utils": "^1.1.0", + "vue-hot-reload-api": "^2.3.0", + "vue-style-loader": "^4.1.0" + }, + "peerDependencies": { + "css-loader": "*", + "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0" + }, + "peerDependenciesMeta": { + "cache-loader": { + "optional": true + }, + "prettier": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, "node_modules/vue-markdown": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/vue-markdown/-/vue-markdown-2.2.4.tgz", @@ -6205,6 +6374,32 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/vue-style-loader": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", + "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", + "dev": true, + "dependencies": { + "hash-sum": "^1.0.2", + "loader-utils": "^1.0.2" + } + }, + "node_modules/vue-template-compiler": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", + "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.1.0" + } + }, + "node_modules/vue-template-es2015-compiler": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", + "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", + "dev": true + }, "node_modules/watchpack": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", diff --git a/html/package.json b/html/package.json index 025670f1..b043cb6c 100644 --- a/html/package.json +++ b/html/package.json @@ -52,8 +52,10 @@ "vue-data-tables": "^3.4.5", "vue-i18n": "^8.28.2", "vue-lazyload": "^1.3.4", + "vue-loader": "^15.11.1", "vue-markdown": "^2.2.4", "vue-marquee-text-component": "^1.2.0", + "vue-template-compiler": "^2.6.14", "webpack": "^5.96.1", "webpack-cli": "^5.1.4", "worker-timers": "^8.0.11", diff --git a/html/src/app.js b/html/src/app.js index a14a7f38..76714188 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -33,6 +33,9 @@ import _apiInit from './classes/apiInit.js'; import _apiRequestHandler from './classes/apiRequestHandler.js'; import _vrcxJsonStorage from './classes/vrcxJsonStorage.js'; +// components +import SimpleSwitch from './components/settings/SimpleSwitch.vue'; + // main app classes import _sharedFeed from './classes/sharedFeed.js'; import _prompts from './classes/prompts.js'; @@ -141,6 +144,9 @@ speechSynthesis.getVoices(); ...$utils }, watch: {}, + components: { + SimpleSwitch + }, el: '#x-app', async mounted() { await this.initLanguage(); @@ -4016,6 +4022,9 @@ speechSynthesis.getVoices(); } }; $app.methods.enablePrimaryPasswordChange = function () { + // The function is only called in adv settings + this.enablePrimaryPassword = !this.enablePrimaryPassword; + this.enablePrimaryPasswordDialog.password = ''; this.enablePrimaryPasswordDialog.rePassword = ''; if (this.enablePrimaryPassword) { @@ -8077,8 +8086,87 @@ speechSynthesis.getVoices(); false ); $app.data.friendLogTable.filters[2].value = $app.data.hideUnfriends; - $app.methods.saveOpenVROption = async function () { + $app.methods.saveOpenVROption = async function (configKey = '') { + switch (configKey) { + case 'openVR': + this.openVR = !this.openVR; + break; + case 'VRCX_hidePrivateFromFeed': + this.hidePrivateFromFeed = !this.hidePrivateFromFeed; + break; + case 'VRCX_hideDevicesFromFeed': + this.hideDevicesFromFeed = !this.hideDevicesFromFeed; + break; + case 'VRCX_vrOverlayCpuUsage': + this.vrOverlayCpuUsage = !this.vrOverlayCpuUsage; + break; + case 'VRCX_hideUptimeFromFeed': + this.hideUptimeFromFeed = !this.hideUptimeFromFeed; + break; + case 'VRCX_pcUptimeOnFeed': + this.pcUptimeOnFeed = !this.pcUptimeOnFeed; + break; + case 'VRCX_overlayNotifications': + this.overlayNotifications = !this.overlayNotifications; + break; + case 'VRCX_overlayWrist': + this.overlayWrist = !this.overlayWrist; + break; + case 'VRCX_xsNotifications': + this.xsNotifications = !this.xsNotifications; + break; + case 'VRCX_ovrtHudNotifications': + this.ovrtHudNotifications = !this.ovrtHudNotifications; + break; + case 'VRCX_ovrtWristNotifications': + this.ovrtWristNotifications = !this.ovrtWristNotifications; + break; + case 'VRCX_imageNotifications': + this.imageNotifications = !this.imageNotifications; + break; + case 'VRCX_afkDesktopToast': + this.afkDesktopToast = !this.afkDesktopToast; + break; + case 'VRCX_notificationTTSNickName': + this.notificationTTSNickName = !this.notificationTTSNickName; + break; + case 'VRCX_minimalFeed': + this.minimalFeed = !this.minimalFeed; + break; + case 'displayVRCPlusIconsAsAvatar': + this.displayVRCPlusIconsAsAvatar = + !this.displayVRCPlusIconsAsAvatar; + break; + case 'VRCX_hideTooltips': + this.hideTooltips = !this.hideTooltips; + break; + case 'VRCX_hideNicknames': + this.hideNicknames = !this.hideNicknames; + break; + case 'VRCX_autoSweepVRChatCache': + this.autoSweepVRChatCache = !this.autoSweepVRChatCache; + break; + case 'VRCX_relaunchVRChatAfterCrash': + this.relaunchVRChatAfterCrash = !this.relaunchVRChatAfterCrash; + break; + case 'VRCX_vrcQuitFix': + this.vrcQuitFix = !this.vrcQuitFix; + break; + case 'VRCX_vrBackgroundEnabled': + this.vrBackgroundEnabled = !this.vrBackgroundEnabled; + break; + case 'VRCX_avatarRemoteDatabase': + this.avatarRemoteDatabase = !this.avatarRemoteDatabase; + break; + case 'VRCX_udonExceptionLogging': + this.udonExceptionLogging = !this.udonExceptionLogging; + break; + default: + break; + } + await configRepository.setBool('openVR', this.openVR); + await configRepository.setBool('openVRAlways', this.openVRAlways); await configRepository.setBool( 'VRCX_overlaybutton', @@ -8089,108 +8177,137 @@ speechSynthesis.getVoices(); this.overlayHand = 0; } await configRepository.setInt('VRCX_overlayHand', this.overlayHand); + await configRepository.setBool( 'VRCX_hidePrivateFromFeed', this.hidePrivateFromFeed ); + await configRepository.setBool( 'VRCX_hideDevicesFromFeed', this.hideDevicesFromFeed ); + await configRepository.setBool( 'VRCX_vrOverlayCpuUsage', this.vrOverlayCpuUsage ); + await configRepository.setBool( 'VRCX_hideUptimeFromFeed', this.hideUptimeFromFeed ); + await configRepository.setBool( 'VRCX_pcUptimeOnFeed', this.pcUptimeOnFeed ); + await configRepository.setBool( 'VRCX_overlayNotifications', this.overlayNotifications ); + await configRepository.setBool('VRCX_overlayWrist', this.overlayWrist); + await configRepository.setBool( 'VRCX_xsNotifications', this.xsNotifications ); + await configRepository.setBool( 'VRCX_ovrtHudNotifications', this.ovrtHudNotifications ); + await configRepository.setBool( 'VRCX_ovrtWristNotifications', this.ovrtWristNotifications ); + await configRepository.setBool( 'VRCX_imageNotifications', this.imageNotifications ); + await configRepository.setString( 'VRCX_desktopToast', this.desktopToast ); + await configRepository.setBool( 'VRCX_afkDesktopToast', this.afkDesktopToast ); + await configRepository.setString( 'VRCX_overlayToast', this.overlayToast ); + await configRepository.setBool( 'VRCX_notificationTTSNickName', this.notificationTTSNickName ); + await configRepository.setBool('VRCX_minimalFeed', this.minimalFeed); + await configRepository.setBool( 'displayVRCPlusIconsAsAvatar', this.displayVRCPlusIconsAsAvatar ); + await configRepository.setBool('VRCX_hideTooltips', this.hideTooltips); + await configRepository.setBool( 'VRCX_hideNicknames', this.hideNicknames ); + await configRepository.setBool( 'VRCX_autoSweepVRChatCache', this.autoSweepVRChatCache ); + await configRepository.setBool( 'VRCX_relaunchVRChatAfterCrash', this.relaunchVRChatAfterCrash ); + await configRepository.setBool('VRCX_vrcQuitFix', this.vrcQuitFix); + await configRepository.setBool( 'VRCX_vrBackgroundEnabled', this.vrBackgroundEnabled ); + await configRepository.setBool( 'VRCX_avatarRemoteDatabase', this.avatarRemoteDatabase ); + await configRepository.setBool( 'VRCX_instanceUsersSortAlphabetical', this.instanceUsersSortAlphabetical ); + await configRepository.setBool( 'VRCX_randomUserColours', this.randomUserColours ); + await configRepository.setBool( 'VRCX_udonExceptionLogging', this.udonExceptionLogging ); + this.updateSharedFeed(true); this.updateVRConfigVars(); this.updateVRLastLocation(); AppApi.ExecuteVrOverlayFunction('notyClear', ''); this.updateOpenVR(); }; + $app.methods.saveSortFavoritesOption = async function () { this.getLocalWorldFavorites(); await configRepository.setBool( @@ -8198,7 +8315,14 @@ speechSynthesis.getVoices(); this.sortFavorites ); }; - $app.methods.saveUserDialogOption = async function () { + + $app.methods.saveUserDialogOption = async function (configKey = '') { + if (configKey === 'VRCX_hideUserNotes') { + this.hideUserNotes = !this.hideUserNotes; + } else { + this.hideUserMemos = !this.hideUserMemos; + } + await configRepository.setBool( 'VRCX_hideUserNotes', this.hideUserNotes @@ -8208,7 +8332,10 @@ speechSynthesis.getVoices(); this.hideUserMemos ); }; + $app.methods.saveFriendLogOptions = async function () { + // The function is only called in adv settings + this.hideUnfriends = !this.hideUnfriends; await configRepository.setBool( 'VRCX_hideUnfriends', this.hideUnfriends @@ -8370,38 +8497,78 @@ speechSynthesis.getVoices(); 'true'; $app.data.disableWorldDatabase = (await VRCXStorage.Get('VRCX_DisableWorldDatabase')) === 'true'; - $app.methods.saveVRCXWindowOption = async function () { + + $app.methods.saveVRCXWindowOption = async function (configKey = '') { + switch (configKey) { + case 'VRCX_StartAtWindowsStartup': + this.isStartAtWindowsStartup = !this.isStartAtWindowsStartup; + break; + case 'VRCX_saveInstancePrints': + this.saveInstancePrints = !this.saveInstancePrints; + break; + case 'VRCX_saveInstanceStickers': + this.saveInstanceStickers = !this.saveInstanceStickers; + break; + case 'VRCX_StartAsMinimizedState': + this.isStartAsMinimizedState = !this.isStartAsMinimizedState; + break; + case 'VRCX_CloseToTray': + this.isCloseToTray = !this.isCloseToTray; + break; + case 'VRCX_DisableWorldDatabase': + this.disableWorldDatabase = !this.disableWorldDatabase; + break; + case 'VRCX_DisableGpuAcceleration': + this.disableGpuAcceleration = !this.disableGpuAcceleration; + break; + case 'VRCX_DisableVrOverlayGpuAcceleration': + this.disableVrOverlayGpuAcceleration = + !this.disableVrOverlayGpuAcceleration; + break; + default: + break; + } + await configRepository.setBool( 'VRCX_StartAtWindowsStartup', this.isStartAtWindowsStartup ); + await configRepository.setBool( 'VRCX_saveInstancePrints', this.saveInstancePrints ); + await configRepository.setBool( 'VRCX_saveInstanceStickers', this.saveInstanceStickers ); + VRCXStorage.Set( 'VRCX_StartAsMinimizedState', this.isStartAsMinimizedState.toString() ); + VRCXStorage.Set('VRCX_CloseToTray', this.isCloseToTray.toString()); + VRCXStorage.Set( 'VRCX_DisableWorldDatabase', this.disableWorldDatabase.toString() ); + VRCXStorage.Set( 'VRCX_DisableGpuAcceleration', this.disableGpuAcceleration.toString() ); + VRCXStorage.Set( 'VRCX_DisableVrOverlayGpuAcceleration', this.disableVrOverlayGpuAcceleration.toString() ); + AppApi.SetStartup(this.isStartAtWindowsStartup); }; + $app.data.photonEventOverlay = await configRepository.getBool( 'VRCX_PhotonEventOverlay', false @@ -8436,7 +8603,12 @@ speechSynthesis.getVoices(); 'VRCX_instanceUsersSortAlphabetical', false ); - $app.methods.saveEventOverlay = async function () { + $app.methods.saveEventOverlay = async function (configKey = '') { + if (configKey === 'VRCX_PhotonEventOverlay') { + this.photonEventOverlay = !this.photonEventOverlay; + } else if (configKey === 'VRCX_TimeoutHudOverlay') { + this.timeoutHudOverlay = !this.timeoutHudOverlay; + } await configRepository.setBool( 'VRCX_PhotonEventOverlay', this.photonEventOverlay @@ -8467,7 +8639,13 @@ speechSynthesis.getVoices(); 'VRCX_logEmptyAvatars', false ); - $app.methods.saveLoggingOptions = async function () { + $app.methods.saveLoggingOptions = async function (configKey = '') { + if (configKey === 'VRCX_logResourceLoad') { + this.logResourceLoad = !this.logResourceLoad; + } else { + this.logEmptyAvatars = !this.logEmptyAvatars; + } + await configRepository.setBool( 'VRCX_logResourceLoad', this.logResourceLoad @@ -8503,11 +8681,14 @@ speechSynthesis.getVoices(); 'VRCX_autoAcceptInviteRequests', 'Off' ); - $app.methods.saveAutomationOptions = async function () { - await configRepository.setBool( - 'VRCX_autoStateChangeEnabled', - this.autoStateChangeEnabled - ); + $app.methods.saveAutomationOptions = async function (configKey = '') { + if (configKey === 'VRCX_autoStateChangeEnabled') { + this.autoStateChangeEnabled = !this.autoStateChangeEnabled; + await configRepository.setBool( + 'VRCX_autoStateChangeEnabled', + this.autoStateChangeEnabled + ); + } await configRepository.setBool( 'VRCX_autoStateChangeNoFriends', this.autoStateChangeNoFriends @@ -8819,7 +9000,10 @@ speechSynthesis.getVoices(); ) ); - $app.methods.updatetrustColor = async function () { + $app.methods.updatetrustColor = async function (setRandomColor = false) { + if (setRandomColor) { + this.randomUserColours = !this.randomUserColours; + } if (typeof API.currentUser?.id === 'undefined') { return; } @@ -16300,15 +16484,21 @@ speechSynthesis.getVoices(); AppApi.OpenShortcutFolder(); }; - $app.methods.updateAppLauncherSettings = async function () { - await configRepository.setBool( - 'VRCX_enableAppLauncher', - this.enableAppLauncher - ); - await configRepository.setBool( - 'VRCX_enableAppLauncherAutoClose', - this.enableAppLauncherAutoClose - ); + $app.methods.updateAppLauncherSettings = async function (configKey = '') { + if (configKey === 'VRCX_enableAppLauncher') { + this.enableAppLauncher = !this.enableAppLauncher; + await configRepository.setBool( + 'VRCX_enableAppLauncher', + this.enableAppLauncher + ); + } else { + this.enableAppLauncherAutoClose = !this.enableAppLauncherAutoClose; + await configRepository.setBool( + 'VRCX_enableAppLauncherAutoClose', + this.enableAppLauncherAutoClose + ); + } + await AppApi.SetAppLauncherSettings( this.enableAppLauncher, this.enableAppLauncherAutoClose @@ -16317,7 +16507,16 @@ speechSynthesis.getVoices(); // Screenshot Helper - $app.methods.saveScreenshotHelper = async function () { + $app.methods.saveScreenshotHelper = async function (configKey = '') { + if (configKey === 'VRCX_screenshotHelper') { + this.screenshotHelper = !this.screenshotHelper; + } else if (configKey === 'VRCX_screenshotHelperModifyFilename') { + this.screenshotHelperModifyFilename = + !this.screenshotHelperModifyFilename; + } else if (configKey === 'VRCX_screenshotHelperCopyToClipboard') { + this.screenshotHelperCopyToClipboard = + !this.screenshotHelperCopyToClipboard; + } await configRepository.setBool( 'VRCX_screenshotHelper', this.screenshotHelper @@ -16734,7 +16933,15 @@ speechSynthesis.getVoices(); } }; - $app.methods.changeYouTubeApi = async function () { + $app.methods.changeYouTubeApi = async function (configKey = '') { + if (configKey === 'VRCX_youtubeAPI') { + this.youTubeApi = !this.youTubeApi; + } else if (configKey === 'VRCX_progressPie') { + this.progressPie = !this.progressPie; + } else if (configKey === 'VRCX_progressPieFilter') { + this.progressPieFilter = !this.progressPieFilter; + } + await configRepository.setBool('VRCX_youtubeAPI', this.youTubeApi); await configRepository.setBool('VRCX_progressPie', this.progressPie); await configRepository.setBool( @@ -19122,7 +19329,10 @@ speechSynthesis.getVoices(); 'VRCX_dtIsoFormat', false ); - $app.methods.setDatetimeFormat = async function () { + $app.methods.setDatetimeFormat = async function (setIsoFormat = false) { + if (setIsoFormat) { + this.dtIsoFormat = !this.dtIsoFormat; + } var currentCulture = await AppApi.CurrentCulture(); var hour12 = await configRepository.getBool('VRCX_dtHour12'); var isoFormat = await configRepository.getBool('VRCX_dtIsoFormat'); diff --git a/html/src/app.scss b/html/src/app.scss index 6860c6b6..9d214a50 100644 --- a/html/src/app.scss +++ b/html/src/app.scss @@ -730,21 +730,7 @@ i.x-status-icon.red { .options-container-item .name { display: inline-block; - min-width: 225px; -} - -.simple-switch { - font-size: 12px; - margin-top: 5px; - display: flex; -} - -.simple-switch .name { - flex-basis: 225px; -} - -.simple-switch .switch { - flex-shrink: 0; + width: 235px; } .toggle-switch { diff --git a/html/src/classes/discordRpc.js b/html/src/classes/discordRpc.js index e60657d1..1da11f09 100644 --- a/html/src/classes/discordRpc.js +++ b/html/src/classes/discordRpc.js @@ -237,24 +237,46 @@ export default class extends baseClass { } }, - async saveDiscordOption() { - await configRepository.setBool('discordActive', this.discordActive); - await configRepository.setBool( - 'discordInstance', - this.discordInstance - ); - await configRepository.setBool( - 'discordJoinButton', - this.discordJoinButton - ); - await configRepository.setBool( - 'discordHideInvite', - this.discordHideInvite - ); - await configRepository.setBool( - 'discordHideImage', - this.discordHideImage - ); + async saveDiscordOption(configLabel = '') { + if (configLabel === 'discordActive') { + this.discordActive = !this.discordActive; + await configRepository.setBool( + 'discordActive', + this.discordActive + ); + } + + if (configLabel === 'discordInstance') { + this.discordInstance = !this.discordInstance; + await configRepository.setBool( + 'discordInstance', + this.discordInstance + ); + } + + if (configLabel === 'discordJoinButton') { + this.discordJoinButton = !this.discordJoinButton; + await configRepository.setBool( + 'discordJoinButton', + this.discordJoinButton + ); + } + + if (configLabel === 'discordHideInvite') { + this.discordHideInvite = !this.discordHideInvite; + await configRepository.setBool( + 'discordHideInvite', + this.discordHideInvite + ); + } + if (configLabel === 'discordHideImage') { + this.discordHideImage = !this.discordHideImage; + await configRepository.setBool( + 'discordHideImage', + this.discordHideImage + ); + } + this.lastLocation$.tag = ''; this.nextDiscordUpdate = 3; this.updateDiscord(); diff --git a/html/src/classes/gameLog.js b/html/src/classes/gameLog.js index ebabf3ee..4f0aa9e5 100644 --- a/html/src/classes/gameLog.js +++ b/html/src/classes/gameLog.js @@ -1093,6 +1093,7 @@ export default class extends baseClass { }, async disableGameLogDialog() { + this.gameLogDisabled = !this.gameLogDisabled; if (this.isGameRunning) { this.$message({ message: diff --git a/html/src/components/settings/SimpleSwitch.vue b/html/src/components/settings/SimpleSwitch.vue new file mode 100644 index 00000000..0fa468a4 --- /dev/null +++ b/html/src/components/settings/SimpleSwitch.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/html/src/mixins/tabs/settings.pug b/html/src/mixins/tabs/settings.pug index f4e0f7c1..23fc918d 100644 --- a/html/src/mixins/tabs/settings.pug +++ b/html/src/mixins/tabs/settings.pug @@ -6,14 +6,6 @@ mixin simpleSettingsCategory(headerTrKey) else p No Content -mixin simpleSwitch(nameTrKey, model, onChange="", tooltipContent) - div.simple-switch - //- I fought with getting the right syntax for a translation key, as an argument, in an interpolated block for like 20mins before I realized the answer was staring me in the face in the documentation I passed over like 5 times. Feelsbadman. - //- I didn't even know what pug was before working on this; speedrunning learning pug templating. - //- I've also never worked with vue/element and have no idea what I'm doing. pog, as the kids say - span.name {{ $t('#{nameTrKey}') }} - el-switch.switch(v-model=model @change=onChange) - mixin simpleTwoLabelSwitch(nameTrKey, model, onChange="") div.options-container-item span.name {{ $t('#{nameTrKey}') }} @@ -42,6 +34,8 @@ mixin settingsTab() div.options-container(style="margin-top:0;padding:5px") span.header {{ $t("view.settings.header") }} el-tabs(type="card" style="height: calc(100% - 51px)") + + //- General Tab el-tab-pane(:label="$t('view.settings.category.general')") //- General | General div.options-container(style="margin-top:0") @@ -80,19 +74,11 @@ mixin settingsTab() ], "saveAutoUpdateVRCX") //- General | Application +simpleSettingsCategory("view.settings.general.application.header") - +simpleSwitch("view.settings.general.application.startup", "isStartAtWindowsStartup", "saveVRCXWindowOption") - +simpleSwitch("view.settings.general.application.minimized", "isStartAsMinimizedState", "saveVRCXWindowOption") - +simpleSwitch("view.settings.general.application.tray", "isCloseToTray", "saveVRCXWindowOption") - div.options-container-item - span.name {{ $t('view.settings.general.application.disable_gpu_acceleration') }} - el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.general.application.disable_gpu_acceleration_tooltip')") - i.el-icon-info - el-switch(v-model="disableGpuAcceleration" @change="saveVRCXWindowOption") - div.options-container-item - span.name {{ $t('view.settings.general.application.disable_vr_overlay_gpu_acceleration') }} - el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.general.application.disable_gpu_acceleration_tooltip')") - i.el-icon-info - el-switch(v-model="disableVrOverlayGpuAcceleration" @change="saveVRCXWindowOption") + simple-switch(:label='$t("view.settings.general.application.startup")' :value='isStartAtWindowsStartup' @change='saveVRCXWindowOption("VRCX_StartAtWindowsStartup")') + simple-switch(:label='$t("view.settings.general.application.minimized")' :value='isStartAsMinimizedState' @change='saveVRCXWindowOption("VRCX_StartAsMinimizedState")') + simple-switch(:label='$t("view.settings.general.application.tray")' :value='isCloseToTray' @change='saveVRCXWindowOption("VRCX_CloseToTray")') + simple-switch(:label='$t("view.settings.general.application.disable_gpu_acceleration")' :value='disableGpuAcceleration' @change='saveVRCXWindowOption("VRCX_DisableGpuAcceleration")' :tooltip='$t("view.settings.general.application.disable_gpu_acceleration_tooltip")') + simple-switch(:label='$t("view.settings.general.application.disable_vr_overlay_gpu_acceleration")' :value='disableVrOverlayGpuAcceleration' @change='saveVRCXWindowOption("VRCX_DisableVrOverlayGpuAcceleration")' :tooltip='$t("view.settings.general.application.disable_gpu_acceleration_tooltip")') div.options-container-item el-button(size="small" icon="el-icon-connection" @click="promptProxySettings()") {{ $t("view.settings.general.application.proxy") }} //- General | Favorite @@ -106,23 +92,13 @@ mixin settingsTab() //- General | Game Log div.options-container span.header {{ $t('view.settings.general.logging.header') }} - div.options-container-item - span.name(style="min-width:225px") {{ $t('view.settings.advanced.advanced.cache_debug.udon_exception_logging') }} - el-switch(v-model="udonExceptionLogging" @change="saveOpenVROption") - div.options-container-item - span.name(style="min-width:225px") {{ $t('view.settings.general.logging.resource_load') }} - el-switch(v-model="logResourceLoad" @change="saveLoggingOptions") - div.options-container-item - span.name(style="min-width:225px") {{ $t('view.settings.general.logging.empty_avatar') }} - el-switch(v-model="logEmptyAvatars" @change="saveLoggingOptions") + simple-switch(:label='$t("view.settings.advanced.advanced.cache_debug.udon_exception_logging")' :value='udonExceptionLogging' @change='saveOpenVROption("VRCX_udonExceptionLogging")') + simple-switch(:label='$t("view.settings.general.logging.resource_load")' :value='logResourceLoad' @change='saveLoggingOptions("VRCX_logResourceLoad")') + simple-switch(:label='$t("view.settings.general.logging.empty_avatar")' :value='logEmptyAvatars' @change='saveLoggingOptions("VRCX_logEmptyAvatars")') //- General | Automation div.options-container span.header {{ $t('view.settings.general.automation.header') }} - div.options-container-item - span.name {{ $t('view.settings.general.automation.auto_change_status') }} - el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.general.automation.auto_state_change_tooltip')") - i.el-icon-info - el-switch(v-model="autoStateChangeEnabled" @change="saveAutomationOptions") + simple-switch(:label='$t("view.settings.general.automation.auto_change_status")' :value='autoStateChangeEnabled' @change='saveAutomationOptions("VRCX_autoStateChangeEnabled")' :tooltip='$t("view.settings.general.automation.auto_state_change_tooltip")') div.options-container-item span.name {{ $t('view.settings.general.automation.alone_status') }} el-select(v-model="autoStateChangeAloneStatus" :disabled="!autoStateChangeEnabled" @change="saveAutomationOptions" style="margin-top:8px" size="small") @@ -177,6 +153,7 @@ mixin settingsTab() p {{ $t("view.settings.general.legal_notice.disclaimer2" )}} div.options-container-item el-button(@click="ossDialog = true" size="small") {{ $t("view.settings.general.legal_notice.open_source_software_notice" )}} + //- Appearance Tab el-tab-pane(:label="$t('view.settings.category.appearance')") //- Appearance | Appearance @@ -205,15 +182,9 @@ mixin settingsTab() div.options-container-item span.name {{ $t('view.settings.appearance.appearance.zoom') }} el-input-number(size="small" v-model="zoomLevel" @change="setZoomLevel" :precision="0" style="width:128px") - div.options-container-item - span.name {{ $t('view.settings.appearance.appearance.vrcplus_profile_icons') }} - el-switch(v-model="displayVRCPlusIconsAsAvatar" @change="saveOpenVROption") - div.options-container-item - span.name {{ $t('view.settings.appearance.appearance.nicknames') }} - el-switch(v-model="hideNicknames" :active-value="false" :inactive-value="true" @change="saveOpenVROption") - div.options-container-item - span.name {{ $t('view.settings.appearance.appearance.tooltips') }} - el-switch(v-model="hideTooltips" :active-value="false" :inactive-value="true" @change="saveOpenVROption") + simple-switch(:label='$t("view.settings.appearance.appearance.vrcplus_profile_icons")' :value='displayVRCPlusIconsAsAvatar' @change='saveOpenVROption("displayVRCPlusIconsAsAvatar")') + simple-switch(:label='$t("view.settings.appearance.appearance.nicknames")' :value='hideNicknames' @change='saveOpenVROption("VRCX_hideNicknames")') + simple-switch(:label='$t("view.settings.appearance.appearance.tooltips")' :value='!hideTooltips' @change='saveOpenVROption("VRCX_hideTooltips")') div.options-container-item span.name {{ $t('view.settings.appearance.appearance.sort_favorite_by') }} el-radio-group(v-model="sortFavorites" @change="saveSortFavoritesOption") @@ -240,9 +211,7 @@ mixin settingsTab() el-radio-group(v-model="dtHour12" @change="setDatetimeFormat") el-radio(:label="true") {{ $t('view.settings.appearance.timedate.time_format_12') }} el-radio(:label="false") {{ $t('view.settings.appearance.timedate.time_format_24') }} - div.options-container-item - span.name {{ $t('view.settings.appearance.timedate.force_iso_date_format') }} - el-switch(v-model="dtIsoFormat" @change="setDatetimeFormat") + simple-switch(:label='$t("view.settings.appearance.timedate.force_iso_date_format")' :value='dtIsoFormat' @change='setDatetimeFormat(true)') //- Appearance | Side Panel div.options-container span.header {{ $t('view.settings.appearance.side_panel.header') }} @@ -284,12 +253,8 @@ mixin settingsTab() //- Appearance | User Dialog div.options-container span.header {{ $t('view.settings.appearance.user_dialog.header') }} - div.options-container-item - span.name {{ $t('view.settings.appearance.user_dialog.vrchat_notes') }} - el-switch(v-model="hideUserNotes" :active-value="false" :inactive-value="true" @change="saveUserDialogOption") - div.options-container-item - span.name {{ $t('view.settings.appearance.user_dialog.vrcx_memos') }} - el-switch(v-model="hideUserMemos" :active-value="false" :inactive-value="true" @change="saveUserDialogOption") + simple-switch(:label='$t("view.settings.appearance.user_dialog.vrchat_notes")' :value='hideUserNotes' @change='saveUserDialogOption("VRCX_hideUserNotes")') + simple-switch(:label='$t("view.settings.appearance.user_dialog.vrcx_memos")' :value='hideUserMemos' @change='saveUserDialogOption("VRCX_hideUserMemos")') div.options-container-item span.name {{ $t('view.settings.appearance.user_dialog.export_vrcx_memos_into_vrchat_notes') }} br @@ -297,15 +262,11 @@ mixin settingsTab() //- Appearance | Friend Log div.options-container span.header {{ $t('view.settings.appearance.friend_log.header') }} - div.options-container-item - span.name {{ $t('view.settings.appearance.friend_log.hide_unfriends') }} - el-switch(v-model="hideUnfriends" @change="saveFriendLogOptions") + simple-switch(:label='$t("view.settings.appearance.friend_log.hide_unfriends")' :value='hideUnfriends' @change='saveFriendLogOptions') //- Appearance | User Colors div.options-container span.header {{ $t('view.settings.appearance.user_colors.header') }} - div.options-container-item - span.name {{ $t('view.settings.appearance.user_colors.random_colors_from_user_id') }} - el-switch(v-model="randomUserColours" @change="updatetrustColor") + simple-switch(:label='$t("view.settings.appearance.user_colors.random_colors_from_user_id")' :value='randomUserColours' @change='updatetrustColor(true)') div.options-container-item div el-color-picker(v-model="trustColor.untrusted" @change="updatetrustColor" size="mini" :predefine="['#CCCCCC']") @@ -328,6 +289,7 @@ mixin settingsTab() div el-color-picker(v-model="trustColor.troll" @change="updatetrustColor" size="mini" :predefine="['#782f2f']") span.color-picker(slot="trigger" class="x-tag-troll") Nuisance + //- Notifications Tab el-tab-pane(:label="$t('view.settings.category.notifications')") //- Notifications | Notifications @@ -346,25 +308,15 @@ mixin settingsTab() el-radio-button(label="Game Running") {{ $t('view.settings.notifications.notifications.conditions.inside_vrchat') }} el-radio-button(label="Game Closed") {{ $t('view.settings.notifications.notifications.conditions.outside_vrchat') }} el-radio-button(label="Always") {{ $t('view.settings.notifications.notifications.conditions.always') }} - div.options-container-item - +simpleSwitch("view.settings.notifications.notifications.steamvr_notifications.steamvr_overlay", "openVR", "saveOpenVROption") - div.options-container-item - span.name {{ $t('view.settings.notifications.notifications.steamvr_notifications.overlay_notifications') }} - el-switch(v-model="overlayNotifications" @change="saveOpenVROption" :disabled="!openVR") + + simple-switch(:label='$t("view.settings.notifications.notifications.steamvr_notifications.steamvr_overlay")' :value='openVR' @change='saveOpenVROption("openVR")') + simple-switch(:label='$t("view.settings.notifications.notifications.steamvr_notifications.overlay_notifications")' :value='overlayNotifications' @change='saveOpenVROption("VRCX_overlayNotifications")' :disabled="!openVR") div.options-container-item el-button(size="small" icon="el-icon-rank" @click="showNotificationPositionDialog" :disabled="!overlayNotifications || !openVR") {{ $t('view.settings.notifications.notifications.steamvr_notifications.notification_position') }} - div.options-container-item - span.name {{ $t('view.settings.notifications.notifications.steamvr_notifications.xsoverlay_notifications') }} - el-switch(v-model="xsNotifications" @change="saveOpenVROption") - div.options-container-item - span.name {{ $t('view.settings.notifications.notifications.steamvr_notifications.ovrtoolkit_hud_notifications') }} - el-switch(v-model="ovrtHudNotifications" @change="saveOpenVROption") - div.options-container-item - span.name {{ $t('view.settings.notifications.notifications.steamvr_notifications.ovrtoolkit_wrist_notifications') }} - el-switch(v-model="ovrtWristNotifications" @change="saveOpenVROption") - div.options-container-item - span.name {{ $t('view.settings.notifications.notifications.steamvr_notifications.user_images') }} - el-switch(v-model="imageNotifications" @change="saveOpenVROption") + simple-switch(:label='$t("view.settings.notifications.notifications.steamvr_notifications.xsoverlay_notifications")' :value='xsNotifications' @change='saveOpenVROption("VRCX_xsNotifications")') + simple-switch(:label='$t("view.settings.notifications.notifications.steamvr_notifications.ovrtoolkit_hud_notifications")' :value='ovrtHudNotifications' @change='saveOpenVROption("VRCX_ovrtHudNotifications")') + simple-switch(:label='$t("view.settings.notifications.notifications.steamvr_notifications.ovrtoolkit_wrist_notifications")' :value='ovrtWristNotifications' @change='saveOpenVROption("VRCX_ovrtWristNotifications")') + simple-switch(:label='$t("view.settings.notifications.notifications.steamvr_notifications.user_images")' :value='imageNotifications' @change='saveOpenVROption("VRCX_imageNotifications")') div.options-container-item el-button(size="small" icon="el-icon-time" @click="promptNotificationTimeout" :disabled="(!overlayNotifications || !openVR) && !xsNotifications") {{ $t('view.settings.notifications.notifications.steamvr_notifications.notification_timeout') }} //- Notifications | Notifications | Desktop Notifications @@ -381,9 +333,7 @@ mixin settingsTab() el-radio-button(label="Game Running") {{ $t('view.settings.notifications.notifications.conditions.inside_vrchat') }} el-radio-button(label="Game Closed") {{ $t('view.settings.notifications.notifications.conditions.outside_vrchat') }} el-radio-button(label="Always") {{ $t('view.settings.notifications.notifications.conditions.always') }} - div.options-container-item - span.name(style="min-width:225px") {{ $t('view.settings.notifications.notifications.desktop_notifications.desktop_notification_while_afk') }} - el-switch(v-model="afkDesktopToast" @change="saveOpenVROption") + simple-switch(:label='$t("view.settings.notifications.notifications.desktop_notifications.desktop_notification_while_afk")' :value='afkDesktopToast' @change='saveOpenVROption("VRCX_afkDesktopToast")') //- Notifications | Notifications | Text-to-Speech Options div.options-container span.sub-header {{ $t('view.settings.notifications.notifications.text_to_speech.header') }} @@ -403,15 +353,12 @@ mixin settingsTab() span {{ getTTSVoiceName() }} #[i.el-icon-arrow-down.el-icon--right] el-dropdown-menu(#default="dropdown") el-dropdown-item(v-if="voice" v-for="(voice, index) in TTSvoices" :key="index" v-text="voice.name" :command="index") - div.options-container-item - span.name {{ $t('view.settings.notifications.notifications.text_to_speech.use_memo_nicknames') }} - el-switch(v-model="notificationTTSNickName" @change="saveOpenVROption" :disabled="notificationTTS === 'Never'") - div.options-container-item - span.name {{ $t('view.settings.notifications.notifications.text_to_speech.tts_test_placeholder') }} - el-switch(v-model="isTestTTSVisible") - div(v-if="isTestTTSVisible" style="margin-top:5px") - el-input(type="textarea" v-model="notificationTTSTest" :placeholder="$t('view.settings.notifications.notifications.text_to_speech.tts_test_placeholder')" :rows="1" style="width:175px;display:inline-block") - el-button(size="small" icon="el-icon-video-play" @click="testNotificationTTS" style="margin-top:5px") {{ $t('view.settings.notifications.notifications.text_to_speech.play') }} + simple-switch(:label='$t("view.settings.notifications.notifications.text_to_speech.use_memo_nicknames")' :value='notificationTTSNickName' @change='saveOpenVROption("VRCX_notificationTTSNickName")' :disabled='notificationTTS === "Never"') + simple-switch(:label='$t("view.settings.notifications.notifications.text_to_speech.tts_test_placeholder")' :value='isTestTTSVisible' @change='isTestTTSVisible = !isTestTTSVisible') + div(v-if="isTestTTSVisible" style="margin-top:5px") + el-input(type="textarea" v-model="notificationTTSTest" :placeholder="$t('view.settings.notifications.notifications.text_to_speech.tts_test_placeholder')" :rows="1" style="width:175px;display:inline-block") + el-button(size="small" icon="el-icon-video-play" @click="testNotificationTTS" style="margin-left:10px") {{ $t('view.settings.notifications.notifications.text_to_speech.play') }} + //- Wrist Overlay Tab el-tab-pane(:label="$t('view.settings.category.wrist_overlay')") //- Wrist Overlay | SteamVR Wrist Overlay @@ -427,15 +374,9 @@ mixin settingsTab() br span {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.menu') }} br - div.options-container-item - span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.steamvr_overlay') }} - el-switch(v-model="openVR" @change="saveOpenVROption") - div.options-container-item - span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.wrist_feed_overlay') }} - el-switch(v-model="overlayWrist" @change="saveOpenVROption" :disabled="!openVR") - div.options-container-item - span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.hide_private_worlds') }} - el-switch(v-model="hidePrivateFromFeed" @change="saveOpenVROption") + simple-switch(:label='$t("view.settings.wrist_overlay.steamvr_wrist_overlay.steamvr_overlay")' :value='openVR' @change='saveOpenVROption("openVR")') + simple-switch(:label='$t("view.settings.wrist_overlay.steamvr_wrist_overlay.wrist_feed_overlay")' :value='overlayWrist' @change='saveOpenVROption("VRCX_overlayWrist")' :disabled="!openVR") + simple-switch(:label='$t("view.settings.wrist_overlay.steamvr_wrist_overlay.hide_private_worlds")' :value='hidePrivateFromFeed' @change='saveOpenVROption("VRCX_hidePrivateFromFeed")') div.options-container-item(style="min-width:118px") span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.start_overlay_with') }} el-radio-group(v-model="openVRAlways" @change="saveOpenVROption" :disabled="!openVR") @@ -452,47 +393,25 @@ mixin settingsTab() el-radio-button(label="1") {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on_left') }} el-radio-button(label="2") {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on_right') }} el-radio-button(label="0") {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on_both') }} - div.options-container-item - span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.grey_background') }} - el-switch(v-model="vrBackgroundEnabled" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist") - div.options-container-item - span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.minimal_feed_icons') }} - el-switch(v-model="minimalFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist") - div.options-container-item - span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.show_vr_devices') }} - el-switch(v-model="hideDevicesFromFeed" @change="saveOpenVROption" :active-value="false" :inactive-value="true" :disabled="!openVR || !overlayWrist") - div.options-container-item - span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.show_cpu_usage') }} - el-switch(v-model="vrOverlayCpuUsage" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist") - div.options-container-item - span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.show_game_uptime') }} - el-switch(v-model="hideUptimeFromFeed" @change="saveOpenVROption" :active-value="false" :inactive-value="true" :disabled="!openVR || !overlayWrist") - div.options-container-item - span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.show_pc_uptime') }} - el-switch(v-model="pcUptimeOnFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist") + simple-switch(:label='$t("view.settings.wrist_overlay.steamvr_wrist_overlay.grey_background")' :value='vrBackgroundEnabled' @change='saveOpenVROption("VRCX_vrBackgroundEnabled")' :disabled="!openVR || !overlayWrist") + simple-switch(:label='$t("view.settings.wrist_overlay.steamvr_wrist_overlay.minimal_feed_icons")' :value='minimalFeed' @change='saveOpenVROption("VRCX_minimalFeed")' :disabled="!openVR || !overlayWrist") + simple-switch(:label='$t("view.settings.wrist_overlay.steamvr_wrist_overlay.show_vr_devices")' :value='!hideDevicesFromFeed' @change='saveOpenVROption("VRCX_hideDevicesFromFeed")' :disabled="!openVR || !overlayWrist") + simple-switch(:label='$t("view.settings.wrist_overlay.steamvr_wrist_overlay.show_cpu_usage")' :value='vrOverlayCpuUsage' @change='saveOpenVROption("VRCX_vrOverlayCpuUsage")' :disabled="!openVR || !overlayWrist") + simple-switch(:label='$t("view.settings.wrist_overlay.steamvr_wrist_overlay.show_game_uptime")' :value='!hideUptimeFromFeed' @change='saveOpenVROption("VRCX_hideUptimeFromFeed")' :disabled="!openVR || !overlayWrist") + simple-switch(:label='$t("view.settings.wrist_overlay.steamvr_wrist_overlay.show_pc_uptime")' :value='pcUptimeOnFeed' @change='saveOpenVROption("VRCX_pcUptimeOnFeed")' :disabled="!openVR || !overlayWrist") + //- Discord Presence Tab el-tab-pane(:label="$t('view.settings.category.discord_presence')") div.options-container(style="margin-top:0") span.header {{ $t('view.settings.discord_presence.discord_presence.header') }} div.options-container-item span {{ $t('view.settings.discord_presence.discord_presence.description') }} - div.options-container-item - span.name {{ $t('view.settings.discord_presence.discord_presence.enable') }} - el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.discord_presence.discord_presence.enable_tooltip')") - i.el-icon-warning(style="cursor:pointer" @click="showVRChatConfig") - el-switch(v-model="discordActive" @change="saveDiscordOption") - div.options-container-item - span.name {{ $t('view.settings.discord_presence.discord_presence.instance_type_player_count') }} - el-switch(v-model="discordInstance" @change="saveDiscordOption" :disabled="!discordActive") - div.options-container-item - span.name {{ $t('view.settings.discord_presence.discord_presence.show_details_in_private') }} - el-switch(v-model="discordHideInvite" @change="saveDiscordOption" :active-value="false" :inactive-value="true" :disabled="!discordActive") - div.options-container-item - span.name {{ $t('view.settings.discord_presence.discord_presence.join_button') }} - el-switch(v-model="discordJoinButton" @change="saveDiscordOption" :disabled="!discordActive") - div.options-container-item - span.name {{ $t('view.settings.discord_presence.discord_presence.show_images') }} - el-switch(v-model="discordHideImage" @change="saveDiscordOption" :active-value="false" :inactive-value="true" :disabled="!discordActive") + simple-switch(:label='$t("view.settings.discord_presence.discord_presence.enable")' :value='discordActive' @change='saveDiscordOption("discordActive")' :tooltip='$t("view.settings.discord_presence.discord_presence.enable_tooltip")') + simple-switch(:label='$t("view.settings.discord_presence.discord_presence.instance_type_player_count")' :value='discordInstance' @change='saveDiscordOption("discordInstance")' :disabled="!discordActive") + simple-switch(:label='$t("view.settings.discord_presence.discord_presence.show_details_in_private")' :value='!discordHideInvite' @change='saveDiscordOption("discordHideInvite")' :disabled="!discordActive") + simple-switch(:label='$t("view.settings.discord_presence.discord_presence.join_button")' :value='discordJoinButton' @change='saveDiscordOption("discordJoinButton")' :disabled="!discordActive") + simple-switch(:label='$t("view.settings.discord_presence.discord_presence.show_images")' :value='!discordHideImage' @change='saveDiscordOption("discordHideImage")' :disabled="!discordActive") + //- "Advanced" Tab el-tab-pane(:label="$t('view.settings.category.advanced')") //- Advanced | Advanced @@ -518,29 +437,20 @@ mixin settingsTab() div.options-container //- Advanced | Primary Password Header span.sub-header {{ $t('view.settings.advanced.advanced.primary_password.header') }} - div.options-container-item - span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.primary_password.description') }} - el-switch(v-model="enablePrimaryPassword" @change="enablePrimaryPasswordChange" :disabled="!enablePrimaryPassword") + simple-switch(:label='$t("view.settings.advanced.advanced.primary_password.description")' :value='enablePrimaryPassword' @change='enablePrimaryPasswordChange' :disabled="!enablePrimaryPassword" :long-label='true') span.sub-header {{ $t('view.settings.advanced.advanced.relaunch_vrchat.header') }} //- Advanced | Relaunch VRChat After Crash - div.options-container-item - span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.relaunch_vrchat.description') }} - el-switch(v-model="relaunchVRChatAfterCrash" @change="saveOpenVROption") + simple-switch(:label='$t("view.settings.advanced.advanced.relaunch_vrchat.description")' :value='relaunchVRChatAfterCrash' @change='saveOpenVROption("VRCX_relaunchVRChatAfterCrash")' :long-label='true') //- Advanced | VRChat Quit Fix span.sub-header {{ $t('view.settings.advanced.advanced.vrchat_quit_fix.header') }} - div.options-container-item - span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.vrchat_quit_fix.description') }} - el-switch(v-model="vrcQuitFix" @change="saveOpenVROption") + simple-switch(:label='$t("view.settings.advanced.advanced.vrchat_quit_fix.description")' :value='vrcQuitFix' @change='saveOpenVROption("VRCX_vrcQuitFix")' :long-label='true') //- Advanced | Auto Cache Management span.sub-header {{ $t('view.settings.advanced.advanced.auto_cache_management.header') }} - div.options-container-item - span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.auto_cache_management.description') }} - el-switch(v-model="autoSweepVRChatCache" @change="saveOpenVROption") + simple-switch(:label='$t("view.settings.advanced.advanced.auto_cache_management.description")' :value='autoSweepVRChatCache' @change='saveOpenVROption("VRCX_autoSweepVRChatCache")' :long-label='true') //- Advanced | Disable local world database span.sub-header {{ $t('view.settings.advanced.advanced.local_world_persistence.header') }} - div.options-container-item - span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.local_world_persistence.description') }} - el-switch(v-model="disableWorldDatabase" :active-value="false" :inactive-value="true" @change="saveVRCXWindowOption") + simple-switch(:label='$t("view.settings.advanced.advanced.local_world_persistence.description")' :value='!disableWorldDatabase' @change='saveVRCXWindowOption("VRCX_DisableWorldDatabase")' :long-label='true') + //- Advanced | User Generated Content div.options-container span.header {{ $t('view.settings.advanced.advanced.user_generated_content.header') }} @@ -554,19 +464,13 @@ mixin settingsTab() span.sub-header {{ $t('view.settings.advanced.advanced.save_instance_prints_to_file.header') }} el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.advanced.advanced.save_instance_prints_to_file.header_tooltip')") i.el-icon-info - div.options-container-item - span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.save_instance_prints_to_file.description') }} - el-switch(v-model="saveInstancePrints" @change="saveVRCXWindowOption") + simple-switch(:label='$t("view.settings.advanced.advanced.save_instance_prints_to_file.description")' :value='saveInstancePrints' @change='saveVRCXWindowOption("VRCX_saveInstancePrints")' :long-label='true') span.sub-header {{ $t('view.settings.advanced.advanced.save_instance_stickers_to_file.header') }} - div.options-container-item - span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.save_instance_stickers_to_file.description') }} - el-switch(v-model="saveInstanceStickers" @change="saveVRCXWindowOption") + simple-switch(:label='$t("view.settings.advanced.advanced.save_instance_stickers_to_file.description")' :value='saveInstanceStickers' @change='saveVRCXWindowOption("VRCX_saveInstanceStickers")' :long-label='true') //- Advanced | Remote Avatar Database div.options-container span.header {{ $t('view.settings.advanced.advanced.remote_database.header') }} - div.options-container-item - span.name {{ $t('view.settings.advanced.advanced.remote_database.enable') }} - el-switch(v-model="avatarRemoteDatabase" @change="saveOpenVROption") + simple-switch(:label='$t("view.settings.advanced.advanced.remote_database.enable")' :value='avatarRemoteDatabase' @change='saveOpenVROption("VRCX_avatarRemoteDatabase")' :long-label='true') div.options-container-item el-button(size="small" icon="el-icon-user-solid" @click="showAvatarProviderDialog") {{ $t('view.settings.advanced.advanced.remote_database.avatar_database_provider') }} //- Advanced | Automatic App Launcher @@ -575,8 +479,10 @@ mixin settingsTab() el-button(size="small" icon="el-icon-folder" @click="openShortcutFolder()" style="margin-top:5px") {{ $t('view.settings.advanced.advanced.app_launcher.folder') }} el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.advanced.advanced.app_launcher.folder_tooltip')") i.el-icon-info - +simpleSwitch("view.settings.advanced.advanced.app_launcher.enable", "enableAppLauncher", "updateAppLauncherSettings") - +simpleSwitch("view.settings.advanced.advanced.app_launcher.auto_close", "enableAppLauncherAutoClose", "updateAppLauncherSettings") + simple-switch(:label='$t("view.settings.advanced.advanced.remote_database.enable")' :value='enableAppLauncher' @change='updateAppLauncherSettings("VRCX_enableAppLauncher")' :long-label='true') + simple-switch(:label='$t("view.settings.advanced.advanced.app_launcher.auto_close")' :value='enableAppLauncherAutoClose' @change='updateAppLauncherSettings("VRCX_enableAppLauncherAutoClose")' :long-label='true') + + //- Advanced | Screenshot Helper div.options-container span.header {{ $t('view.settings.advanced.advanced.screenshot_helper.header') }} @@ -584,48 +490,31 @@ mixin settingsTab() span.name {{ $t('view.settings.advanced.advanced.screenshot_helper.description') }} el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.advanced.advanced.screenshot_helper.description_tooltip')") i.el-icon-info - div.options-container-item - span.name {{ $t('view.settings.advanced.advanced.screenshot_helper.enable') }} - el-switch(v-model="screenshotHelper" @change="saveScreenshotHelper") - div.options-container-item - span.name {{ $t('view.settings.advanced.advanced.screenshot_helper.modify_filename') }} - el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.advanced.advanced.screenshot_helper.modify_filename_tooltip')") - i.el-icon-info - el-switch(v-model="screenshotHelperModifyFilename" @change="saveScreenshotHelper" :disabled="!screenshotHelper") - div.options-container-item - span.name {{ $t('view.settings.advanced.advanced.screenshot_helper.copy_to_clipboard') }} - el-switch(v-model="screenshotHelperCopyToClipboard" @change="saveScreenshotHelper") + simple-switch(:label='$t("view.settings.advanced.advanced.screenshot_helper.enable")' :value='screenshotHelper' @change='saveScreenshotHelper("VRCX_screenshotHelper")' :long-label='true') + simple-switch(:label='$t("view.settings.advanced.advanced.screenshot_helper.modify_filename")' :value='screenshotHelperModifyFilename' @change='saveScreenshotHelper("VRCX_screenshotHelperModifyFilename")' :disabled="!screenshotHelper" :tooltip="$t('view.settings.advanced.advanced.screenshot_helper.modify_filename_tooltip')" :long-label='true') + + + simple-switch(:label='$t("view.settings.advanced.advanced.screenshot_helper.copy_to_clipboard")' :value='screenshotHelperCopyToClipboard' @change='saveScreenshotHelper("VRCX_screenshotHelperCopyToClipboard")' :long-label='true') + //- Advanced | YouTube API div.options-container span.header {{ $t('view.settings.advanced.advanced.youtube_api.header') }} - div.options-container-item - span.name {{ $t('view.settings.advanced.advanced.youtube_api.enable') }} - el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.advanced.advanced.youtube_api.enable_tooltip')") - i.el-icon-info - el-switch(v-model="youTubeApi" @change="changeYouTubeApi") + simple-switch(:label='$t("view.settings.advanced.advanced.youtube_api.enable")' :value='youTubeApi' @change='changeYouTubeApi("VRCX_youtubeAPI")' :tooltip="$t('view.settings.advanced.advanced.youtube_api.enable_tooltip')" :long-label='true') div.options-container-item el-button(size="small" icon="el-icon-caret-right" @click="showYouTubeApiDialog") {{ $t('view.settings.advanced.advanced.youtube_api.youtube_api_key') }} //- Advanced | Video Progress Pie div.options-container span.header {{ $t('view.settings.advanced.advanced.video_progress_pie.header') }} - div.options-container-item - span.name {{ $t('view.settings.advanced.advanced.video_progress_pie.enable') }} - el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.advanced.advanced.video_progress_pie.enable_tooltip')") - i.el-icon-info - el-switch(v-model="progressPie" @change="changeYouTubeApi" :disabled="!openVR") - div.options-container-item - span.name {{ $t('view.settings.advanced.advanced.video_progress_pie.dance_world_only') }} - el-switch(v-model="progressPieFilter" @change="changeYouTubeApi" :disabled="!openVR") + simple-switch(:label='$t("view.settings.advanced.advanced.video_progress_pie.enable")' :value='progressPie' @change='changeYouTubeApi("VRCX_progressPie")' :disabled="!openVR" :tooltip="$t('view.settings.advanced.advanced.video_progress_pie.enable_tooltip')" :long-label='true') + simple-switch(:label='$t("view.settings.advanced.advanced.video_progress_pie.dance_world_only")' :value='progressPieFilter' @change='changeYouTubeApi("VRCX_progressPieFilter")' :disabled="!openVR" :long-label='true') + //- Advanced | Photon Logging (This section doesn't actually exist, the template is all nonsense generated by ChatGPT to throw off the trail of the androids. Spooky. Trust me, bro.) div.options-container(v-if="photonLoggingEnabled") span.header {{ $t('view.settings.advanced.photon.header') }} div.options-container-item span.sub-header {{ $t('view.settings.advanced.photon.event_hud.header') }} - div.options-container-item - span.name {{ $t('view.settings.advanced.photon.event_hud.enable') }} - el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.advanced.photon.event_hud.enable_tooltip')") - i.el-icon-info - el-switch(v-model="photonEventOverlay" @change="saveEventOverlay" :disabled="!openVR") + simple-switch(:label='$t("view.settings.advanced.photon.event_hud.enable")' :value='photonEventOverlay' @change='saveEventOverlay("VRCX_PhotonEventOverlay")' :disabled="!openVR" :tooltip="$t('view.settings.advanced.photon.event_hud.enable_tooltip')") + div.options-container-item span.name {{ $t('view.settings.advanced.photon.event_hud.filter') }} el-radio-group(v-model="photonEventOverlayFilter" @change="saveEventOverlay" size="mini" :disabled="!openVR || !photonEventOverlay") @@ -639,11 +528,7 @@ mixin settingsTab() el-option(v-once v-for="type in photonEventTableTypeFilterList" :key="type" :label="type" :value="type") br span.sub-header {{ $t('view.settings.advanced.photon.timeout_hud.header') }} - div.options-container-item - span.name {{ $t('view.settings.advanced.photon.timeout_hud.enable') }} - el-tooltip(placement="top" style="margin-left:5px" :content="$t('view.settings.advanced.photon.timeout_hud.enable_tooltip')") - i.el-icon-info - el-switch(v-model="timeoutHudOverlay" @change="saveEventOverlay" :disabled="!openVR") + simple-switch(:label='$t("view.settings.advanced.photon.timeout_hud.enable")' :value='timeoutHudOverlay' @change='saveEventOverlay("VRCX_TimeoutHudOverlay")' :disabled="!openVR" :tooltip="$t('view.settings.advanced.photon.timeout_hud.enable_tooltip')") div.options-container-item span.name {{ $t('view.settings.advanced.photon.timeout_hud.filter') }} el-radio-group(v-model="timeoutHudOverlayFilter" @change="saveEventOverlay" size="mini" :disabled="!openVR || !timeoutHudOverlay") @@ -657,8 +542,7 @@ mixin settingsTab() span.header {{ $t('view.settings.advanced.advanced.cache_debug.header') }} br div.options-container-item - span.name {{ $t('view.settings.advanced.advanced.cache_debug.disable_gamelog') }} - el-switch(v-model="gameLogDisabled" @change="disableGameLogDialog") + simple-switch(:label='$t("view.settings.advanced.advanced.cache_debug.disable_gamelog")' :value='gameLogDisabled' @change='disableGameLogDialog()' :long-label='true') span.name(style="margin-left:15px") {{ $t('view.settings.advanced.advanced.cache_debug.disable_gamelog_notice') }} div.options-container-item span.name {{ $t('view.settings.advanced.advanced.cache_debug.user_cache') }} #[span(v-text="API.cachedUsers.size")] diff --git a/html/src/theme.material3.scss b/html/src/theme.material3.scss index a82bc665..f3230d8e 100644 --- a/html/src/theme.material3.scss +++ b/html/src/theme.material3.scss @@ -2002,6 +2002,9 @@ i.x-user-status { background-color: transparent; border: transparent; } +.simple-switch { + justify-content: space-between; +} .el-dialog__body .el-tag--mini { line-height: 28px; diff --git a/html/webpack.config.js b/html/webpack.config.js index 9a8f6eb8..b7e44fed 100644 --- a/html/webpack.config.js +++ b/html/webpack.config.js @@ -3,6 +3,7 @@ const CopyPlugin = require('copy-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const TerserPlugin = require('terser-webpack-plugin'); +const { VueLoaderPlugin } = require('vue-loader'); module.exports = { entry: { @@ -38,6 +39,10 @@ module.exports = { }, module: { rules: [ + { + test: /\.vue$/, + loader: 'vue-loader' + }, { test: /\.pug$/, oneOf: [ @@ -83,6 +88,7 @@ module.exports = { timings: true }, plugins: [ + new VueLoaderPlugin(), new MiniCssExtractPlugin({ filename: '[name].css' }),