mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 14:53:50 +02:00
Delete screenshot metadata
This commit is contained in:
@@ -11,118 +11,155 @@ namespace VRCX;
|
|||||||
|
|
||||||
public partial class AppApi
|
public partial class AppApi
|
||||||
{
|
{
|
||||||
public string GetExtraScreenshotData(string path, bool carouselCache)
|
public string GetExtraScreenshotData(string path, bool carouselCache)
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileNameWithoutExtension(path);
|
||||||
|
var metadata = new JObject();
|
||||||
|
|
||||||
|
if (!File.Exists(path) || !path.EndsWith(".png"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var files = Directory.GetFiles(Path.GetDirectoryName(path), "*.png");
|
||||||
|
|
||||||
|
// Add previous/next file paths to metadata so the screenshot viewer carousel can request metadata for next/previous images in directory
|
||||||
|
if (carouselCache)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileNameWithoutExtension(path);
|
var index = Array.IndexOf(files, path);
|
||||||
var metadata = new JObject();
|
if (index > 0)
|
||||||
|
|
||||||
if (!File.Exists(path) || !path.EndsWith(".png"))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var files = Directory.GetFiles(Path.GetDirectoryName(path), "*.png");
|
|
||||||
|
|
||||||
// Add previous/next file paths to metadata so the screenshot viewer carousel can request metadata for next/previous images in directory
|
|
||||||
if (carouselCache)
|
|
||||||
{
|
{
|
||||||
var index = Array.IndexOf(files, path);
|
metadata.Add("previousFilePath", files[index - 1]);
|
||||||
if (index > 0)
|
}
|
||||||
{
|
if (index < files.Length - 1)
|
||||||
metadata.Add("previousFilePath", files[index - 1]);
|
{
|
||||||
}
|
metadata.Add("nextFilePath", files[index + 1]);
|
||||||
if (index < files.Length - 1)
|
|
||||||
{
|
|
||||||
metadata.Add("nextFilePath", files[index + 1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using var png = new PNGFile(path);
|
|
||||||
metadata.Add("fileResolution", PNGHelper.ReadResolution(png));
|
|
||||||
|
|
||||||
var creationDate = File.GetCreationTime(path);
|
|
||||||
metadata.Add("creationDate", creationDate.ToString("yyyy-MM-dd HH:mm:ss"));
|
|
||||||
|
|
||||||
var fileSizeBytes = new FileInfo(path).Length;
|
|
||||||
metadata.Add("fileSizeBytes", fileSizeBytes.ToString());
|
|
||||||
metadata.Add("fileName", fileName);
|
|
||||||
metadata.Add("filePath", path);
|
|
||||||
metadata.Add("fileSize", $"{(fileSizeBytes / 1024f / 1024f).ToString("0.00")} MB");
|
|
||||||
|
|
||||||
return metadata.ToString(Formatting.Indented);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetScreenshotMetadata(string path)
|
using var png = new PNGFile(path);
|
||||||
|
metadata.Add("fileResolution", PNGHelper.ReadResolution(png));
|
||||||
|
|
||||||
|
var creationDate = File.GetCreationTime(path);
|
||||||
|
metadata.Add("creationDate", creationDate.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
var fileSizeBytes = new FileInfo(path).Length;
|
||||||
|
metadata.Add("fileSizeBytes", fileSizeBytes.ToString());
|
||||||
|
metadata.Add("fileName", fileName);
|
||||||
|
metadata.Add("filePath", path);
|
||||||
|
metadata.Add("fileSize", $"{(fileSizeBytes / 1024f / 1024f).ToString("0.00")} MB");
|
||||||
|
|
||||||
|
return metadata.ToString(Formatting.Indented);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetScreenshotMetadata(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
|
||||||
|
var metadata = ScreenshotHelper.GetScreenshotMetadata(path);
|
||||||
|
|
||||||
|
if (metadata == null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(path))
|
var obj = new JObject
|
||||||
return null;
|
|
||||||
|
|
||||||
|
|
||||||
var metadata = ScreenshotHelper.GetScreenshotMetadata(path);
|
|
||||||
|
|
||||||
if (metadata == null)
|
|
||||||
{
|
{
|
||||||
var obj = new JObject
|
{ "sourceFile", path },
|
||||||
{
|
{ "error", "Screenshot contains no metadata." }
|
||||||
{ "sourceFile", path },
|
|
||||||
{ "error", "Screenshot contains no metadata." }
|
|
||||||
};
|
|
||||||
|
|
||||||
return obj.ToString(Formatting.Indented);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (metadata.Error != null)
|
return obj.ToString(Formatting.Indented);
|
||||||
{
|
};
|
||||||
var obj = new JObject
|
|
||||||
{
|
|
||||||
{ "sourceFile", path },
|
|
||||||
{ "error", metadata.Error }
|
|
||||||
};
|
|
||||||
|
|
||||||
return obj.ToString(Formatting.Indented);
|
if (metadata.Error != null)
|
||||||
}
|
|
||||||
|
|
||||||
return JsonConvert.SerializeObject(metadata, Formatting.Indented, new JsonSerializerSettings
|
|
||||||
{
|
|
||||||
ContractResolver = new DefaultContractResolver
|
|
||||||
{
|
|
||||||
NamingStrategy = new CamelCaseNamingStrategy() // This'll serialize our .net property names to their camelCase equivalents. Ex; "FileName" -> "fileName"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public string FindScreenshotsBySearch(string searchQuery, int searchType = 0)
|
|
||||||
{
|
{
|
||||||
var stopwatch = new Stopwatch();
|
var obj = new JObject
|
||||||
stopwatch.Start();
|
|
||||||
|
|
||||||
var searchPath = GetVRChatPhotosLocation();
|
|
||||||
var screenshots = ScreenshotHelper.FindScreenshots(searchQuery, searchPath, (ScreenshotHelper.ScreenshotSearchType)searchType);
|
|
||||||
|
|
||||||
JArray json = new JArray();
|
|
||||||
|
|
||||||
foreach (var screenshot in screenshots)
|
|
||||||
{
|
{
|
||||||
json.Add(screenshot.SourceFile);
|
{ "sourceFile", path },
|
||||||
}
|
{ "error", metadata.Error }
|
||||||
|
};
|
||||||
|
|
||||||
stopwatch.Stop();
|
return obj.ToString(Formatting.Indented);
|
||||||
|
|
||||||
logger.Info($"FindScreenshotsBySearch took {stopwatch.ElapsedMilliseconds}ms to complete.");
|
|
||||||
|
|
||||||
return json.ToString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLastScreenshot()
|
return JsonConvert.SerializeObject(metadata, Formatting.Indented, new JsonSerializerSettings
|
||||||
{
|
{
|
||||||
// Get the last screenshot taken by VRChat
|
ContractResolver = new DefaultContractResolver
|
||||||
var path = GetVRChatPhotosLocation();
|
{
|
||||||
if (!Directory.Exists(path))
|
NamingStrategy = new CamelCaseNamingStrategy() // This'll serialize our .net property names to their camelCase equivalents. Ex; "FileName" -> "fileName"
|
||||||
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;
|
public string FindScreenshotsBySearch(string searchQuery, int searchType = 0)
|
||||||
|
{
|
||||||
|
var stopwatch = new Stopwatch();
|
||||||
|
stopwatch.Start();
|
||||||
|
|
||||||
|
var searchPath = GetVRChatPhotosLocation();
|
||||||
|
var screenshots = ScreenshotHelper.FindScreenshots(searchQuery, searchPath, (ScreenshotHelper.ScreenshotSearchType)searchType);
|
||||||
|
|
||||||
|
JArray json = new JArray();
|
||||||
|
|
||||||
|
foreach (var screenshot in screenshots)
|
||||||
|
{
|
||||||
|
json.Add(screenshot.SourceFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
|
||||||
|
logger.Info($"FindScreenshotsBySearch took {stopwatch.ElapsedMilliseconds}ms to complete.");
|
||||||
|
|
||||||
|
return json.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetLastScreenshot()
|
||||||
|
{
|
||||||
|
// Get the last screenshot taken by VRChat
|
||||||
|
var path = GetVRChatPhotosLocation();
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteScreenshotMetadata(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path) || !File.Exists(path) || !path.EndsWith(".png"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ScreenshotHelper.DeleteTextMetadata(path, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.Error(ex, "Failed to delete screenshot metadata for {0}", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteAllScreenshotMetadata()
|
||||||
|
{
|
||||||
|
var path = GetVRChatPhotosLocation();
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var imageFiles = Directory.GetFiles(path, "*.png", SearchOption.AllDirectories);
|
||||||
|
foreach (var file in imageFiles)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ScreenshotHelper.DeleteTextMetadata(file, true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.Error(ex, "Failed to delete screenshot metadata for {0}", file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -43,7 +43,7 @@ public class PNGFile : IDisposable
|
|||||||
ReadAndCacheMetadata();
|
ReadAndCacheMetadata();
|
||||||
|
|
||||||
var chunk = metadataChunkCache.FirstOrDefault((chunk) => chunkTypeFilter.HasFlag(chunk.ChunkTypeEnum));
|
var chunk = metadataChunkCache.FirstOrDefault((chunk) => chunkTypeFilter.HasFlag(chunk.ChunkTypeEnum));
|
||||||
if (chunk.IsZero())
|
if (chunk == null || chunk.IsZero())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return chunk;
|
return chunk;
|
||||||
@@ -60,7 +60,7 @@ public class PNGFile : IDisposable
|
|||||||
public PNGChunk? GetChunkReverse(PNGChunkTypeFilter chunkTypeFilter)
|
public PNGChunk? GetChunkReverse(PNGChunkTypeFilter chunkTypeFilter)
|
||||||
{
|
{
|
||||||
var chunk = ReadChunkReverse(chunkTypeFilter);
|
var chunk = ReadChunkReverse(chunkTypeFilter);
|
||||||
if (chunk != null && chunk.IsZero())
|
if (chunk == null || chunk.IsZero())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return chunk;
|
return chunk;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace VRCX
|
|||||||
/// If true, the function searches from the end of the file using a reverse search bruteforce method.
|
/// If true, the function searches from the end of the file using a reverse search bruteforce method.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The text associated with the specified keyword, or null if not found.</returns>
|
/// <returns>The text associated with the specified keyword, or null if not found.</returns>
|
||||||
public static string ReadTextChunk(string keyword, PNGFile pngFile, bool legacySearch = false)
|
public static string? ReadTextChunk(string keyword, PNGFile pngFile, bool legacySearch = false)
|
||||||
{
|
{
|
||||||
// Search for legacy text chunks created by old vrchat mods
|
// Search for legacy text chunks created by old vrchat mods
|
||||||
if (legacySearch)
|
if (legacySearch)
|
||||||
|
|||||||
@@ -582,6 +582,13 @@
|
|||||||
"header": "Save Instance Emoji To File",
|
"header": "Save Instance Emoji To File",
|
||||||
"description": "Save spawned emoji to your VRChat Pictures folder"
|
"description": "Save spawned emoji to your VRChat Pictures folder"
|
||||||
},
|
},
|
||||||
|
"delete_all_screenshot_metadata": {
|
||||||
|
"button": "Delete Screenshot Metadata",
|
||||||
|
"ask": "Are you sure you want to delete all VRC & VRCX screenshot metadata from your VRChat Pictures folder?",
|
||||||
|
"confirm": "Deleting all screenshot metadata is a very destructive action and cannot be undone! This includes all prints, sub folders and other unrelated images in your VRChat Pictures folder, if these photos are precious to you, please make a backup before proceeding.",
|
||||||
|
"confirm_yes": "Yes",
|
||||||
|
"confirm_no": "No"
|
||||||
|
},
|
||||||
"remote_database": {
|
"remote_database": {
|
||||||
"header": "Remote Avatar Database",
|
"header": "Remote Avatar Database",
|
||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
@@ -1533,6 +1540,7 @@
|
|||||||
"last_screenshot": "Last Screenshot",
|
"last_screenshot": "Last Screenshot",
|
||||||
"copy_image": "Copy Image",
|
"copy_image": "Copy Image",
|
||||||
"open_folder": "Open Folder",
|
"open_folder": "Open Folder",
|
||||||
|
"delete_metadata": "Delete Metadata",
|
||||||
"upload": "Upload"
|
"upload": "Upload"
|
||||||
},
|
},
|
||||||
"registry_backup": {
|
"registry_backup": {
|
||||||
@@ -1692,6 +1700,10 @@
|
|||||||
},
|
},
|
||||||
"friend": {
|
"friend": {
|
||||||
"load_failed": "Failed to load friends list, logging out"
|
"load_failed": "Failed to load friends list, logging out"
|
||||||
|
},
|
||||||
|
"screenshot_metadata": {
|
||||||
|
"deleted": "Screenshot metadata deleted",
|
||||||
|
"delete_failed": "Failed to delete screenshot metadata"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prompt": {
|
"prompt": {
|
||||||
|
|||||||
@@ -512,6 +512,71 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function askDeleteAllScreenshotMetadata() {
|
||||||
|
$app.$confirm(
|
||||||
|
t(
|
||||||
|
'view.settings.advanced.advanced.delete_all_screenshot_metadata.ask'
|
||||||
|
),
|
||||||
|
{
|
||||||
|
confirmButtonText: t(
|
||||||
|
'view.settings.advanced.advanced.delete_all_screenshot_metadata.confirm_yes'
|
||||||
|
),
|
||||||
|
cancelButtonText: t(
|
||||||
|
'view.settings.advanced.advanced.delete_all_screenshot_metadata.confirm_no'
|
||||||
|
),
|
||||||
|
type: 'warning',
|
||||||
|
showInput: false,
|
||||||
|
callback: async (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
deleteAllScreenshotMetadata();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteAllScreenshotMetadata() {
|
||||||
|
$app.$confirm(
|
||||||
|
t(
|
||||||
|
'view.settings.advanced.advanced.delete_all_screenshot_metadata.confirm'
|
||||||
|
),
|
||||||
|
{
|
||||||
|
confirmButtonText: t(
|
||||||
|
'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old_confirm'
|
||||||
|
),
|
||||||
|
cancelButtonText: t(
|
||||||
|
'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old_cancel'
|
||||||
|
),
|
||||||
|
type: 'warning',
|
||||||
|
showInput: false,
|
||||||
|
callback: async (action) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
const msgBox = $app.$message({
|
||||||
|
message: 'Batch metadata removal in progress...',
|
||||||
|
type: 'warning',
|
||||||
|
duration: 0
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await AppApi.DeleteAllScreenshotMetadata();
|
||||||
|
$app.$message({
|
||||||
|
message: 'Batch metadata removal complete',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
$app.$message({
|
||||||
|
message: `Batch metadata removal failed: ${err}`,
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
msgBox.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function resetUGCFolder() {
|
function resetUGCFolder() {
|
||||||
setUGCFolderPath('');
|
setUGCFolderPath('');
|
||||||
}
|
}
|
||||||
@@ -647,6 +712,7 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
|||||||
showVRChatConfig,
|
showVRChatConfig,
|
||||||
promptAutoClearVRCXCacheFrequency,
|
promptAutoClearVRCXCacheFrequency,
|
||||||
setSaveInstanceEmoji,
|
setSaveInstanceEmoji,
|
||||||
setVrcRegistryAutoBackup
|
setVrcRegistryAutoBackup,
|
||||||
|
askDeleteAllScreenshotMetadata
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
2
src/types/globals.d.ts
vendored
2
src/types/globals.d.ts
vendored
@@ -290,6 +290,8 @@ declare global {
|
|||||||
searchType?: number
|
searchType?: number
|
||||||
): Promise<string>;
|
): Promise<string>;
|
||||||
GetLastScreenshot(): Promise<string>;
|
GetLastScreenshot(): Promise<string>;
|
||||||
|
DeleteScreenshotMetadata(path: string): Promise<boolean>;
|
||||||
|
DeleteAllScreenshotMetadata(): Promise<void>;
|
||||||
|
|
||||||
// Moderations
|
// Moderations
|
||||||
GetVRChatModerations(
|
GetVRChatModerations(
|
||||||
|
|||||||
@@ -1285,6 +1285,9 @@
|
|||||||
:value="screenshotHelperCopyToClipboard"
|
:value="screenshotHelperCopyToClipboard"
|
||||||
@change="setScreenshotHelperCopyToClipboard()"
|
@change="setScreenshotHelperCopyToClipboard()"
|
||||||
:long-label="true" />
|
:long-label="true" />
|
||||||
|
<el-button size="small" icon="el-icon-delete" @click="askDeleteAllScreenshotMetadata()">{{
|
||||||
|
t('view.settings.advanced.advanced.delete_all_screenshot_metadata.button')
|
||||||
|
}}</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="options-container">
|
<div class="options-container">
|
||||||
@@ -2113,7 +2116,8 @@
|
|||||||
openUGCFolderSelector,
|
openUGCFolderSelector,
|
||||||
showVRChatConfig,
|
showVRChatConfig,
|
||||||
promptAutoClearVRCXCacheFrequency,
|
promptAutoClearVRCXCacheFrequency,
|
||||||
setSaveInstanceEmoji
|
setSaveInstanceEmoji,
|
||||||
|
askDeleteAllScreenshotMetadata
|
||||||
} = advancedSettingsStore;
|
} = advancedSettingsStore;
|
||||||
|
|
||||||
const instanceTypes = ref([
|
const instanceTypes = ref([
|
||||||
|
|||||||
@@ -42,6 +42,13 @@
|
|||||||
@click="uploadScreenshotToGallery"
|
@click="uploadScreenshotToGallery"
|
||||||
>{{ t('dialog.screenshot_metadata.upload') }}</el-button
|
>{{ t('dialog.screenshot_metadata.upload') }}</el-button
|
||||||
>
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="screenshotMetadataDialog.metadata.filePath"
|
||||||
|
size="small"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="deleteMetadata(screenshotMetadataDialog.metadata.filePath)"
|
||||||
|
>{{ t('dialog.screenshot_metadata.delete_metadata') }}</el-button
|
||||||
|
>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@@ -279,6 +286,26 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function deleteMetadata(path) {
|
||||||
|
if (!path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AppApi.DeleteScreenshotMetadata(path).then((result) => {
|
||||||
|
if (!result) {
|
||||||
|
$message({
|
||||||
|
message: t('message.screenshot_metadata.delete_failed'),
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$message({
|
||||||
|
message: t('message.screenshot_metadata.deleted'),
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
const D = props.screenshotMetadataDialog;
|
||||||
|
getAndDisplayScreenshot(D.metadata.filePath, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
function uploadScreenshotToGallery() {
|
function uploadScreenshotToGallery() {
|
||||||
const D = props.screenshotMetadataDialog;
|
const D = props.screenshotMetadataDialog;
|
||||||
if (D.metadata.fileSizeBytes > 10000000) {
|
if (D.metadata.fileSizeBytes > 10000000) {
|
||||||
|
|||||||
Reference in New Issue
Block a user