From 6aea44461f8d6e4f96e60de1b80d9a26ce372a2f Mon Sep 17 00:00:00 2001 From: Natsumi Date: Sat, 17 Apr 2021 22:27:42 +1200 Subject: [PATCH] Display and set previous images for avatars/worlds --- html/src/app.dark.scss | 2 +- html/src/app.js | 183 ++++++++++++++++++++++++++++++++--------- html/src/app.scss | 9 +- html/src/index.pug | 32 +++++-- 4 files changed, 176 insertions(+), 50 deletions(-) diff --git a/html/src/app.dark.scss b/html/src/app.dark.scss index 40848b44..d74b5260 100644 --- a/html/src/app.dark.scss +++ b/html/src/app.dark.scss @@ -309,7 +309,7 @@ button { } .x-friend-item:hover, -.x-change-avatar-item:hover { +.x-change-image-item:hover { background: #3e3e3e; } diff --git a/html/src/app.js b/html/src/app.js index 138f1cc5..7e907126 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -8133,6 +8133,8 @@ speechSynthesis.getVoices(); type: 'error' }); } + } else if (command === 'Previous Images') { + this.displayPreviousImages('User'); } else { this.$confirm(`Continue? ${command}`, 'Confirm', { confirmButtonText: 'Confirm', @@ -8413,6 +8415,12 @@ speechSynthesis.getVoices(); case 'Rename': this.promptRenameWorld(D); break; + case 'Change Image': + this.displayPreviousImages('World', 'Change'); + break; + case 'Previous Images': + this.displayPreviousImages('World', 'Display'); + break; case 'Change Description': this.promptChangeWorldDescription(D); break; @@ -8595,7 +8603,10 @@ speechSynthesis.getVoices(); document.getElementById('AvatarImageUploadButton').click(); break; case 'Change Image': - this.displayAvatarImages(); + this.displayPreviousImages('Avatar', 'Change'); + break; + case 'Previous Images': + this.displayPreviousImages('Avatar', 'Display'); break; case 'Change Description': this.promptChangeAvatarDescription(D); @@ -10533,17 +10544,44 @@ speechSynthesis.getVoices(); } }); - // Set avatar image + API.setWorldImage = function (params) { + return this.call(`worlds/${params.id}`, { + method: 'PUT', + params + }).then((json) => { + var args = { + json, + params + }; + this.$emit('WORLDIMAGE:SET', args); + this.$emit('WORLD', args); + return args; + }); + }; - $app.methods.displayAvatarImages = function () { - this.changeAvatarImageTableFileId = ''; - this.changeAvatarImageTable = ''; - if (this.avatarDialog.visible) { - var { imageUrl } = this.avatarDialog.ref; - } else if (this.userDialog.visible) { - var imageUrl = this.userDialog.ref.currentAvatarImageUrl; + API.$on('WORLDIMAGE:SET', function (args) { + $app.worldDialog.loading = false; + if (args.json.imageUrl === args.params.imageUrl) { + $app.$message({ + message: 'World image changed', + type: 'success' + }); } else { - return; + this.$throw(0, 'World image change failed'); + } + }); + + // Set avatar/world image + + $app.methods.displayPreviousImages = function (type, command) { + this.previousImagesTableFileId = ''; + this.previousImagesTable = ''; + if (type === 'Avatar') { + var { imageUrl } = this.avatarDialog.ref; + } else if (type === 'World') { + var { imageUrl } = this.worldDialog.ref; + } else if (type === 'User') { + var imageUrl = this.userDialog.ref.currentAvatarImageUrl; } var fileId = extractFileId(imageUrl); if (!fileId) { @@ -10552,21 +10590,74 @@ speechSynthesis.getVoices(); var params = { fileId }; - this.changeAvatarImageDialogVisible = true; - this.$nextTick(() => adjustDialogZ(this.$refs.changeAvatarImageDialog.$el)); - API.getAvatarImages(params).then((args) => { - this.changeAvatarImageTableFileId = args.json.id; - var images = args.json.versions; - var imageArray = []; - images.forEach((image) => { - if (image.file) { - imageArray.push(image.file.url); - } + if (type === 'Avatar') { + if (command === 'Display') { + this.previousImagesDialogVisible = true; + this.$nextTick(() => adjustDialogZ(this.$refs.previousImagesDialog.$el)); + } else if (command === 'Change') { + this.changeAvatarImageDialogVisible = true; + this.$nextTick(() => adjustDialogZ(this.$refs.changeAvatarImageDialog.$el)); + } + API.getAvatarImages(params).then((args) => { + this.previousImagesTableFileId = args.json.id; + var images = args.json.versions; + var imageArray = []; + images.forEach((image) => { + if (image.file) { + imageArray.push(image.file.url); + } + }); + this.previousImagesTable = images; }); - this.changeAvatarImageTable = images; - }); + } else if (type === 'World') { + if (command === 'Display') { + this.previousImagesDialogVisible = true; + this.$nextTick(() => adjustDialogZ(this.$refs.previousImagesDialog.$el)); + } else if (command === 'Change') { + this.changeWorldImageDialogVisible = true; + this.$nextTick(() => adjustDialogZ(this.$refs.changeWorldImageDialog.$el)); + } + API.getWorldImages(params).then((args) => { + this.previousImagesTableFileId = args.json.id; + var images = args.json.versions; + var imageArray = []; + images.forEach((image) => { + if (image.file) { + imageArray.push(image.file.url); + } + }); + this.previousImagesTable = images; + }); + } else if (type === 'User') { + this.previousImagesDialogVisible = true; + this.$nextTick(() => adjustDialogZ(this.$refs.previousImagesDialog.$el)); + API.getAvatarImages(params).then((args) => { + this.previousImagesTableFileId = args.json.id; + var images = args.json.versions; + var imageArray = []; + images.forEach((image) => { + if (image.file) { + imageArray.push(image.file.url); + } + }); + this.previousImagesTable = images; + }); + } }; + $app.data.previousImagesDialogVisible = false; + $app.data.changeAvatarImageDialogVisible = false; + $app.data.changeAvatarImageDialogLoading = false; + $app.data.changeWorldImageDialogVisible = false; + $app.data.changeWorldImageDialogLoading = false; + $app.data.previousImagesTable = {}; + $app.data.previousImagesFileId = ''; + + API.$on('LOGIN', function () { + $app.previousImagesTable = {}; + $app.previousImagesDialogVisible = false; + }); + API.getAvatarImages = async function (params) { return await this.call(`file/${params.fileId}`, { method: 'GET', @@ -10581,6 +10672,20 @@ speechSynthesis.getVoices(); }); }; + API.getWorldImages = async function (params) { + return await this.call(`file/${params.fileId}`, { + method: 'GET', + params + }).then((json) => { + var args = { + json, + params + }; + this.$emit('WORLDIMAGE:GET', args); + return args; + }); + }; + API.$on('AVATARIMAGE:GET', function (args) { $app.storeAvatarImage(args); }); @@ -10605,31 +10710,33 @@ speechSynthesis.getVoices(); $app.methods.setAvatarImage = function (image) { this.changeAvatarImageDialogLoading = true; var parmas = { - id: $app.avatarDialog.id, - imageUrl: `https://api.vrchat.cloud/api/1/file/${$app.changeAvatarImageTableFileId}/${image.version}/file` + id: this.avatarDialog.id, + imageUrl: `https://api.vrchat.cloud/api/1/file/${this.previousImagesTableFileId}/${image.version}/file` }; API.setAvatarImage(parmas).finally(() => { this.changeAvatarImageDialogLoading = false; - $app.changeAvatarImageDialogVisible = false; + this.changeAvatarImageDialogVisible = false; }); }; - $app.methods.compareCurrentAvatarImage = function (image) { - if (`https://api.vrchat.cloud/api/1/file/${$app.changeAvatarImageTableFileId}/${image.version}/file` === this.avatarDialog.ref.imageUrl) { + $app.methods.setWorldImage = function (image) { + this.changeWorldImageDialogLoading = true; + var parmas = { + id: this.worldDialog.id, + imageUrl: `https://api.vrchat.cloud/api/1/file/${this.previousImagesTableFileId}/${image.version}/file` + }; + API.setWorldImage(parmas).finally(() => { + this.changeWorldImageDialogLoading = false; + this.changeWorldImageDialogVisible = false; + }); + }; + + $app.methods.compareCurrentImage = function (image) { + if (`https://api.vrchat.cloud/api/1/file/${this.previousImagesTableFileId}/${image.version}/file` === this.avatarDialog.ref.imageUrl) { return true; } return false; - } - - $app.data.changeAvatarImageDialogVisible = false; - $app.data.changeAvatarImageDialogLoading = false; - $app.data.changeAvatarImageTable = {}; - $app.data.changeAvatarImageTableFileId = ''; - - API.$on('LOGIN', function () { - $app.changeAvatarImageTable = {}; - $app.changeAvatarImageDialogVisible = false; - }); + }; // Avatar names diff --git a/html/src/app.scss b/html/src/app.scss index 933fed76..bdf6e05b 100644 --- a/html/src/app.scss +++ b/html/src/app.scss @@ -385,23 +385,22 @@ img.friends-list-avatar { object-fit: cover; } -.x-change-avatar-item { - cursor: pointer; +.x-change-image-item { display: inline-block; padding: 4px 4px 0 4px; } -.x-change-avatar-item:hover { +.x-change-image-item:hover { background: #f0f0f0; border-radius: 2px; } -.x-change-avatar-item > img { +.x-change-image-item > img { width: 240px; height: 180px; } -.current-avatar-image { +.current-image { border: 2px solid #67c23a; padding: 2px 2px 0 2px; } diff --git a/html/src/index.pug b/html/src/index.pug index fc5e7785..aa12f32f 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -987,6 +987,7 @@ html el-dropdown-item(v-else icon="el-icon-plus" command="Send Friend Request") Send Friend Request el-dropdown-item(icon="el-icon-s-custom" command="Show Avatar Author" divided) Show Avatar Author el-dropdown-item(icon="el-icon-s-custom" command="Show Fallback Avatar Details") Show Fallback Avatar Details + el-dropdown-item(icon="el-icon-picture-outline" command="Previous Images") Show Avatar Previous Images el-dropdown-item(v-if="userDialog.isBlock" icon="el-icon-circle-check" command="Unblock" divided style="color:#F56C6C") Unblock el-dropdown-item(v-else icon="el-icon-circle-close" command="Block" divided) Block el-dropdown-item(v-if="userDialog.isMute" icon="el-icon-microphone" command="Unmute" style="color:#F56C6C") Unmute @@ -1138,9 +1139,13 @@ html el-dropdown-item(icon="el-icon-s-flag" command="New Instance" divided) New Instance el-dropdown-item(v-if="API.currentUser.$homeLocation && API.currentUser.$homeLocation.worldId === worldDialog.id" icon="el-icon-magic-stick" command="Reset Home" divided) Reset Home el-dropdown-item(v-else icon="el-icon-s-home" command="Make Home" divided) Make Home - el-dropdown-item(icon="el-icon-edit" command="Rename") Rename - el-dropdown-item(icon="el-icon-edit" command="Change Description") Change Description - el-dropdown-item(v-if="API.currentUser.id === worldDialog.ref.authorId" icon="el-icon-delete" command="Delete" style="color:#F56C6C" divided) Delete + template(v-if="API.currentUser.id !== worldDialog.ref.authorId") + el-dropdown-item(icon="el-icon-picture-outline" command="Previous Images") Previous Images + template(v-else) + el-dropdown-item(icon="el-icon-edit" command="Rename") Rename + el-dropdown-item(icon="el-icon-edit" command="Change Description") Change Description + el-dropdown-item(icon="el-icon-picture-outline" command="Change Image") Change Image + el-dropdown-item(icon="el-icon-delete" command="Delete" style="color:#F56C6C" divided) Delete el-tabs el-tab-pane(label="Instances") div. @@ -1248,6 +1253,7 @@ html el-dropdown-menu(#default="dropdown") el-dropdown-item(icon="el-icon-check" command="Select Avatar") Select Avatar el-dropdown-item(v-if="/quest/.test(avatarDialog.ref.tags)" icon="el-icon-check" command="Select Fallback Avatar") Select Fallback Avatar + el-dropdown-item(v-if="avatarDialog.ref.authorId !== API.currentUser.id" icon="el-icon-picture-outline" command="Previous Images") Previous Images template(v-if="avatarDialog.ref.authorId === API.currentUser.id") el-dropdown-item(v-if="avatarDialog.ref.releaseStatus === 'public'" icon="el-icon-user-solid" command="Make Private" divided) Make Private el-dropdown-item(v-else icon="el-icon-user" command="Make Public" divided) Make Public @@ -1697,9 +1703,23 @@ html //- dialog: Change avatar image el-dialog.x-dialog(ref="changeAvatarImageDialog" :visible.sync="changeAvatarImageDialogVisible" title="Change Avatar Image" width="800px") div(v-loading="changeAvatarImageDialogLoading") - div(style="display:inline-block" v-for="image in changeAvatarImageTable" :key="image.version" v-if="image.file") - .x-change-avatar-item(@click="setAvatarImage(image)" :class="{ 'current-avatar-image': compareCurrentAvatarImage(image) }") - img.avatar(v-lazy="image.file.url") + div(style="display:inline-block" v-for="image in previousImagesTable" :key="image.version" v-if="image.file") + .x-change-image-item(@click="setAvatarImage(image)" style="cursor:pointer" :class="{ 'current-image': compareCurrentImage(image) }") + img.image(v-lazy="image.file.url") + + //- dialog: Change world image + el-dialog.x-dialog(ref="changeWorldImageDialog" :visible.sync="changeWorldImageDialogVisible" title="Change World Image" width="800px") + div(v-loading="changeWorldImageDialogLoading") + div(style="display:inline-block" v-for="image in previousImagesTable" :key="image.version" v-if="image.file") + .x-change-image-item(@click="setWorldImage(image)" style="cursor:pointer" :class="{ 'current-image': compareCurrentImage(image) }") + img.image(v-lazy="image.file.url") + + //- dialog: Display previous avatar/world images + el-dialog.x-dialog(ref="previousImagesDialog" :visible.sync="previousImagesDialogVisible" title="Previous Images" width="800px") + div + div(style="display:inline-block" v-for="image in previousImagesTable" :key="image.version" v-if="image.file") + .x-change-image-item + img.image(v-lazy="image.file.url") //- dialog: open source software notice el-dialog.x-dialog(:visible.sync="ossDialog" title="Open Source Software Notice" width="650px")