Avatar Gallery Order

This commit is contained in:
Natsumi
2025-05-26 04:33:41 +10:00
parent df56b1d8b9
commit 2d58d3cbbd
5 changed files with 140 additions and 20 deletions

View File

@@ -215,6 +215,27 @@ const avatarReq = {
// window.API.$emit('AVATARGALLERYIMAGE:ADD', args);
return args;
});
},
/**
* @param {string[]} order
* @returns {Promise<{json: any, params}>}
*/
setAvatarGalleryOrder(order) {
const params = {
ids: order
};
return window.API.call('files/order', {
method: 'PUT',
params
}).then((json) => {
const args = {
json,
params
};
// window.API.$emit('AVATARGALLERYIMAGE:ORDER', args);
return args;
});
}
};
// #endregion

View File

@@ -9535,6 +9535,7 @@ console.log(`isLinux: ${LINUX}`);
bundleSizes: [],
platformInfo: {},
galleryImages: [],
galleryLoading: false,
lastUpdated: '',
inCache: false,
cacheSize: 0,
@@ -9578,6 +9579,7 @@ console.log(`isLinux: ${LINUX}`);
D.bundleSizes = [];
D.platformInfo = {};
D.galleryImages = [];
D.galleryLoading = true;
D.isFavorite =
API.cachedFavoritesByObjectId.has(avatarId) ||
(API.currentUser.$isVRCPlus &&
@@ -9637,18 +9639,30 @@ console.log(`isLinux: ${LINUX}`);
$app.methods.getAvatarGallery = async function (avatarId) {
var D = this.avatarDialog;
const args = await avatarRequest.getAvatarGallery(avatarId);
const args = await avatarRequest
.getAvatarGallery(avatarId)
.finally(() => {
D.galleryLoading = false;
});
if (args.params.galleryId !== D.id) {
return;
}
D.galleryImages = [];
for (const file of args.json) {
// wtf is this? why is order sorting only needed if it's your own avatar?
const sortedGallery = args.json.sort((a, b) => {
if (!a.order && !b.order) {
return 0;
}
return a.order - b.order;
});
for (const file of sortedGallery) {
const url = file.versions[file.versions.length - 1].file.url;
D.galleryImages.push(url);
}
// for JSON tab treeData
D.ref.gallery = args.json;
return D.galleryImages;
};
$app.methods.selectAvatarWithConfirmation = function (id) {

View File

@@ -23,6 +23,20 @@ const _utils = {
)
);
},
moveArrayItem(array, fromIndex, toIndex) {
if (!Array.isArray(array) || fromIndex === toIndex) {
return;
}
if (fromIndex < 0 || fromIndex >= array.length) {
return;
}
if (toIndex < 0 || toIndex >= array.length) {
return;
}
const item = array[fromIndex];
array.splice(fromIndex, 1);
array.splice(toIndex, 0, item);
},
escapeTag(tag) {
var s = String(tag);
return s.replace(/["&'<>]/g, (c) => `&#${c.charCodeAt(0)};`);

View File

@@ -4,7 +4,7 @@
class="x-dialog x-avatar-dialog"
:visible.sync="avatarDialog.visible"
:show-close="false"
width="600px">
width="700px">
<div v-loading="avatarDialog.loading">
<div style="display: flex">
<el-popover placement="right" width="500px" trigger="click">
@@ -378,6 +378,7 @@
@change="onFileChangeAvatarGallery" />
<el-button
v-if="avatarDialog.ref.authorId === API.currentUser.id"
v-loading="avatarDialog.galleryLoading"
size="small"
icon="el-icon-upload2"
style="margin-left: 5px"
@@ -394,14 +395,31 @@
:src="imageUrl"
style="width: 100%; height: 100%; object-fit: contain"
@click="showFullscreenImageDialog(imageUrl)" />
<el-button
<div
v-if="avatarDialog.ref.authorId === API.currentUser.id"
size="mini"
icon="el-icon-delete"
circle
class="x-link"
style="position: absolute; bottom: 5px; right: 5px"
@click.stop="deleteAvatarGalleryImage(imageUrl)"></el-button>
style="position: absolute; bottom: 5px; left: 33.3%">
<el-button
size="mini"
icon="el-icon-back"
circle
class="x-link"
style="margin-left: 0px"
@click.stop="reorderAvatarGalleryImage(imageUrl, -1)"></el-button>
<el-button
size="mini"
icon="el-icon-right"
circle
class="x-link"
style="margin-left: 0px"
@click.stop="reorderAvatarGalleryImage(imageUrl, 1)"></el-button>
<el-button
size="mini"
icon="el-icon-delete"
circle
class="x-link"
style="margin-left: 0px"
@click.stop="deleteAvatarGalleryImage(imageUrl)"></el-button>
</div>
</el-carousel-item>
</el-carousel>
</div>
@@ -1280,16 +1298,22 @@
}
const r = new FileReader();
r.onload = function () {
props.avatarDialog.galleryLoading = true;
const base64Body = btoa(r.result);
avatarRequest.uploadAvatarGalleryImage(base64Body, props.avatarDialog.id).then((args) => {
$message({
message: t('message.avatar_gallery.uploaded'),
type: 'success'
avatarRequest
.uploadAvatarGalleryImage(base64Body, props.avatarDialog.id)
.then((args) => {
$message({
message: t('message.avatar_gallery.uploaded'),
type: 'success'
});
console.log(args);
props.avatarDialog.galleryImages = getAvatarGallery(props.avatarDialog.id);
return args;
})
.finally(() => {
props.avatarDialog.galleryLoading = false;
});
console.log(args);
getAvatarGallery(props.avatarDialog.id);
return args;
});
};
r.readAsBinaryString(files[0]);
clearFile();
@@ -1302,7 +1326,50 @@
message: t('message.avatar_gallery.deleted'),
type: 'success'
});
getAvatarGallery(props.avatarDialog.id);
props.avatarDialog.galleryImages = getAvatarGallery(props.avatarDialog.id);
return args;
});
}
function reorderAvatarGalleryImage(imageUrl, direction) {
const fileId = extractFileId(imageUrl);
let fileIds = [];
props.avatarDialog.ref.gallery.forEach((item) => {
fileIds.push(extractFileId(item.id));
});
const index = fileIds.indexOf(fileId);
if (index === -1) {
$message({
message: t('message.avatar_gallery.not_found'),
type: 'error'
});
return;
}
if (direction === -1 && index === 0) {
$message({
message: t('message.avatar_gallery.already_first'),
type: 'warning'
});
return;
}
if (direction === 1 && index === fileIds.length - 1) {
$message({
message: t('message.avatar_gallery.already_last'),
type: 'warning'
});
return;
}
if (direction === -1) {
utils.moveArrayItem(fileIds, index, index - 1);
} else {
utils.moveArrayItem(fileIds, index, index + 1);
}
avatarRequest.setAvatarGalleryOrder(fileIds).then((args) => {
$message({
message: t('message.avatar_gallery.reordered'),
type: 'success'
});
props.avatarDialog.galleryImages = getAvatarGallery(props.avatarDialog.id);
return args;
});
}

View File

@@ -1643,7 +1643,11 @@
"avatar_gallery": {
"uploaded": "Avatar gallery image uploaded",
"failed": "Failed to upload avatar gallery image",
"deleted": "Avatar gallery image deleted"
"deleted": "Avatar gallery image deleted",
"not_found": "Avatar gallery fileId not found",
"already_first": "Already first image",
"already_last": "Already last image",
"reordered": "Successfully reordered avatar gallery images"
},
"world": {
"image_changed": "World image changed",