mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-07 06:56:04 +02:00
Upload screenshot to gallery
This commit is contained in:
@@ -689,11 +689,8 @@ namespace VRCX
|
|||||||
public void GetScreenshotMetadata(string path)
|
public void GetScreenshotMetadata(string path)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileNameWithoutExtension(path);
|
var fileName = Path.GetFileNameWithoutExtension(path);
|
||||||
|
|
||||||
const string fileNamePrefix = "VRChat_";
|
|
||||||
var metadata = new JObject();
|
var metadata = new JObject();
|
||||||
|
if (File.Exists(path) && path.EndsWith(".png"))
|
||||||
if (File.Exists(path) && path.EndsWith(".png") && fileName.StartsWith(fileNamePrefix))
|
|
||||||
{
|
{
|
||||||
string metadataString = null;
|
string metadataString = null;
|
||||||
var readPNGFailed = false;
|
var readPNGFailed = false;
|
||||||
@@ -756,9 +753,14 @@ namespace VRCX
|
|||||||
metadata.Add("nextFilePath", files[index + 1]);
|
metadata.Add("nextFilePath", files[index + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metadata.Add("fileResolution", ScreenshotHelper.ReadPNGResolution(path));
|
||||||
|
var creationDate = File.GetCreationTime(path);
|
||||||
|
metadata.Add("creationDate", creationDate.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
metadata.Add("fileName", fileName);
|
metadata.Add("fileName", fileName);
|
||||||
metadata.Add("filePath", path);
|
metadata.Add("filePath", path);
|
||||||
metadata.Add("fileSize", $"{(new FileInfo(path).Length / 1024f / 1024f).ToString("0.00")} MB");
|
var fileSizeBytes = new FileInfo(path).Length;
|
||||||
|
metadata.Add("fileSizeBytes", fileSizeBytes.ToString());
|
||||||
|
metadata.Add("fileSize", $"{(fileSizeBytes / 1024f / 1024f).ToString("0.00")} MB");
|
||||||
ExecuteAppFunction("displayScreenshotMetadata", metadata.ToString(Formatting.Indented));
|
ExecuteAppFunction("displayScreenshotMetadata", metadata.ToString(Formatting.Indented));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -775,6 +777,16 @@ namespace VRCX
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetFileBase64(string path)
|
||||||
|
{
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
return Convert.ToBase64String(File.ReadAllBytes(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private struct XSOMessage
|
private struct XSOMessage
|
||||||
{
|
{
|
||||||
public int messageType { get; set; }
|
public int messageType { get; set; }
|
||||||
|
|||||||
+20
-1
@@ -66,6 +66,19 @@ namespace VRCX
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string ReadPNGResolution(string path)
|
||||||
|
{
|
||||||
|
if (!File.Exists(path) || !IsPNGFile(path)) return null;
|
||||||
|
|
||||||
|
var png = File.ReadAllBytes(path);
|
||||||
|
var existingpHYs = FindChunk(png, "IHDR");
|
||||||
|
if (existingpHYs == null) return null;
|
||||||
|
|
||||||
|
var text = existingpHYs.GetResolution();
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the specified file is a PNG file. We do this by checking if the first 8 bytes in the file path match the PNG signature.
|
/// Determines whether the specified file is a PNG file. We do this by checking if the first 8 bytes in the file path match the PNG signature.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -358,10 +371,16 @@ namespace VRCX
|
|||||||
public string GetText(string keyword)
|
public string GetText(string keyword)
|
||||||
{
|
{
|
||||||
var offset = keywordEncoding.GetByteCount(keyword) + 5;
|
var offset = keywordEncoding.GetByteCount(keyword) + 5;
|
||||||
// Read string from PNG chunk
|
|
||||||
return Encoding.UTF8.GetString(ChunkDataBytes.ToArray(), offset, ChunkDataBytes.Count - offset);
|
return Encoding.UTF8.GetString(ChunkDataBytes.ToArray(), offset, ChunkDataBytes.Count - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetResolution()
|
||||||
|
{
|
||||||
|
var x = BitConverter.ToInt32(ChunkDataBytes.Take(4).Reverse().ToArray(), 0);
|
||||||
|
var y = BitConverter.ToInt32(ChunkDataBytes.Skip(4).Take(4).Reverse().ToArray(), 0);
|
||||||
|
return $"{x}x{y}";
|
||||||
|
}
|
||||||
|
|
||||||
// Crc32 implementation from
|
// Crc32 implementation from
|
||||||
// https://web.archive.org/web/20150825201508/http://upokecenter.dreamhosters.com/articles/png-image-encoder-in-c/
|
// https://web.archive.org/web/20150825201508/http://upokecenter.dreamhosters.com/articles/png-image-encoder-in-c/
|
||||||
private static uint Crc32(byte[] stream, int offset, int length, uint crc)
|
private static uint Crc32(byte[] stream, int offset, int length, uint crc)
|
||||||
|
|||||||
+63
-7
@@ -20212,33 +20212,40 @@ speechSynthesis.getVoices();
|
|||||||
var json = JSON.parse(metadata);
|
var json = JSON.parse(metadata);
|
||||||
D.metadata = json;
|
D.metadata = json;
|
||||||
|
|
||||||
// VRChat_3840x2160_2022-02-02_03-21-39.771
|
|
||||||
// VRChat_2023-02-16_10-39-25.274_3840x2160
|
|
||||||
var regex = json.fileName.match(
|
var regex = json.fileName.match(
|
||||||
/VRChat_((\d{3,})x(\d{3,})_(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})\.(\d{1,})|(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})\.(\d{3})_(\d{3,})x(\d{3,}))/
|
/VRChat_((\d{3,})x(\d{3,})_(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})\.(\d{1,})|(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})\.(\d{3})_(\d{3,})x(\d{3,}))/
|
||||||
);
|
);
|
||||||
if (regex) {
|
if (regex) {
|
||||||
if (typeof regex[2] !== 'undefined') {
|
if (typeof regex[2] !== 'undefined' && regex[4].length === 4) {
|
||||||
// old format
|
// old format
|
||||||
|
// VRChat_3840x2160_2022-02-02_03-21-39.771
|
||||||
var date = `${regex[4]}-${regex[5]}-${regex[6]}`;
|
var date = `${regex[4]}-${regex[5]}-${regex[6]}`;
|
||||||
var time = `${regex[7]}:${regex[8]}:${regex[9]}`;
|
var time = `${regex[7]}:${regex[8]}:${regex[9]}`;
|
||||||
D.metadata.dateTime = Date.parse(`${date} ${time}`);
|
D.metadata.dateTime = Date.parse(`${date} ${time}`);
|
||||||
D.metadata.resolution = `${regex[2]}x${regex[3]}`;
|
// D.metadata.resolution = `${regex[2]}x${regex[3]}`;
|
||||||
} else if (typeof regex[11] !== 'undefined') {
|
} else if (
|
||||||
|
typeof regex[11] !== 'undefined' &&
|
||||||
|
regex[11].length === 4
|
||||||
|
) {
|
||||||
// new format
|
// new format
|
||||||
|
// VRChat_2023-02-16_10-39-25.274_3840x2160
|
||||||
var date = `${regex[11]}-${regex[12]}-${regex[13]}`;
|
var date = `${regex[11]}-${regex[12]}-${regex[13]}`;
|
||||||
var time = `${regex[14]}:${regex[15]}:${regex[16]}`;
|
var time = `${regex[14]}:${regex[15]}:${regex[16]}`;
|
||||||
D.metadata.dateTime = Date.parse(`${date} ${time}`);
|
D.metadata.dateTime = Date.parse(`${date} ${time}`);
|
||||||
D.metadata.resolution = `${regex[18]}x${regex[19]}`;
|
// D.metadata.resolution = `${regex[18]}x${regex[19]}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!D.metadata.dateTime) {
|
||||||
|
D.metadata.dateTime = Date.parse(json.creationDate);
|
||||||
|
}
|
||||||
|
|
||||||
this.showScreenshotMetadataDialog();
|
this.showScreenshotMetadataDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.data.screenshotMetadataDialog = {
|
$app.data.screenshotMetadataDialog = {
|
||||||
visible: false,
|
visible: false,
|
||||||
metadata: {}
|
metadata: {},
|
||||||
|
isUploading: false
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.methods.showScreenshotMetadataDialog = function () {
|
$app.methods.showScreenshotMetadataDialog = function () {
|
||||||
@@ -20270,6 +20277,40 @@ speechSynthesis.getVoices();
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$app.methods.uploadScreenshotToGallery = function () {
|
||||||
|
var D = this.screenshotMetadataDialog;
|
||||||
|
if (D.metadata.fileSizeBytes > 10000000) {
|
||||||
|
$app.$message({
|
||||||
|
message: 'File size too large',
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
D.isUploading = true;
|
||||||
|
AppApi.GetFileBase64(D.metadata.filePath)
|
||||||
|
.then((base64Body) => {
|
||||||
|
API.uploadGalleryImage(base64Body)
|
||||||
|
.then((args) => {
|
||||||
|
$app.$message({
|
||||||
|
message: 'Gallery image uploaded',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
return args;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
D.isUploading = false;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
$app.$message({
|
||||||
|
message: 'Failed to upload gallery image',
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
console.error(err);
|
||||||
|
D.isUploading = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// YouTube API
|
// YouTube API
|
||||||
|
|
||||||
$app.data.youTubeApiKey = '';
|
$app.data.youTubeApiKey = '';
|
||||||
@@ -21475,6 +21516,9 @@ speechSynthesis.getVoices();
|
|||||||
}
|
}
|
||||||
this.photonLastEvent7List = Date.parse(data.dt);
|
this.photonLastEvent7List = Date.parse(data.dt);
|
||||||
break;
|
break;
|
||||||
|
case 'VrcxMessage':
|
||||||
|
this.eventVrcxMessage(data);
|
||||||
|
break;
|
||||||
case 'Ping':
|
case 'Ping':
|
||||||
if (!this.photonLoggingEnabled) {
|
if (!this.photonLoggingEnabled) {
|
||||||
this.photonLoggingEnabled = true;
|
this.photonLoggingEnabled = true;
|
||||||
@@ -21512,6 +21556,18 @@ speechSynthesis.getVoices();
|
|||||||
$app.data.photonEventCount = 0;
|
$app.data.photonEventCount = 0;
|
||||||
$app.data.photonEventIcon = false;
|
$app.data.photonEventIcon = false;
|
||||||
|
|
||||||
|
$app.methods.eventVrcxMessage = function (data) {
|
||||||
|
console.log(data);
|
||||||
|
var entry = {
|
||||||
|
created_at: new Date().toJSON(),
|
||||||
|
type: 'Event',
|
||||||
|
data: data.Data
|
||||||
|
};
|
||||||
|
database.addGamelogEventToDatabase(entry);
|
||||||
|
this.queueGameLogNoty(entry);
|
||||||
|
this.addGameLog(entry);
|
||||||
|
};
|
||||||
|
|
||||||
$app.methods.photonEventPulse = function () {
|
$app.methods.photonEventPulse = function () {
|
||||||
this.photonEventCount++;
|
this.photonEventCount++;
|
||||||
this.photonEventIcon = true;
|
this.photonEventIcon = true;
|
||||||
|
|||||||
+4
-2
@@ -3800,9 +3800,11 @@ html
|
|||||||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="screenshotMetadataDialog" :visible.sync="screenshotMetadataDialog.visible" :title="$t('dialog.screenshot_metadata.header')" width="1050px")
|
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="screenshotMetadataDialog" :visible.sync="screenshotMetadataDialog.visible" :title="$t('dialog.screenshot_metadata.header')" width="1050px")
|
||||||
div(v-if="screenshotMetadataDialog.visible")
|
div(v-if="screenshotMetadataDialog.visible")
|
||||||
el-button(size="small" icon="el-icon-folder-opened" @click="AppApi.OpenScreenshotFileDialog()") {{ $t('dialog.screenshot_metadata.browse') }}
|
el-button(size="small" icon="el-icon-folder-opened" @click="AppApi.OpenScreenshotFileDialog()") {{ $t('dialog.screenshot_metadata.browse') }}
|
||||||
span(v-if="!screenshotMetadataDialog.metadata.resolution" v-text="screenshotMetadataDialog.metadata.fileName" style="margin-left:5px")
|
el-button(v-if="API.currentUser.$isVRCPlus && screenshotMetadataDialog.metadata.filePath" size="small" icon="el-icon-upload2" @click="uploadScreenshotToGallery") {{ $t('dialog.screenshot_metadata.upload') }}
|
||||||
|
span(v-text="screenshotMetadataDialog.metadata.fileName" style="margin-left:5px")
|
||||||
|
br
|
||||||
span(v-if="screenshotMetadataDialog.metadata.dateTime" style="margin-left:5px") {{ screenshotMetadataDialog.metadata.dateTime | formatDate('long') }}
|
span(v-if="screenshotMetadataDialog.metadata.dateTime" style="margin-left:5px") {{ screenshotMetadataDialog.metadata.dateTime | formatDate('long') }}
|
||||||
span(v-if="screenshotMetadataDialog.metadata.resolution" v-text="screenshotMetadataDialog.metadata.resolution" style="margin-left:5px")
|
span(v-if="screenshotMetadataDialog.metadata.fileResolution" v-text="screenshotMetadataDialog.metadata.fileResolution" style="margin-left:5px")
|
||||||
el-tag(v-if="screenshotMetadataDialog.metadata.fileSize" type="info" effect="plain" size="mini" style="margin-left:5px" v-text="screenshotMetadataDialog.metadata.fileSize")
|
el-tag(v-if="screenshotMetadataDialog.metadata.fileSize" type="info" effect="plain" size="mini" style="margin-left:5px" v-text="screenshotMetadataDialog.metadata.fileSize")
|
||||||
br
|
br
|
||||||
location(v-if="screenshotMetadataDialog.metadata.world" :location="screenshotMetadataDialog.metadata.world.instanceId" :hint="screenshotMetadataDialog.metadata.world.name")
|
location(v-if="screenshotMetadataDialog.metadata.world" :location="screenshotMetadataDialog.metadata.world.instanceId" :hint="screenshotMetadataDialog.metadata.world.name")
|
||||||
|
|||||||
@@ -1055,7 +1055,8 @@
|
|||||||
},
|
},
|
||||||
"screenshot_metadata": {
|
"screenshot_metadata": {
|
||||||
"header": "Screenshot Metadata",
|
"header": "Screenshot Metadata",
|
||||||
"browse": "Browse"
|
"browse": "Browse",
|
||||||
|
"upload": "Upload"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prompt": {
|
"prompt": {
|
||||||
|
|||||||
Reference in New Issue
Block a user