diff --git a/Dotnet/AppApi/Common/Screenshot.cs b/Dotnet/AppApi/Common/Screenshot.cs
index c18a6a95..8da85883 100644
--- a/Dotnet/AppApi/Common/Screenshot.cs
+++ b/Dotnet/AppApi/Common/Screenshot.cs
@@ -116,14 +116,11 @@ public partial class AppApi
var path = GetVRChatPhotosLocation();
if (!Directory.Exists(path))
return null;
-
- var lastDirectory = Directory.GetDirectories(path).OrderByDescending(Directory.GetCreationTime).FirstOrDefault();
- if (lastDirectory == null)
- return null;
-
- var lastScreenshot = Directory.GetFiles(lastDirectory, "*.png").OrderByDescending(File.GetCreationTime).FirstOrDefault();
- if (lastScreenshot == null)
- return null;
+
+ // exclude folder names that contain "Prints" or "Stickers"
+ var imageFiles = Directory.GetFiles(path, "*.png", SearchOption.AllDirectories)
+ .Where(x => !Regex.IsMatch(x, @"\\Prints\\|\\Stickers\\", RegexOptions.IgnoreCase));
+ var lastScreenshot = imageFiles.OrderByDescending(Directory.GetCreationTime).FirstOrDefault();
return lastScreenshot;
}
diff --git a/Dotnet/ScreenshotMetadata/ScreenshotHelper.cs b/Dotnet/ScreenshotMetadata/ScreenshotHelper.cs
index 59455406..b8fff74f 100644
--- a/Dotnet/ScreenshotMetadata/ScreenshotHelper.cs
+++ b/Dotnet/ScreenshotMetadata/ScreenshotHelper.cs
@@ -76,16 +76,17 @@ namespace VRCX
if (metadata == null || metadata.Error != null)
{
addToCache.Add(dbEntry);
- metadataCache.Add(file, null);
+ metadataCache.TryAdd(file, null);
continue;
}
dbEntry.Metadata = JsonConvert.SerializeObject(metadata);
addToCache.Add(dbEntry);
- metadataCache.Add(file, metadata);
+ metadataCache.TryAdd(file, metadata);
}
- if (metadata == null) continue;
+ if (metadata == null)
+ continue;
switch (searchType)
{
@@ -121,18 +122,13 @@ namespace VRCX
return result;
}
- ///
- /// Retrieves metadata from a PNG screenshot file and attempts to parse it.
- ///
- /// The path to the PNG screenshot file.
- /// A JObject containing the metadata or null if no metadata was found.
- public static ScreenshotMetadata GetScreenshotMetadata(string path, bool includeJSON = false)
+ public static ScreenshotMetadata? GetScreenshotMetadata(string path, bool includeJSON = false)
{
// Early return if file doesn't exist, or isn't a PNG(Check both extension and file header)
if (!File.Exists(path) || !path.EndsWith(".png") || !IsPNGFile(path))
return null;
- ///if (metadataCache.TryGetValue(path, out var cachedMetadata))
+ // if (metadataCache.TryGetValue(path, out var cachedMetadata))
// return cachedMetadata;
string metadataString;
diff --git a/Dotnet/ScreenshotMetadata/ScreenshotMetadata.cs b/Dotnet/ScreenshotMetadata/ScreenshotMetadata.cs
index 7856393d..62e086f6 100644
--- a/Dotnet/ScreenshotMetadata/ScreenshotMetadata.cs
+++ b/Dotnet/ScreenshotMetadata/ScreenshotMetadata.cs
@@ -57,7 +57,7 @@ namespace VRCX
/// Any error that occurred while parsing the file. This being true implies nothing else is set.
///
[JsonIgnore]
- internal string Error;
+ internal string? Error;
[JsonIgnore]
internal string JSON;
diff --git a/src-electron/main.js b/src-electron/main.js
index 8d9e969d..0589aa34 100644
--- a/src-electron/main.js
+++ b/src-electron/main.js
@@ -17,11 +17,12 @@ if (!isDotNetInstalled()) {
app.quit();
return;
}
+console.log('DOTNET_ROOT:', process.env.DOTNET_ROOT);
// get launch arguments
const args = process.argv.slice(1);
const noInstall = args.some((val) => val === '--no-install');
-
+const homePath = getHomePath();
tryCopyFromWinePrefix();
const rootDir = app.getAppPath();
@@ -261,7 +262,7 @@ async function installVRCXappImageLauncher() {
let targetIconName;
const desktopFiles = fs.readdirSync(
- path.join(app.getPath('home'), '.local/share/applications')
+ path.join(homePath, '.local/share/applications')
);
for (const file of desktopFiles) {
if (file.includes('appimagekit_') && file.includes('VRCX')) {
@@ -284,8 +285,7 @@ async function installVRCXappImageLauncher() {
*/
async function installVRCX() {
- let homePath = getHomePath();
- console.log('True Home path:', homePath);
+ console.log('Home path:', homePath);
console.log('AppImage path:', appImagePath);
if (!appImagePath) {
console.error('AppImage path is not available!');
@@ -302,10 +302,8 @@ async function installVRCX() {
appImageLauncherInstalled = true;
}
*/
-
- if (
- appImagePath.startsWith(path.join(homePath, 'Applications'))
- ) {
+
+ if (appImagePath.startsWith(path.join(homePath, 'Applications'))) {
/*
if (appImageLauncherInstalled) {
installVRCXappImageLauncher();
@@ -332,9 +330,7 @@ async function installVRCX() {
}
if (
- process.env.APPIMAGE.startsWith(
- path.join(homePath, 'Applications')
- ) &&
+ process.env.APPIMAGE.startsWith(path.join(homePath, 'Applications')) &&
path.basename(process.env.APPIMAGE) === 'VRCX.AppImage'
) {
interopApi.getDotNetObject('Update').Init(appImagePath);
@@ -369,10 +365,7 @@ async function installVRCX() {
// Download the icon and save it to the target directory
const iconUrl =
'https://raw.githubusercontent.com/vrcx-team/VRCX/master/VRCX.png';
- const iconPath = path.join(
- homePath,
- '.local/share/icons/VRCX.png'
- );
+ const iconPath = path.join(homePath, '.local/share/icons/VRCX.png');
await downloadIcon(iconUrl, iconPath)
.then(() => {
console.log('Icon downloaded and saved to:', iconPath);
@@ -448,17 +441,13 @@ function getVRCXPath() {
}
function getHomePath() {
- let relativeHomePath = path.join(app.getPath('home'));
- // console.log('Relative Home Path: ' + relativeHomePath);
+ const relativeHomePath = path.join(app.getPath('home'));
try {
- let absoluteHomePath = fs.realpathSync(relativeHomePath);
- // console.log('readlink output: ' + absoluteHomePath);
- return absoluteHomePath;
- }
- catch (err) {
+ const absoluteHomePath = fs.realpathSync(relativeHomePath);
+ return absoluteHomePath;
+ } catch (err) {
return relativeHomePath;
}
-
}
function getVersion() {
@@ -488,7 +477,7 @@ function tryCopyFromWinePrefix() {
// try copy from old wine path
const userName = process.env.USER || process.env.USERNAME;
const oldPath = path.join(
- app.getPath('home'),
+ homePath,
'.local/share/vrcx/drive_c/users',
userName,
'AppData/Roaming/VRCX'
diff --git a/src/app.js b/src/app.js
index 127b9c6c..5bebeee8 100644
--- a/src/app.js
+++ b/src/app.js
@@ -8126,7 +8126,7 @@ console.log(`isLinux: ${LINUX}`);
'[ "https://avtr.just-h.party/vrcx_search.php" ]'
)
);
- $app.data.pendingOfflineDelay = 130000;
+ $app.data.pendingOfflineDelay = 180000;
if (await configRepository.getString('VRCX_avatarRemoteDatabaseProvider')) {
// move existing provider to new list
var avatarRemoteDatabaseProvider = await configRepository.getString(
@@ -16769,9 +16769,12 @@ console.log(`isLinux: ${LINUX}`);
$app.methods.getAndDisplayLastScreenshot = function () {
this.screenshotMetadataResetSearch();
- AppApi.GetLastScreenshot().then((path) =>
- this.getAndDisplayScreenshot(path)
- );
+ AppApi.GetLastScreenshot().then((path) => {
+ if (!path) {
+ return;
+ }
+ this.getAndDisplayScreenshot(path);
+ });
};
/**
@@ -17054,6 +17057,9 @@ console.log(`isLinux: ${LINUX}`);
};
$app.methods.copyImageToClipboard = function (path) {
+ if (!path) {
+ return;
+ }
AppApi.CopyImageToClipboard(path).then(() => {
this.$message({
message: 'Image copied to clipboard',
@@ -17063,6 +17069,9 @@ console.log(`isLinux: ${LINUX}`);
};
$app.methods.openImageFolder = function (path) {
+ if (!path) {
+ return;
+ }
AppApi.OpenFolderAndSelectItem(path).then(() => {
this.$message({
message: 'Opened image folder',
diff --git a/src/classes/apiLogin.js b/src/classes/apiLogin.js
index 9f82a37e..b71f16b3 100644
--- a/src/classes/apiLogin.js
+++ b/src/classes/apiLogin.js
@@ -15,6 +15,7 @@ export default class extends baseClass {
async init() {
API.isLoggedIn = false;
API.attemptingAutoLogin = false;
+ API.autoLoginAttempts = new Set();
/**
* @param {{ username: string, password: string }} params credential to login
@@ -126,9 +127,25 @@ export default class extends baseClass {
return;
}
if ($app.enablePrimaryPassword) {
+ console.error(
+ 'Primary password is enabled, this disables auto login.'
+ );
+ this.attemptingAutoLogin = false;
this.logout();
return;
}
+ var attemptsInLastHour = Array.from(this.autoLoginAttempts).filter(
+ (timestamp) => timestamp > new Date().getTime() - 3600000
+ ).length;
+ if (attemptsInLastHour >= 3) {
+ console.error(
+ 'More than 3 auto login attempts within the past hour, logging out instead of attempting auto login.'
+ );
+ this.attemptingAutoLogin = false;
+ this.logout();
+ return;
+ }
+ this.autoLoginAttempts.add(new Date().getTime());
$app.relogin(user)
.then(() => {
if (this.errorNoty) {
@@ -167,6 +184,7 @@ export default class extends baseClass {
API.$on('LOGOUT', function () {
this.attemptingAutoLogin = false;
+ this.autoLoginAttempts.clear();
});
API.logout = function () {
diff --git a/src/localization/en/en.json b/src/localization/en/en.json
index d154172e..88293682 100644
--- a/src/localization/en/en.json
+++ b/src/localization/en/en.json
@@ -165,7 +165,8 @@
"unmute": "Unmute",
"interactOn": "Interact On",
"interactOff": "Interact Off",
- "muteChat": "Mute chat"
+ "muteChat": "Mute chat",
+ "unmuteChat": "Unmute chat"
}
},
"notification": {
diff --git a/src/views/tabs/Moderation.vue b/src/views/tabs/Moderation.vue
index 1133f9c5..44674a91 100644
--- a/src/views/tabs/Moderation.vue
+++ b/src/views/tabs/Moderation.vue
@@ -171,7 +171,8 @@
'unmute',
'interactOn',
'interactOff',
- 'muteChat'
+ 'muteChat',
+ 'unmuteChat'
],
tableProps: {
stripe: true,