Files
VRCX/ScreenshotMetadata.cs
Teacup 0a0f166a2b feat: Add searching & fullscreen mode to screenshot viewer (#627)
* Optimized search screenshots by metadata

* feat: Screenshot metadata search bar

* fix: Reset search when selecting a file manually

* refactor: Re-do the whole search thing. Add number of results to dialog when searching

* fix: Add check & error for null metadata

* fix: Add sourceFile to error obj on return

* fix: Fix screenshot file dialog not sending path back to JS

* fix: Stop lfs parsing from dying if a value doesn't exist

* fix: Fix and optimize FileStream reading of metadata for searches

* fix: Reset search data and revert to normal when user clears out search box

* refactor: Remove/optimize some old screenshot helper stuff

- Use FileStream in ReadPNGResolution
- Limit the FindChunkIndex search range used when writing metadata
- Remove old ReadPNGDescription, just use filestream version now

* fix: Reset metadata search state if a file is added manually

* feat: Move viewer popover dialog to the fullscreen image viewer

* refactor: Change how parsing errors are handled... again

* refactor: Let the search carousel loop around

* fix: Re-do legacy parsing /wo JObject. Fix legacy instance ids/pos.

Also adds further docs to the legacy parsing for the various formats

* feat: Add persistent metadata cache for search

* Clean up

* fix: Fix viewer dying

sourceFile wasn't being included for vrcx pics

* refactor: Cache the state of files with no metadata

This is so we're not constantly re-processing these files with no metadata on every first search after a restart; These files won't magically gain metadata and this could cause a lot of hitching for someone that had potentially thousands of screenshots before using VRCX.

* Screenshot viewer loading

---------

Co-authored-by: Nekromateion <43814053+Nekromateion@users.noreply.github.com>
Co-authored-by: Natsumi <cmcooper123@hotmail.com>
2023-09-03 09:02:09 +12:00

143 lines
4.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Newtonsoft.Json;
namespace VRCX
{
public class ScreenshotMetadata
{
/// <summary>
/// Name of the application writing to the screenshot. Should be VRCX.
/// </summary>
public string Application { get; set; }
/// <summary>
/// The version of this schema. If the format changes, this number should change.
/// </summary>
public int Version { get; set; }
/// <summary>
/// The details of the user that took the picture.
/// </summary>
public AuthorDetail Author { get; set; }
/// <summary>
/// Information about the world the picture was taken in.
/// </summary>
public WorldDetail World { get; set; }
/// <summary>
/// A list of players in the world at the time the picture was taken.
/// </summary>
public List<PlayerDetail> Players { get; set; }
/// <summary>
/// If this class was serialized from a file, this should be the path to the file.
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
internal string SourceFile;
/// <summary>
/// The position of the player that took the picture when the shot was taken. Not written by VRCX, this is legacy support for reading LFS files.
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public Vector3? Pos { get; set; }
/// <summary>
/// Any error that occurred while parsing the file. This being true implies nothing else is set.
/// </summary>
[JsonIgnore]
internal string Error;
[JsonIgnore]
internal string JSON;
public ScreenshotMetadata()
{
Application = "VRCX";
Version = 1;
Author = new AuthorDetail();
World = new WorldDetail();
Players = new List<PlayerDetail>();
}
public static ScreenshotMetadata JustError(string sourceFile, string error)
{
return new ScreenshotMetadata
{
Error = error,
SourceFile = sourceFile
};
}
public bool ContainsPlayerID(string id)
{
return Players.Any(p => p.Id == id);
}
public bool ContainsPlayerName(string playerName, bool partial, bool ignoreCase)
{
var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
if (partial)
{
return Players.Any(p => p.DisplayName.IndexOf(playerName, comparisonType) != -1);
}
return Players.Any(p => p.DisplayName.Equals(playerName, comparisonType));
}
public class AuthorDetail
{
/// <summary>
/// The ID of the user.
/// </summary>
public string Id { get; set; }
/// <summary>
/// The display name of the user.
/// </summary>
public string DisplayName { get; set; }
}
public class WorldDetail
{
/// <summary>
/// The ID of the world.
/// </summary>
public string Id { get; set; }
/// <summary>
/// The name of the world.
/// </summary>
public string Name { get; set; }
/// <summary>
/// The full ID of the game instance.
/// </summary>
public string InstanceId { get; set; }
}
public class PlayerDetail
{
/// <summary>
/// The ID of the player in the world.
/// </summary>
public string Id { get; set; }
/// <summary>
/// The display name of the player in the world.
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// The position of the player in the world. Not written by VRCX, this is legacy support for reading LFS files.
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public Vector3? Pos { get; set; } = null;
}
}
}