From 885ead4edfdd96623a18642fffe2005cd8659aef Mon Sep 17 00:00:00 2001 From: Natsumi Date: Tue, 14 Jan 2025 00:58:20 +1300 Subject: [PATCH] Fixes, sort group instances --- Dotnet/AppApi/Electron/AppApiElectron.cs | 24 ++++++++++++- Dotnet/AppApi/Electron/Folders.cs | 45 ++++++++++++------------ build-scripts/make-junction.cmd | 7 +++- src-electron/main.js | 10 +++++- src/app.js | 34 +++++++++++++++--- src/classes/groups.js | 1 + src/mixins/tabs/settings.pug | 24 ++++++------- 7 files changed, 103 insertions(+), 42 deletions(-) diff --git a/Dotnet/AppApi/Electron/AppApiElectron.cs b/Dotnet/AppApi/Electron/AppApiElectron.cs index ad7cad21..ff9422db 100644 --- a/Dotnet/AppApi/Electron/AppApiElectron.cs +++ b/Dotnet/AppApi/Electron/AppApiElectron.cs @@ -83,7 +83,29 @@ namespace VRCX public override string GetClipboard() { - return string.Empty; + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "xclip", + Arguments = "-o", + UseShellExecute = false, + RedirectStandardOutput = true, + CreateNoWindow = true + } + }; + try + { + process.Start(); + var output = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + return output; + } + catch (Exception ex) + { + logger.Error($"Failed to get clipboard: {ex.Message}"); + return string.Empty; + } } public override void SetStartup(bool enabled) diff --git a/Dotnet/AppApi/Electron/Folders.cs b/Dotnet/AppApi/Electron/Folders.cs index 308784f8..b080cc7b 100644 --- a/Dotnet/AppApi/Electron/Folders.cs +++ b/Dotnet/AppApi/Electron/Folders.cs @@ -22,6 +22,7 @@ namespace VRCX static AppApiElectron() { + const string vrchatAppid = "438100"; _homeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); _steamPath = Path.Combine(_homeDirectory, ".local/share/Steam"); var flatpakSteamPath = Path.Combine(_homeDirectory, ".var/app/com.valvesoftware.Steam/.local/share/Steam"); @@ -31,39 +32,39 @@ namespace VRCX _steamPath = flatpakSteamPath; } _steamUserdataPath = Path.Combine(_homeDirectory, ".steam/steam/userdata"); - - string vrchatAppid = "438100"; - string libraryfoldersVdfPath = Path.Combine(_steamPath, "config", "libraryfolders.vdf"); - string maybeSteamLibraryPath = null; - if (!File.Exists(libraryfoldersVdfPath)) + + var libraryFoldersVdfPath = Path.Combine(_steamPath, "config/libraryfolders.vdf"); + var vrcLibraryPath = GetLibraryWithAppId(libraryFoldersVdfPath, vrchatAppid); + if (string.IsNullOrEmpty(vrcLibraryPath)) { - logger.Error("libraryfolders.vdf not found"); - } else { - maybeSteamLibraryPath = GetLibraryWithAppId(libraryfoldersVdfPath, vrchatAppid); - } - - string vrcLibraryPath = null; - if (maybeSteamLibraryPath == null) - { - logger.Warn("falling back to default VRChat path as libraryfolders.vdf was not found OR libraryfolders.vdf does not contain VRChat's appid (438100)"); + logger.Warn("Falling back to default VRChat path as libraryfolders.vdf was not found OR libraryfolders.vdf does not contain VRChat's appid (438100)"); vrcLibraryPath = _steamPath; - } else { - logger.Info($"Using steam library path {maybeSteamLibraryPath}"); - vrcLibraryPath = maybeSteamLibraryPath; } + logger.Info($"Using steam library path {vrcLibraryPath}"); _vrcPrefixPath = Path.Combine(vrcLibraryPath, $"steamapps/compatdata/{vrchatAppid}/pfx"); _vrcAppDataPath = Path.Combine(_vrcPrefixPath, "drive_c/users/steamuser/AppData/LocalLow/VRChat/VRChat"); } - private static string? GetLibraryWithAppId(string pathToLibraryFolders, string appid) + private static string? GetLibraryWithAppId(string libraryFoldersVdfPath, string appId) { - string? libraryPath = null; - foreach (var line in File.ReadLines(pathToLibraryFolders)) + if (!File.Exists(libraryFoldersVdfPath)) + return null; + + foreach (var line in File.ReadLines(libraryFoldersVdfPath)) { + string? libraryPath = null; // Assumes line will be \t\t"path"\t\t"pathToLibrary" - if (line.Contains("\"path\"")) libraryPath = line.Split("\t")[4].Replace("\"", ""); + if (line.Contains("\"path\"")) + { + var parts = line.Split("\t"); + if (parts.Length < 4) + continue; + + libraryPath = parts[4].Replace("\"", ""); + } - if (line.Contains($"\"{appid}\"")) return libraryPath; + if (line.Contains($"\"{appId}\"")) + return libraryPath; } return null; diff --git a/build-scripts/make-junction.cmd b/build-scripts/make-junction.cmd index 8d456d6d..2c617cff 100644 --- a/build-scripts/make-junction.cmd +++ b/build-scripts/make-junction.cmd @@ -1 +1,6 @@ -mklink /J "%~dp0\..\build\Cef\html" "%~dp0\..\build\html" \ No newline at end of file +@echo off +setlocal enabledelayedexpansion + +if not exist "%~dp0\..\build\Cef\html" ( + mklink /J "%~dp0\..\build\Cef\html" "%~dp0\..\build\html" +) \ No newline at end of file diff --git a/src-electron/main.js b/src-electron/main.js index d9153607..975d84c6 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -18,6 +18,10 @@ if (!isDotNetInstalled()) { return; } +// get launch arguments +const args = process.argv.slice(1); +const noInstall = args.some((val) => val === '--no-install'); + tryCopyFromWinePrefix(); const rootDir = app.getAppPath(); @@ -285,6 +289,10 @@ async function installVRCX() { console.error('AppImage path is not available!'); return; } + if (noInstall) { + console.log('Skipping installation.'); + return; + } /* let appImageLauncherInstalled = false; @@ -455,7 +463,7 @@ function isDotNetInstalled() { encoding: 'utf-8' } ); - return result.stdout.includes('.NETCore.App 8.0'); + return result.stdout?.includes('.NETCore.App 8.0'); } function tryCopyFromWinePrefix() { diff --git a/src/app.js b/src/app.js index 2b59607e..16115a70 100644 --- a/src/app.js +++ b/src/app.js @@ -4301,10 +4301,13 @@ console.log(`isLinux: ${LINUX}`); $app.friends.clear(); $app.pendingActiveFriends.clear(); $app.friendNumber = 0; + $app.isFriendsGroupMe = true; $app.isVIPFriends = true; $app.isOnlineFriends = true; $app.isActiveFriends = true; $app.isOfflineFriends = false; + $app.isGroupInstances = false; + $app.groupInstances = []; $app.vipFriends_ = []; $app.onlineFriends_ = []; $app.activeFriends_ = []; @@ -4313,6 +4316,7 @@ console.log(`isLinux: ${LINUX}`); $app.sortOnlineFriends = false; $app.sortActiveFriends = false; $app.sortOfflineFriends = false; + $app.updateInGameGroupOrder(); }); API.$on('USER:CURRENT', function (args) { @@ -8579,7 +8583,7 @@ console.log(`isLinux: ${LINUX}`); document.head.appendChild($appThemeStyle); } this.updateVRConfigVars(); - await this.updatetrustColor(); + await this.updateTrustColor(); await this.applyWineEmojis(); }; @@ -9158,7 +9162,7 @@ console.log(`isLinux: ${LINUX}`); ) ); - $app.methods.updatetrustColor = async function (setRandomColor = false) { + $app.methods.updateTrustColor = async function (setRandomColor = false) { if (setRandomColor) { this.randomUserColours = !this.randomUserColours; } @@ -9184,10 +9188,10 @@ console.log(`isLinux: ${LINUX}`); API.applyUserTrustLevel(ref); }); } - await this.updatetrustColorClasses(); + await this.updateTrustColorClasses(); }; - $app.methods.updatetrustColorClasses = async function () { + $app.methods.updateTrustColorClasses = async function () { var trustColor = JSON.parse( await configRepository.getString( 'VRCX_trustColor', @@ -9215,7 +9219,7 @@ console.log(`isLinux: ${LINUX}`); style.innerHTML = newCSS; document.getElementsByTagName('head')[0].appendChild(style); }; - await $app.methods.updatetrustColorClasses(); + await $app.methods.updateTrustColorClasses(); $app.data.notificationPosition = await configRepository.getString( 'VRCX_notificationPosition', @@ -16754,9 +16758,11 @@ console.log(`isLinux: ${LINUX}`); location.worldId, this.screenshotHelperModifyFilename ); + console.log('Screenshot metadata added', newPath); } if (this.screenshotHelperCopyToClipboard) { await AppApi.CopyImageToClipboard(newPath); + console.log('Screenshot copied to clipboard', newPath); } }; @@ -17705,6 +17711,9 @@ console.log(`isLinux: ${LINUX}`); var json = await this.getVRChatRegistryKey( `VRC_GROUP_ORDER_${API.currentUser.id}` ); + if (!json) { + return; + } this.inGameGroupOrder = JSON.parse(json); } catch (err) { console.error(err); @@ -17726,6 +17735,21 @@ console.log(`isLinux: ${LINUX}`); return aIndex - bIndex; }; + $app.methods.sortGroupInstancesByInGame = function (a, b) { + var aIndex = this.inGameGroupOrder.indexOf(a?.group?.id); + var bIndex = this.inGameGroupOrder.indexOf(b?.group?.id); + if (aIndex === -1 && bIndex === -1) { + return 0; + } + if (aIndex === -1) { + return 1; + } + if (bIndex === -1) { + return -1; + } + return aIndex - bIndex; + }; + $app.methods.sortCurrentUserGroups = async function () { var D = this.userDialog; var sortMethod = function () {}; diff --git a/src/classes/groups.js b/src/classes/groups.js index 8596d026..10f323da 100644 --- a/src/classes/groups.js +++ b/src/classes/groups.js @@ -1239,6 +1239,7 @@ export default class extends baseClass { instance: this.applyInstance(json) }); } + $app.groupInstances.sort(this.sortGroupInstancesByInGame); }); /** diff --git a/src/mixins/tabs/settings.pug b/src/mixins/tabs/settings.pug index 32cd9044..85a02000 100644 --- a/src/mixins/tabs/settings.pug +++ b/src/mixins/tabs/settings.pug @@ -187,7 +187,7 @@ mixin settingsTab() span.name {{ $t('view.settings.appearance.appearance.zoom') }} el-input-number(size="small" v-model="zoomLevel" @change="setZoomLevel" :precision="0" style="width:128px") 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.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') }} @@ -257,8 +257,8 @@ mixin settingsTab() //- Appearance | User Dialog div.options-container span.header {{ $t('view.settings.appearance.user_dialog.header') }} - 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")') + 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 @@ -270,28 +270,28 @@ mixin settingsTab() //- Appearance | User Colors div.options-container span.header {{ $t('view.settings.appearance.user_colors.header') }} - simple-switch(:label='$t("view.settings.appearance.user_colors.random_colors_from_user_id")' :value='randomUserColours' @change='updatetrustColor(true)') + 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']") + el-color-picker(v-model="trustColor.untrusted" @change="updateTrustColor(false)" size="mini" :predefine="['#CCCCCC']") span.color-picker(slot="trigger" class="x-tag-untrusted") Visitor div - el-color-picker(v-model="trustColor.basic" @change="updatetrustColor" size="mini" :predefine="['#1778ff']") + el-color-picker(v-model="trustColor.basic" @change="updateTrustColor(false)" size="mini" :predefine="['#1778ff']") span.color-picker(slot="trigger" class="x-tag-basic") New User div - el-color-picker(v-model="trustColor.known" @change="updatetrustColor" size="mini" :predefine="['#2bcf5c']") + el-color-picker(v-model="trustColor.known" @change="updateTrustColor(false)" size="mini" :predefine="['#2bcf5c']") span.color-picker(slot="trigger" class="x-tag-known") User div - el-color-picker(v-model="trustColor.trusted" @change="updatetrustColor" size="mini" :predefine="['#ff7b42']") + el-color-picker(v-model="trustColor.trusted" @change="updateTrustColor(false)" size="mini" :predefine="['#ff7b42']") span.color-picker(slot="trigger" class="x-tag-trusted") Known User div - el-color-picker(v-model="trustColor.veteran" @change="updatetrustColor" size="mini" :predefine="['#b18fff', '#8143e6', '#ff69b4', '#b52626', '#ffd000', '#abcdef']") + el-color-picker(v-model="trustColor.veteran" @change="updateTrustColor(false)" size="mini" :predefine="['#b18fff', '#8143e6', '#ff69b4', '#b52626', '#ffd000', '#abcdef']") span.color-picker(slot="trigger" class="x-tag-veteran") Trusted User div - el-color-picker(v-model="trustColor.vip" @change="updatetrustColor" size="mini" :predefine="['#ff2626']") + el-color-picker(v-model="trustColor.vip" @change="updateTrustColor(false)" size="mini" :predefine="['#ff2626']") span.color-picker(slot="trigger" class="x-tag-vip") VRChat Team div - el-color-picker(v-model="trustColor.troll" @change="updatetrustColor" size="mini" :predefine="['#782f2f']") + el-color-picker(v-model="trustColor.troll" @change="updateTrustColor(false)" size="mini" :predefine="['#782f2f']") span.color-picker(slot="trigger" class="x-tag-troll") Nuisance //- Notifications Tab @@ -391,7 +391,7 @@ mixin settingsTab() el-radio(:label="true") {{ "SteamVR" }} div.options-container-item span.name {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.overlay_button') }} - el-radio-group(v-model="overlaybutton" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist") + el-radio-group(v-model="overlaybutton" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist") el-radio(:label="false") {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.overlay_button_grip') }} el-radio(:label="true") {{ $t('view.settings.wrist_overlay.steamvr_wrist_overlay.overlay_button_menu') }} div.options-container-item