Add queue for print downloads and automatic cropping for saved prints (#1068)

* Add queue for print downloads

To prevent issues with rate limits in instances with a lot of prints switch downloading prints to use a queue.

* Auto cropping for instance print saving

Add option to automatically crop prints saved using the "Save Instance Prints" feature and a popup to apply crop to all previously saved prints while preserving metadata.

---------

Co-authored-by: Natsumi <11171153+Natsumi-sama@users.noreply.github.com>
This commit is contained in:
Nekromateion
2025-01-09 00:47:02 +01:00
committed by GitHub
parent addad7bc06
commit 35621f27d2
6 changed files with 174 additions and 16 deletions

View File

@@ -8602,6 +8602,10 @@ speechSynthesis.getVoices();
this.saveInstancePrints
);
await configRepository.setBool(
'VRCX_cropInstancePrints',
this.cropInstancePrints
);
await configRepository.setBool(
'VRCX_saveInstanceStickers',
this.saveInstanceStickers
@@ -18102,19 +18106,39 @@ speechSynthesis.getVoices();
.replace(/T/g, '_')
.replace(/Z/g, '');
var fileName = `${displayName}_${fileNameDate}_${fileId}.png`;
var status = await AppApi.SaveStickerToFile(
var filePath = await AppApi.SaveStickerToFile(
imageUrl,
this.ugcFolderPath,
monthFolder,
fileName
);
if (status) {
if (filePath) {
console.log(`Sticker saved to file: ${monthFolder}\\${fileName}`);
}
};
// #endregion
// #region | Prints
$app.methods.cropPrintsChanged = function () {
if (!this.cropInstancePrints)
return;
this.$confirm(
$t('view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old'),
{
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: 'info',
showInput: false,
callback: (action) => {
if (action === 'confirm') {
AppApi.CropAllPrints(this.ugcFolderPath);
}
}
});
this.saveVRCXWindowOption();
}
API.$on('LOGIN', function () {
$app.printTable = [];
});
@@ -18284,6 +18308,11 @@ speechSynthesis.getVoices();
false
);
$app.data.cropInstancePrints = await configRepository.getBool(
'VRCX_cropInstancePrints',
false
);
$app.data.saveInstanceStickers = await configRepository.getBool(
'VRCX_saveInstanceStickers',
false
@@ -18325,13 +18354,29 @@ speechSynthesis.getVoices();
};
$app.data.printCache = [];
$app.data.printQueue = [];
$app.data.printQueueWorker = undefined;
$app.methods.trySavePrintToFile = async function (printId) {
$app.methods.queueSavePrintToFile = function (printId) {
if ($app.printCache.includes(printId)) return;
$app.printCache.push(printId);
if ($app.printCache.length > 100) {
$app.printCache.shift();
}
$app.printQueue.push(printId);
if (!$app.printQueueWorker) {
$app.printQueueWorker = workerTimers.setInterval(() => {
let printId = $app.printQueue.shift();
if (printId) {
$app.trySavePrintToFile(printId);
}
}, 2_500);
}
}
$app.methods.trySavePrintToFile = async function (printId) {
var args = await API.getPrint({ printId });
var imageUrl = args.json?.files?.image;
if (!imageUrl) {
@@ -18341,14 +18386,23 @@ speechSynthesis.getVoices();
var createdAt = this.getPrintLocalDate(args.json);
var monthFolder = createdAt.toISOString().slice(0, 7);
var fileName = this.getPrintFileName(args.json);
var status = await AppApi.SavePrintToFile(
var filePath = await AppApi.SavePrintToFile(
imageUrl,
this.ugcFolderPath,
monthFolder,
fileName
);
if (status) {
if (filePath) {
console.log(`Print saved to file: ${monthFolder}\\${fileName}`);
if (this.cropInstancePrints) {
await AppApi.CropPrintImage(filePath);
}
}
if ($app.printQueue.length == 0) {
workerTimers.clearInterval($app.printQueueWorker);
$app.printQueueWorker = undefined;
}
};

View File

@@ -286,7 +286,7 @@ export default class extends baseClass {
printId = pathArray[4];
}
if (printId && printId.length === 41) {
$app.trySavePrintToFile(printId);
$app.queueSavePrintToFile(printId);
}
} catch (err) {
console.error(err);

View File

@@ -507,7 +507,11 @@
"save_instance_prints_to_file": {
"header": "Save Instance Prints To File",
"header_tooltip": "Requires \"--enable-sdk-log-levels\" VRC launch option",
"description": "Save spawned prints to your VRChat Pictures folder"
"description": "Save spawned prints to your VRChat Pictures folder",
"crop": "Automatically crop saved prints to remove the white border",
"crop_convert_old": "Do you want to crop all prints that have already been saved?",
"crop_convert_old_confirm": "Yes",
"crop_convert_old_cancel": "No"
},
"save_instance_stickers_to_file": {
"header": "Save Instance Stickers To File",

View File

@@ -465,6 +465,11 @@ mixin settingsTab()
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
simple-switch(:label='$t("view.settings.advanced.advanced.save_instance_prints_to_file.description")' :value='saveInstancePrints' @change='saveVRCXWindowOption("VRCX_saveInstancePrints")' :long-label='true')
br
span.name(style="min-width:300px") {{ $t('view.settings.advanced.advanced.save_instance_prints_to_file.crop') }}
el-switch(v-model="cropInstancePrints" @change="cropPrintsChanged")
br
span.sub-header {{ $t('view.settings.advanced.advanced.save_instance_stickers_to_file.header') }}
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