diff --git a/html/src/app.js b/html/src/app.js index d127d04a..05f8f1aa 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -5712,11 +5712,15 @@ speechSynthesis.getVoices(); ); } if (this.saveCredentials) { - savedCredentials[currentUser.username].loginParmas = - this.saveCredentials; + var credentialsToSave = { + user: currentUser, + loginParmas: this.saveCredentials + }; + savedCredentials[currentUser.username] = credentialsToSave; delete this.saveCredentials; - } - if (typeof savedCredentials[currentUser.username] !== 'undefined') { + } else if ( + typeof savedCredentials[currentUser.username] !== 'undefined' + ) { savedCredentials[currentUser.username].user = currentUser; savedCredentials[currentUser.username].cookies = await webApiService.getCookies(); @@ -11449,9 +11453,6 @@ speechSynthesis.getVoices(); case 'Rename': this.promptRenameWorld(D); break; - case 'Upload Image': - document.getElementById('WorldImageUploadButton').click(); - break; case 'Change Image': this.displayPreviousImages('World', 'Change'); break; @@ -11461,6 +11462,9 @@ speechSynthesis.getVoices(); case 'Change Description': this.promptChangeWorldDescription(D); break; + case 'Download Unity Package': + this.openExternalLink(this.worldDialog.ref.unityPackageUrl); + break; default: this.$confirm(`Continue? ${command}`, 'Confirm', { confirmButtonText: 'Confirm', @@ -11657,9 +11661,6 @@ speechSynthesis.getVoices(); case 'Rename': this.promptRenameAvatar(D); break; - case 'Upload Image': - document.getElementById('AvatarImageUploadButton').click(); - break; case 'Change Image': this.displayPreviousImages('Avatar', 'Change'); break; @@ -12539,6 +12540,12 @@ speechSynthesis.getVoices(); }); $app.methods.setVRCPlusIcon = function (fileId) { + if (!API.currentUser.$isVRCPlus) { + this.$message({ + message: 'VRCPlus required', + type: 'error' + }); + } var userIcon = ''; if (fileId) { userIcon = `https://api.vrchat.cloud/api/1/file/${fileId}/1`; @@ -12587,6 +12594,18 @@ speechSynthesis.getVoices(); }); }; + API.deleteFileVersion = function (params) { + return this.call(`file/${params.fileId}/${params.version}`, { + method: 'DELETE' + }).then((json) => { + var args = { + json, + params + }; + return args; + }); + }; + $app.methods.compareCurrentVRCPlusIcon = function (userIcon) { var currentUserIcon = extractFileId(API.currentUser.userIcon); if (userIcon === currentUserIcon) { @@ -13613,6 +13632,7 @@ speechSynthesis.getVoices(); return; } this.avatarDialog.loading = true; + this.changeAvatarImageDialogLoading = true; var r = new FileReader(); r.onload = async function (file) { var base64File = btoa(r.result); @@ -13688,6 +13708,7 @@ speechSynthesis.getVoices(); method: 'PUT' }); $app.avatarDialog.loading = false; + $app.changeAvatarImageDialogLoading = false; }; API.$on('AVATARIMAGE:INIT', function (args) { @@ -13748,6 +13769,7 @@ speechSynthesis.getVoices(); .then((json) => { if (json.status !== 200) { $app.avatarDialog.loading = false; + $app.changeAvatarImageDialogLoading = false; this.$throw('Avatar image upload failed', json); } var args = { @@ -13844,6 +13866,7 @@ speechSynthesis.getVoices(); .then((json) => { if (json.status !== 200) { $app.avatarDialog.loading = false; + $app.changeAvatarImageDialogLoading = false; this.$throw('Avatar image upload failed', json); } var args = { @@ -13943,6 +13966,7 @@ speechSynthesis.getVoices(); return; } this.worldDialog.loading = true; + this.changeWorldImageDialogLoading = true; var r = new FileReader(); r.onload = async function (file) { var base64File = btoa(r.result); @@ -14018,6 +14042,7 @@ speechSynthesis.getVoices(); method: 'PUT' }); $app.worldDialog.loading = false; + $app.changeWorldImageDialogLoading = false; }; API.$on('WORLDIMAGE:INIT', function (args) { @@ -14078,6 +14103,7 @@ speechSynthesis.getVoices(); .then((json) => { if (json.status !== 200) { $app.worldDialog.loading = false; + $app.changeWorldImageDialogLoading = false; this.$throw('World image upload failed', json); } var args = { @@ -14174,6 +14200,7 @@ speechSynthesis.getVoices(); .then((json) => { if (json.status !== 200) { $app.worldDialog.loading = false; + $app.changeWorldImageDialogLoading = false; this.$throw('World image upload failed', json); } var args = { @@ -14240,11 +14267,13 @@ speechSynthesis.getVoices(); API.$on('AVATARIMAGE:SET', function (args) { $app.avatarDialog.loading = false; + $app.changeAvatarImageDialogLoading = false; if (args.json.imageUrl === args.params.imageUrl) { $app.$message({ message: 'Avatar image changed', type: 'success' }); + $app.displayPreviousImages('Avatar', 'Change'); } else { this.$throw(0, 'Avatar image change failed'); } @@ -14267,11 +14296,13 @@ speechSynthesis.getVoices(); API.$on('WORLDIMAGE:SET', function (args) { $app.worldDialog.loading = false; + $app.changeWorldImageDialogLoading = false; if (args.json.imageUrl === args.params.imageUrl) { $app.$message({ message: 'World image changed', type: 'success' }); + $app.displayPreviousImages('World', 'Change'); } else { this.$throw(0, 'World image change failed'); } @@ -14312,7 +14343,12 @@ speechSynthesis.getVoices(); } API.getAvatarImages(params).then((args) => { this.previousImagesTableFileId = args.json.id; - var images = args.json.versions.reverse(); + var images = []; + args.json.versions.forEach((item) => { + if (!item.deleted) { + images.unshift(item); + } + }); this.checkPreviousImageAvailable(images); }); } else if (type === 'World') { @@ -14324,13 +14360,23 @@ speechSynthesis.getVoices(); } API.getWorldImages(params).then((args) => { this.previousImagesTableFileId = args.json.id; - var images = args.json.versions.reverse(); + var images = []; + args.json.versions.forEach((item) => { + if (!item.deleted) { + images.unshift(item); + } + }); this.checkPreviousImageAvailable(images); }); } else if (type === 'User') { API.getAvatarImages(params).then((args) => { this.previousImagesTableFileId = args.json.id; - var images = args.json.versions.reverse(); + var images = []; + args.json.versions.forEach((item) => { + if (!item.deleted) { + images.unshift(item); + } + }); this.checkPreviousImageAvailable(images); }); } @@ -14430,6 +14476,32 @@ speechSynthesis.getVoices(); }); }; + $app.methods.uploadAvatarImage = function () { + document.getElementById('AvatarImageUploadButton').click(); + }; + + $app.methods.deleteAvatarImage = function () { + this.changeAvatarImageDialogLoading = true; + var parmas = { + fileId: this.previousImagesTableFileId, + version: this.previousImagesTable[0].version + }; + API.deleteFileVersion(parmas) + .then((args) => { + this.previousImagesTableFileId = args.json.id; + var images = []; + args.json.versions.forEach((item) => { + if (!item.deleted) { + images.unshift(item); + } + }); + this.checkPreviousImageAvailable(images); + }) + .finally(() => { + this.changeAvatarImageDialogLoading = false; + }); + }; + $app.methods.setWorldImage = function (image) { this.changeWorldImageDialogLoading = true; var parmas = { @@ -14442,6 +14514,32 @@ speechSynthesis.getVoices(); }); }; + $app.methods.uploadWorldImage = function () { + document.getElementById('WorldImageUploadButton').click(); + }; + + $app.methods.deleteWorldImage = function () { + this.changeWorldImageDialogLoading = true; + var parmas = { + fileId: this.previousImagesTableFileId, + version: this.previousImagesTable[0].version + }; + API.deleteFileVersion(parmas) + .then((args) => { + this.previousImagesTableFileId = args.json.id; + var images = []; + args.json.versions.forEach((item) => { + if (!item.deleted) { + images.unshift(item); + } + }); + this.checkPreviousImageAvailable(images); + }) + .finally(() => { + this.changeWorldImageDialogLoading = false; + }); + }; + $app.methods.compareCurrentImage = function (image) { if ( `https://api.vrchat.cloud/api/1/file/${this.previousImagesTableFileId}/${image.version}/file` === @@ -15497,6 +15595,12 @@ speechSynthesis.getVoices(); }); $app.methods.setProfilePicOverride = function (fileId) { + if (!API.currentUser.$isVRCPlus) { + this.$message({ + message: 'VRCPlus required', + type: 'error' + }); + } var profilePicOverride = ''; if (fileId) { profilePicOverride = `https://api.vrchat.cloud/api/1/file/${fileId}/1`; @@ -15910,7 +16014,6 @@ speechSynthesis.getVoices(); key !== API.currentUser.id ) { API.cachedUsers.delete(key); - console.log(key); } }); API.cachedWorlds.forEach((value, key) => { @@ -15919,7 +16022,6 @@ speechSynthesis.getVoices(); value.authorId !== API.currentUser.id ) { API.cachedWorlds.delete(key); - console.log(key); } }); API.cachedAvatars.forEach((value, key) => { @@ -15928,7 +16030,6 @@ speechSynthesis.getVoices(); value.authorId !== API.currentUser.id ) { API.cachedAvatars.delete(key); - console.log(key); } }); diff --git a/html/src/index.pug b/html/src/index.pug index 4d95e3d2..e0a4eec4 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -1125,11 +1125,11 @@ html div(v-loading="userDialog.loading") div(style="display:flex") el-popover(v-if="userDialog.ref.profilePicOverride" placement="right" width="500px" trigger="click") - img.x-link(slot="reference" v-lazy="userDialog.ref.profilePicOverride" style="flex:none;width:160px;height:120px;border-radius:4px;object-fit:cover") - img.x-link(v-lazy="userDialog.ref.profilePicOverride" style="width:500px;height:375px;object-fit:cover" @click="openExternalLink(userDialog.ref.profilePicOverride)") + img.x-link(slot="reference" v-lazy="userDialog.ref.profilePicOverride" style="flex:none;height:120px;width:213.33px;border-radius:4px;object-fit:cover") + img.x-link(v-lazy="userDialog.ref.profilePicOverride" style="height:400px" @click="openExternalLink(userDialog.ref.profilePicOverride)") el-popover(v-else placement="right" width="500px" trigger="click") - img.x-link(slot="reference" v-lazy="userDialog.ref.currentAvatarThumbnailImageUrl" style="flex:none;width:160px;height:120px;border-radius:4px") - img.x-link(v-lazy="userDialog.ref.currentAvatarImageUrl" style="width:500px;height:375px" @click="openExternalLink(userDialog.ref.currentAvatarImageUrl)") + img.x-link(slot="reference" v-lazy="userDialog.ref.currentAvatarThumbnailImageUrl" style="flex:none;height:120px;width:160px;border-radius:4px;object-fit:cover") + img.x-link(v-lazy="userDialog.ref.currentAvatarImageUrl" style="height:500px" @click="openExternalLink(userDialog.ref.currentAvatarImageUrl)") div(style="flex:1;display:flex;align-items:center;margin-left:15px") div(style="flex:1") div @@ -1163,8 +1163,8 @@ html span(v-text="userDialog.ref.statusDescription" style="font-size:12px") div(v-if="userDialog.ref.userIcon" style="flex:none;margin-right:10px") el-popover(placement="right" width="500px" trigger="click") - img.x-link(slot="reference" v-lazy="userDialog.ref.userIcon" style="flex:none;width:120px;height:120px;border-radius:4px") - img.x-link(v-lazy="userDialog.ref.userIcon" style="width:500px;height:500px;" @click="openExternalLink(userDialog.ref.userIcon)") + img.x-link(slot="reference" v-lazy="userDialog.ref.userIcon" style="flex:none;width:120px;height:120px;border-radius:4px;object-fit:cover") + img.x-link(v-lazy="userDialog.ref.userIcon" style="height:500px" @click="openExternalLink(userDialog.ref.userIcon)") div(style="flex:none") el-tooltip(v-if="userDialog.isFavorite" placement="top" content="Remove from favorites" :disabled="hideTooltips") el-button(@click="userDialogCommand('Delete Favorite')" type="warning" icon="el-icon-star-on" circle) @@ -1399,8 +1399,7 @@ html 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-upload2" command="Upload Image") Upload Image (1200x900) - input(type="file" accept="image/*" @change="onFileChangeWorldImage" id="WorldImageUploadButton" style="display:none") + el-dropdown-item(v-if="worldDialog.ref.unityPackageUrl" icon="el-icon-download" command="Download Unity Package") Download Unity Package el-dropdown-item(icon="el-icon-delete" command="Delete" style="color:#F56C6C" divided) Delete el-tabs el-tab-pane(label="Instances") @@ -1548,8 +1547,6 @@ html 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-upload2" command="Upload Image") Upload Image (1200x900) - input(type="file" accept="image/*" @change="onFileChangeAvatarImage" id="AvatarImageUploadButton" style="display:none") el-dropdown-item(v-if="avatarDialog.ref.unityPackageUrl" icon="el-icon-download" command="Download Unity Package") Download Unity Package el-dropdown-item(icon="el-icon-user" command="Delete" style="color:#F56C6C" divided) Delete el-tabs @@ -2363,6 +2360,12 @@ html //- dialog: Change avatar image el-dialog.x-dialog(ref="changeAvatarImageDialog" :visible.sync="changeAvatarImageDialogVisible" title="Change Avatar Image" width="800px") div(v-loading="changeAvatarImageDialogLoading") + input(type="file" accept="image/*" @change="onFileChangeAvatarImage" id="AvatarImageUploadButton" style="display:none") + el-button-group(style="padding-bottom:10px") + el-button(type="default" size="small" @click="displayPreviousImages('Avatar', 'Change')" icon="el-icon-refresh") Refresh + el-button(type="default" size="small" @click="uploadAvatarImage" icon="el-icon-upload2") Upload Image (1200x900) + //- el-button(type="default" size="small" @click="deleteAvatarImage" icon="el-icon-delete") Delete Latest Image + br 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") @@ -2370,6 +2373,12 @@ html //- dialog: Change world image el-dialog.x-dialog(ref="changeWorldImageDialog" :visible.sync="changeWorldImageDialogVisible" title="Change World Image" width="800px") div(v-loading="changeWorldImageDialogLoading") + input(type="file" accept="image/*" @change="onFileChangeWorldImage" id="WorldImageUploadButton" style="display:none") + el-button-group(style="padding-bottom:10px") + el-button(type="default" size="small" @click="displayPreviousImages('World', 'Change')" icon="el-icon-refresh") Refresh + el-button(type="default" size="small" @click="uploadWorldImage" icon="el-icon-upload2") Upload Image (1200x900) + //- el-button(type="default" size="small" @click="deleteWorldImage" icon="el-icon-delete") Delete Latest Image + br 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")