mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 14:53:50 +02:00
Add support for prints
This commit is contained in:
@@ -4,6 +4,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -172,6 +173,18 @@ namespace VRCX
|
|||||||
// If not JSON metadata, return early so we're not throwing/catching pointless exceptions
|
// If not JSON metadata, return early so we're not throwing/catching pointless exceptions
|
||||||
if (!metadataString.StartsWith("{"))
|
if (!metadataString.StartsWith("{"))
|
||||||
{
|
{
|
||||||
|
// parse VRC prints
|
||||||
|
var xmlIndex = metadataString.IndexOf("<x:xmpmeta");
|
||||||
|
if (xmlIndex != -1)
|
||||||
|
{
|
||||||
|
var xmlString = metadataString.Substring(xmlIndex);
|
||||||
|
// everything after index
|
||||||
|
var result = ParseVRCPrint(xmlString.Substring(xmlIndex - 7));
|
||||||
|
result.SourceFile = path;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
logger.ConditionalDebug("Screenshot file '{0}' has unknown non-JSON metadata:\n{1}\n", path, metadataString);
|
logger.ConditionalDebug("Screenshot file '{0}' has unknown non-JSON metadata:\n{1}\n", path, metadataString);
|
||||||
return ScreenshotMetadata.JustError(path, "File has unknown non-JSON metadata.");
|
return ScreenshotMetadata.JustError(path, "File has unknown non-JSON metadata.");
|
||||||
}
|
}
|
||||||
@@ -193,6 +206,44 @@ namespace VRCX
|
|||||||
return ScreenshotMetadata.JustError(path, "Failed to parse screenshot metadata JSON. Check logs.");
|
return ScreenshotMetadata.JustError(path, "Failed to parse screenshot metadata JSON. Check logs.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ScreenshotMetadata ParseVRCPrint(string xmlString)
|
||||||
|
{
|
||||||
|
var doc = new XmlDocument();
|
||||||
|
doc.LoadXml(xmlString);
|
||||||
|
var root = doc.DocumentElement;
|
||||||
|
var nsManager = new XmlNamespaceManager(doc.NameTable);
|
||||||
|
nsManager.AddNamespace("x", "adobe:ns:meta/");
|
||||||
|
nsManager.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
|
||||||
|
nsManager.AddNamespace("xmp", "http://ns.adobe.com/xap/1.0/");
|
||||||
|
nsManager.AddNamespace("tiff", "http://ns.adobe.com/tiff/1.0/");
|
||||||
|
nsManager.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
|
||||||
|
nsManager.AddNamespace("vrc", "http://ns.vrchat.com/vrc/1.0/");
|
||||||
|
var creatorTool = root.SelectSingleNode("//xmp:CreatorTool", nsManager)?.InnerText;
|
||||||
|
var authorId = root.SelectSingleNode("//xmp:Author", nsManager)?.InnerText;
|
||||||
|
var dateTime = root.SelectSingleNode("//tiff:DateTime", nsManager)?.InnerText;
|
||||||
|
var note = root.SelectSingleNode("//dc:title/rdf:Alt/rdf:li", nsManager)?.InnerText;
|
||||||
|
var worldId = root.SelectSingleNode("//vrc:World", nsManager)?.InnerText;
|
||||||
|
|
||||||
|
return new ScreenshotMetadata
|
||||||
|
{
|
||||||
|
Application = creatorTool,
|
||||||
|
Version = 1,
|
||||||
|
Author = new ScreenshotMetadata.AuthorDetail
|
||||||
|
{
|
||||||
|
Id = authorId,
|
||||||
|
DisplayName = null
|
||||||
|
},
|
||||||
|
World = new ScreenshotMetadata.WorldDetail
|
||||||
|
{
|
||||||
|
Id = worldId,
|
||||||
|
InstanceId = worldId,
|
||||||
|
Name = null
|
||||||
|
},
|
||||||
|
Timestamp = DateTime.TryParse(dateTime, out var dt) ? dt : null,
|
||||||
|
Note = note
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes a text description into a PNG file at the specified path.
|
/// Writes a text description into a PNG file at the specified path.
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ namespace VRCX
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public Vector3? Pos { get; set; }
|
public Vector3? Pos { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public DateTime? Timestamp { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string? Note { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Any error that occurred while parsing the file. This being true implies nothing else is set.
|
/// Any error that occurred while parsing the file. This being true implies nothing else is set.
|
||||||
|
|||||||
@@ -256,7 +256,6 @@ namespace VRCX
|
|||||||
if (options.TryGetValue("postData", out object postDataObject))
|
if (options.TryGetValue("postData", out object postDataObject))
|
||||||
{
|
{
|
||||||
var jsonPostData = (JObject)JsonConvert.DeserializeObject((string)postDataObject);
|
var jsonPostData = (JObject)JsonConvert.DeserializeObject((string)postDataObject);
|
||||||
Dictionary<string, string> postData = new Dictionary<string, string>();
|
|
||||||
string formDataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n";
|
string formDataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n";
|
||||||
if (jsonPostData != null)
|
if (jsonPostData != null)
|
||||||
{
|
{
|
||||||
@@ -294,6 +293,65 @@ namespace VRCX
|
|||||||
await requestStream.WriteAsync(endBytes, 0, endBytes.Length);
|
await requestStream.WriteAsync(endBytes, 0, endBytes.Length);
|
||||||
requestStream.Close();
|
requestStream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task PrintImageUpload(HttpWebRequest request, IDictionary<string, object> options)
|
||||||
|
{
|
||||||
|
if (ProxySet)
|
||||||
|
request.Proxy = Proxy;
|
||||||
|
|
||||||
|
request.AutomaticDecompression = DecompressionMethods.All;
|
||||||
|
request.Method = "POST";
|
||||||
|
var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
|
||||||
|
request.ContentType = "multipart/form-data; boundary=" + boundary;
|
||||||
|
var requestStream = request.GetRequestStream();
|
||||||
|
// var requestStream = new MemoryStream();
|
||||||
|
var imageData = options["imageData"] as string;
|
||||||
|
var fileToUpload = Convert.FromBase64String(imageData);
|
||||||
|
const string fileFormKey = "image";
|
||||||
|
const string fileName = "image";
|
||||||
|
const string fileMimeType = "image/png";
|
||||||
|
var fileSize = fileToUpload.Length;
|
||||||
|
const string headerTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\nContent-Length: {4}\r\n";
|
||||||
|
var header = string.Format(headerTemplate, boundary, fileFormKey, fileName, fileMimeType, fileSize);
|
||||||
|
var headerBytes = Encoding.UTF8.GetBytes(header);
|
||||||
|
await requestStream.WriteAsync(headerBytes);
|
||||||
|
using (var fileStream = new MemoryStream(fileToUpload))
|
||||||
|
{
|
||||||
|
var buffer = new byte[1024];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
|
||||||
|
{
|
||||||
|
await requestStream.WriteAsync(buffer.AsMemory(0, bytesRead));
|
||||||
|
}
|
||||||
|
fileStream.Close();
|
||||||
|
}
|
||||||
|
var newlineBytes = Encoding.UTF8.GetBytes("\r\n");
|
||||||
|
await requestStream.WriteAsync(newlineBytes);
|
||||||
|
const string textContentType = "text/plain; charset=utf-8";
|
||||||
|
const string formDataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\nContent-Type: {2}\r\nContent-Length: {3}\r\n{4}\r\n";
|
||||||
|
if (options.TryGetValue("postData", out var postDataObject))
|
||||||
|
{
|
||||||
|
var jsonPostData = JsonConvert.DeserializeObject<Dictionary<string, string>>(postDataObject.ToString());
|
||||||
|
if (jsonPostData != null)
|
||||||
|
{
|
||||||
|
foreach (var (key, value) in jsonPostData)
|
||||||
|
{
|
||||||
|
var section = string.Format(formDataTemplate, boundary, key, textContentType, value.Length, value);
|
||||||
|
var sectionBytes = Encoding.UTF8.GetBytes(section);
|
||||||
|
await requestStream.WriteAsync(sectionBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var endBytes = Encoding.UTF8.GetBytes("--" + boundary + "--");
|
||||||
|
await requestStream.WriteAsync(endBytes);
|
||||||
|
// test file
|
||||||
|
// var newFileStream = new FileStream(@"D:\WindowsFiles\Desktop\test", FileMode.Create, FileAccess.Write);
|
||||||
|
// requestStream.WriteTo(newFileStream);
|
||||||
|
// newFileStream.Close();
|
||||||
|
|
||||||
|
requestStream.Close();
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
#pragma warning disable CS4014
|
#pragma warning disable CS4014
|
||||||
|
|
||||||
@@ -364,6 +422,11 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
await LegacyImageUpload(request, options);
|
await LegacyImageUpload(request, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.TryGetValue("uploadImagePrint", out _))
|
||||||
|
{
|
||||||
|
await PrintImageUpload(request, options);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
122
html/src/app.js
122
html/src/app.js
@@ -7573,6 +7573,7 @@ speechSynthesis.getVoices();
|
|||||||
},
|
},
|
||||||
layout: 'table'
|
layout: 'table'
|
||||||
};
|
};
|
||||||
|
$app.data.printTable = [];
|
||||||
$app.data.stickerTable = [];
|
$app.data.stickerTable = [];
|
||||||
$app.data.emojiTable = [];
|
$app.data.emojiTable = [];
|
||||||
$app.data.VRCPlusIconsTable = [];
|
$app.data.VRCPlusIconsTable = [];
|
||||||
@@ -16068,8 +16069,11 @@ speechSynthesis.getVoices();
|
|||||||
// D.metadata.resolution = `${regex[18]}x${regex[19]}`;
|
// D.metadata.resolution = `${regex[18]}x${regex[19]}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (metadata.timestamp) {
|
||||||
|
D.metadata.dateTime = Date.parse(metadata.timestamp);
|
||||||
|
}
|
||||||
if (!D.metadata.dateTime) {
|
if (!D.metadata.dateTime) {
|
||||||
D.metadata.dateTime = Date.parse(json.creationDate);
|
D.metadata.dateTime = Date.parse(metadata.creationDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fullscreenImageDialog?.visible) {
|
if (this.fullscreenImageDialog?.visible) {
|
||||||
@@ -17120,6 +17124,7 @@ speechSynthesis.getVoices();
|
|||||||
$app.data.galleryDialogIconsLoading = false;
|
$app.data.galleryDialogIconsLoading = false;
|
||||||
$app.data.galleryDialogEmojisLoading = false;
|
$app.data.galleryDialogEmojisLoading = false;
|
||||||
$app.data.galleryDialogStickersLoading = false;
|
$app.data.galleryDialogStickersLoading = false;
|
||||||
|
$app.data.galleryDialogPrintsLoading = false;
|
||||||
|
|
||||||
API.$on('LOGIN', function () {
|
API.$on('LOGIN', function () {
|
||||||
$app.galleryTable = [];
|
$app.galleryTable = [];
|
||||||
@@ -17132,6 +17137,7 @@ speechSynthesis.getVoices();
|
|||||||
this.refreshVRCPlusIconsTable();
|
this.refreshVRCPlusIconsTable();
|
||||||
this.refreshEmojiTable();
|
this.refreshEmojiTable();
|
||||||
this.refreshStickerTable();
|
this.refreshStickerTable();
|
||||||
|
this.refreshPrintTable();
|
||||||
workerTimers.setTimeout(() => this.setGalleryTab(pageNum), 100);
|
workerTimers.setTimeout(() => this.setGalleryTab(pageNum), 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -17395,6 +17401,120 @@ speechSynthesis.getVoices();
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
// #region | Prints
|
||||||
|
API.$on('LOGIN', function () {
|
||||||
|
$app.printTable = [];
|
||||||
|
});
|
||||||
|
|
||||||
|
$app.methods.refreshPrintTable = function () {
|
||||||
|
this.galleryDialogPrintsLoading = true;
|
||||||
|
var params = {
|
||||||
|
n: 100,
|
||||||
|
tag: 'print'
|
||||||
|
};
|
||||||
|
API.getFileList(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
API.$on('FILES:LIST', function (args) {
|
||||||
|
if (args.params.tag === 'print') {
|
||||||
|
$app.printTable = args.json.reverse();
|
||||||
|
$app.galleryDialogPrintsLoading = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$app.methods.deletePrint = function (fileId) {
|
||||||
|
API.deleteFile(fileId).then((args) => {
|
||||||
|
API.$emit('PRINT:DELETE', args);
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
API.$on('PRINT:DELETE', function (args) {
|
||||||
|
var array = $app.printTable;
|
||||||
|
var { length } = array;
|
||||||
|
for (var i = 0; i < length; ++i) {
|
||||||
|
if (args.fileId === array[i].id) {
|
||||||
|
array.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$app.methods.onFileChangePrint = function (e) {
|
||||||
|
var clearFile = function () {
|
||||||
|
if (document.querySelector('#PrintUploadButton')) {
|
||||||
|
document.querySelector('#PrintUploadButton').value = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var files = e.target.files || e.dataTransfer.files;
|
||||||
|
if (!files.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (files[0].size >= 100000000) {
|
||||||
|
// 100MB
|
||||||
|
$app.$message({
|
||||||
|
message: 'File size too large',
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
clearFile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!files[0].type.match(/image.*/)) {
|
||||||
|
$app.$message({
|
||||||
|
message: "File isn't an image",
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
clearFile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var r = new FileReader();
|
||||||
|
r.onload = function () {
|
||||||
|
var date = new Date();
|
||||||
|
var timestamp = date.toISOString().slice(0, 19);
|
||||||
|
var params = {
|
||||||
|
note: 'test print',
|
||||||
|
worldId: 'wrld_10e5e467-fc65-42ed-8957-f02cace1398c',
|
||||||
|
timestamp
|
||||||
|
};
|
||||||
|
var base64Body = btoa(r.result);
|
||||||
|
API.uploadPrint(base64Body, params).then((args) => {
|
||||||
|
$app.$message({
|
||||||
|
message: 'Print uploaded',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
r.readAsBinaryString(files[0]);
|
||||||
|
clearFile();
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.displayPrintUpload = function () {
|
||||||
|
document.getElementById('PrintUploadButton').click();
|
||||||
|
};
|
||||||
|
|
||||||
|
API.uploadPrint = function (imageData, params) {
|
||||||
|
return this.call('prints', {
|
||||||
|
uploadImagePrint: true,
|
||||||
|
postData: JSON.stringify(params),
|
||||||
|
imageData
|
||||||
|
}).then((json) => {
|
||||||
|
var args = {
|
||||||
|
json,
|
||||||
|
params
|
||||||
|
};
|
||||||
|
this.$emit('PRINT:ADD', args);
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
API.$on('PRINT:ADD', function (args) {
|
||||||
|
if (Object.keys($app.printTable).length !== 0) {
|
||||||
|
$app.printTable.unshift(args.json);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
// #region | Emoji
|
// #region | Emoji
|
||||||
|
|
||||||
|
|||||||
@@ -559,7 +559,11 @@ export default class extends baseClass {
|
|||||||
props: {
|
props: {
|
||||||
userid: String,
|
userid: String,
|
||||||
location: String,
|
location: String,
|
||||||
key: Number
|
key: Number,
|
||||||
|
hint: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -569,7 +573,9 @@ export default class extends baseClass {
|
|||||||
methods: {
|
methods: {
|
||||||
async parse() {
|
async parse() {
|
||||||
this.username = this.userid;
|
this.username = this.userid;
|
||||||
if (this.userid) {
|
if (this.hint) {
|
||||||
|
this.username = this.hint;
|
||||||
|
} else if (this.userid) {
|
||||||
var args = await API.getCachedUser({
|
var args = await API.getCachedUser({
|
||||||
userId: this.userid
|
userId: this.userid
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -525,6 +525,10 @@ export default class extends baseClass {
|
|||||||
if ($app.galleryDialogVisible) {
|
if ($app.galleryDialogVisible) {
|
||||||
$app.refreshEmojiTable();
|
$app.refreshEmojiTable();
|
||||||
}
|
}
|
||||||
|
} else if (contentType === 'print') {
|
||||||
|
if ($app.galleryDialogVisible) {
|
||||||
|
$app.refreshPrintTable();
|
||||||
|
}
|
||||||
} else if (contentType === 'avatar') {
|
} else if (contentType === 'avatar') {
|
||||||
// hmm, utilizing this might be too spamy and cause UI to move around
|
// hmm, utilizing this might be too spamy and cause UI to move around
|
||||||
} else if (contentType === 'world') {
|
} else if (contentType === 'world') {
|
||||||
|
|||||||
@@ -1266,6 +1266,7 @@
|
|||||||
"icons": "Icons",
|
"icons": "Icons",
|
||||||
"emojis": "Emojis",
|
"emojis": "Emojis",
|
||||||
"stickers": "Stickers",
|
"stickers": "Stickers",
|
||||||
|
"prints": "Prints",
|
||||||
"refresh": "Refresh",
|
"refresh": "Refresh",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ mixin currentUser()
|
|||||||
.vrcplus-icon(v-if="image.versions[image.versions.length - 1].file.url" @click="setProfilePicOverride(image.id)" :class="{ 'current-vrcplus-icon': compareCurrentProfilePic(image.id) }")
|
.vrcplus-icon(v-if="image.versions[image.versions.length - 1].file.url" @click="setProfilePicOverride(image.id)" :class="{ 'current-vrcplus-icon': compareCurrentProfilePic(image.id) }")
|
||||||
img.avatar(v-lazy="image.versions[image.versions.length - 1].file.url")
|
img.avatar(v-lazy="image.versions[image.versions.length - 1].file.url")
|
||||||
div(style="float:right;margin-top:5px")
|
div(style="float:right;margin-top:5px")
|
||||||
el-button(type="default" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-download" circle)
|
el-button(type="default" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-picture-outline" circle)
|
||||||
el-button(type="default" @click="deleteGalleryImage(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
el-button(type="default" @click="deleteGalleryImage(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||||||
el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogIconsLoading")
|
el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogIconsLoading")
|
||||||
span(slot="label") {{ $t('dialog.gallery_icons.icons') }}
|
span(slot="label") {{ $t('dialog.gallery_icons.icons') }}
|
||||||
@@ -93,7 +93,7 @@ mixin currentUser()
|
|||||||
.vrcplus-icon(v-if="image.versions[image.versions.length - 1].file.url" @click="setVRCPlusIcon(image.id)" :class="{ 'current-vrcplus-icon': compareCurrentVRCPlusIcon(image.id) }")
|
.vrcplus-icon(v-if="image.versions[image.versions.length - 1].file.url" @click="setVRCPlusIcon(image.id)" :class="{ 'current-vrcplus-icon': compareCurrentVRCPlusIcon(image.id) }")
|
||||||
img.avatar(v-lazy="image.versions[image.versions.length - 1].file.url")
|
img.avatar(v-lazy="image.versions[image.versions.length - 1].file.url")
|
||||||
div(style="float:right;margin-top:5px")
|
div(style="float:right;margin-top:5px")
|
||||||
el-button(type="default" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-download" circle)
|
el-button(type="default" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-picture-outline" circle)
|
||||||
el-button(type="default" @click="deleteVRCPlusIcon(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
el-button(type="default" @click="deleteVRCPlusIcon(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||||||
el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogEmojisLoading")
|
el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogEmojisLoading")
|
||||||
span(slot="label") {{ $t('dialog.gallery_icons.emojis') }}
|
span(slot="label") {{ $t('dialog.gallery_icons.emojis') }}
|
||||||
@@ -134,7 +134,7 @@ mixin currentUser()
|
|||||||
span(v-if="image.frames" style="margin-right:5px") {{ image.frames }}frames
|
span(v-if="image.frames" style="margin-right:5px") {{ image.frames }}frames
|
||||||
br
|
br
|
||||||
div(style="float:right;margin-top:5px")
|
div(style="float:right;margin-top:5px")
|
||||||
el-button(type="default" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-download" circle)
|
el-button(type="default" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-picture-outline" circle)
|
||||||
el-button(type="default" @click="deleteEmoji(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
el-button(type="default" @click="deleteEmoji(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||||||
el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogStickersLoading")
|
el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogStickersLoading")
|
||||||
span(slot="label") {{ $t('dialog.gallery_icons.stickers') }}
|
span(slot="label") {{ $t('dialog.gallery_icons.stickers') }}
|
||||||
@@ -148,5 +148,19 @@ mixin currentUser()
|
|||||||
.vrcplus-icon(v-if="image.versions[image.versions.length - 1].file.url" style="overflow:hidden" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)")
|
.vrcplus-icon(v-if="image.versions[image.versions.length - 1].file.url" style="overflow:hidden" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)")
|
||||||
img.avatar(v-lazy="image.versions[image.versions.length - 1].file.url")
|
img.avatar(v-lazy="image.versions[image.versions.length - 1].file.url")
|
||||||
div(style="float:right;margin-top:5px")
|
div(style="float:right;margin-top:5px")
|
||||||
el-button(type="default" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-download" circle)
|
el-button(type="default" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-picture-outline" circle)
|
||||||
el-button(type="default" @click="deleteSticker(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
el-button(type="default" @click="deleteSticker(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||||||
|
el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogPrintsLoading")
|
||||||
|
span(slot="label") {{ $t('dialog.gallery_icons.prints') }}
|
||||||
|
span(style="color:#909399;font-size:12px;margin-left:5px") {{ printTable.length }}/64
|
||||||
|
input(type="file" accept="image/png,image/jpg,image/jpeg,image/webp,image/bmp,image/gif" @change="onFileChangePrint" id="PrintUploadButton" style="display:none")
|
||||||
|
el-button-group
|
||||||
|
el-button(type="default" size="small" @click="refreshPrintTable" icon="el-icon-refresh") {{ $t('dialog.gallery_icons.refresh') }}
|
||||||
|
//- el-button(type="default" size="small" @click="displayPrintUpload" icon="el-icon-upload2" :disabled="!API.currentUser.$isVRCPlus") {{ $t('dialog.gallery_icons.upload') }}
|
||||||
|
br
|
||||||
|
.x-friend-item(v-if="image.versions && image.versions.length > 0" v-for="image in printTable" :key="image.id" style="display:inline-block;margin-top:10px;width:unset;cursor:default")
|
||||||
|
.vrcplus-icon(v-if="image.versions[image.versions.length - 1].file.url" style="overflow:hidden" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)")
|
||||||
|
img.avatar(v-lazy="image.versions[image.versions.length - 1].file.url")
|
||||||
|
div(style="float:right;margin-top:5px")
|
||||||
|
el-button(type="default" @click="showFullscreenImageDialog(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-picture-outline" circle)
|
||||||
|
el-button(type="default" @click="deletePrint(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||||||
|
|||||||
@@ -23,13 +23,16 @@ mixin screenshotMetadata()
|
|||||||
br
|
br
|
||||||
span(v-text="screenshotMetadataDialog.metadata.fileName")
|
span(v-text="screenshotMetadataDialog.metadata.fileName")
|
||||||
br
|
br
|
||||||
|
template(v-if="screenshotMetadataDialog.metadata.note")
|
||||||
|
span(v-text="screenshotMetadataDialog.metadata.note")
|
||||||
|
br
|
||||||
span(v-if="screenshotMetadataDialog.metadata.dateTime" style="margin-right:5px") {{ screenshotMetadataDialog.metadata.dateTime | formatDate('long') }}
|
span(v-if="screenshotMetadataDialog.metadata.dateTime" style="margin-right:5px") {{ screenshotMetadataDialog.metadata.dateTime | formatDate('long') }}
|
||||||
span(v-if="screenshotMetadataDialog.metadata.fileResolution" v-text="screenshotMetadataDialog.metadata.fileResolution" style="margin-right:5px")
|
span(v-if="screenshotMetadataDialog.metadata.fileResolution" v-text="screenshotMetadataDialog.metadata.fileResolution" style="margin-right:5px")
|
||||||
el-tag(v-if="screenshotMetadataDialog.metadata.fileSize" type="info" effect="plain" size="mini" v-text="screenshotMetadataDialog.metadata.fileSize")
|
el-tag(v-if="screenshotMetadataDialog.metadata.fileSize" type="info" effect="plain" size="mini" 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")
|
||||||
br
|
br
|
||||||
span.x-link(v-if="screenshotMetadataDialog.metadata.author" v-text="screenshotMetadataDialog.metadata.author.displayName" @click="showUserDialog(screenshotMetadataDialog.metadata.author.id)" style="color:#909399;font-family:monospace")
|
display-name(v-if="screenshotMetadataDialog.metadata.author" :userid="screenshotMetadataDialog.metadata.author.id" :hind="screenshotMetadataDialog.metadata.author.displayName" style="color:#909399;font-family:monospace")
|
||||||
br
|
br
|
||||||
el-carousel(ref="screenshotMetadataCarousel" :interval="0" initial-index="1" indicator-position="none" arrow="always" height="600px" style="margin-top:10px" @change="screenshotMetadataCarouselChange")
|
el-carousel(ref="screenshotMetadataCarousel" :interval="0" initial-index="1" indicator-position="none" arrow="always" height="600px" style="margin-top:10px" @change="screenshotMetadataCarouselChange")
|
||||||
el-carousel-item
|
el-carousel-item
|
||||||
|
|||||||
Reference in New Issue
Block a user