Upgrade to Vue3 and Element Plus (#1374)

* Update Vue devtools

* upgrade vue pinia element-plus vue-i18n, add vite

* fix: i18n

* global components

* change v-deep

* upgrade vue-lazyload

* data table

* update enlint and safe-dialog

* package.json and vite.config.js

* el-icon

* el-message

* vue 2 -> vue3 migration changes

* $pinia

* dialog

* el-popover slot

* lint

* chore

* slot

* scss

* remote state access

* misc

* jsconfig

* el-button size mini -> small

* :model-value

* ElMessageBox

* datatable

* remove v-lazyload

* template #dropdown

* mini -> small

* css

* byebye hideTooltips

* use sass-embedded

* Update SQLite, remove unneeded libraries

* Fix shift remove local avatar favorites

* Electron arm64

* arm64 support

* bye pug

* f-word vite hah

* misc

* remove safe dialog component

* Add self invite to launch dialog

* Fix errors

* Icons 1

* improve localfavorite loading performance

* improve favorites world item performance

* dialog visibility changes for Element Plus

* clear element plus error

* import performance

* revert App.vue hah

* hah

* Revert "Add self invite to launch dialog"

This reverts commit 4801cfad58.

* Toggle self invite/open in-game

* Self invite on launch dialog

* el-button icon

* el-icon

* fix user dialog tab switching logic

* fix PlayerList

* Formatting changes

* More icons

* Fix friend log table

* loading margin

* fix markdown

* fix world dialog tab switching issue

* Fixes and formatting

* fix: global i18n.t export

* fix favorites world tab not working

* Create instance, displayName

* Remove group members sort by userId

* Fix loading dialog tabs on swtich

* Star

* charts console.warn

* wip: fix charts

* wip: fix charts

* wip: charts composables

* fix favorite item tooltip warning

* Fixes and formatting

* Clean up image dialogs

* Remove unused method

* Fix platform/size border

* Fix platform/size border

* $vr

* fix friendExportDialogVisible binding

* ElMessageBox and Settings

* Login formatting

* Rename VR overlay query

* Fix image popover and userdialog badges

* Formatting

* Big buttons

* Fixes, update Cef

* Fix gameLog table nav buttons jumping around while using nav buttons

* Fix z-index

* vr overlay

* vite input add theme

* defineAsyncComponent

* ISO 639-1

* fix i18n

* clean t

* Formatting, fix calendar, rotate arrows

* Show user status when user is offline

* Fix VR overlay

* fix theme and clean up

* split InstanceActivity

* tweak

* Fix VR overlay formatting

* fix scss var

* AppDebug hahahaha

* Years

* remove reactive

* improve perf

* state hah…

* fix user rendering poblems when user object is not yet loaded

* improve perf

* Update avatar/world image uploader, licenses, remove previous images dialog (old images are now deleted)

* improve perf 1

* Suppress stray errors

* fix traveling location display issue

* Fix empty instance creator

* improve friend list refresh performance

* fix main charts

* fix chart

* Fix darkmode

* Fix avatar dialog tags

---------

Co-authored-by: pa <maplenagisa@gmail.com>
This commit is contained in:
Natsumi
2025-09-12 10:45:24 +12:00
committed by GitHub
parent b233bbc299
commit 3324d0d279
249 changed files with 12948 additions and 19815 deletions
+42 -48
View File
@@ -14,15 +14,12 @@
<span class="name">{{ t('view.favorite.edit_mode') }}</span>
<el-switch v-model="editFavoritesMode" style="margin-left: 5px"></el-switch>
</div>
<el-tooltip
placement="bottom"
:content="t('view.favorite.refresh_favorites_tooltip')"
:disabled="hideTooltips">
<el-tooltip placement="bottom" :content="t('view.favorite.refresh_favorites_tooltip')">
<el-button
type="default"
:loading="isFavoriteLoading"
size="small"
icon="el-icon-refresh"
:icon="Refresh"
circle
@click="
refreshFavorites();
@@ -33,13 +30,11 @@
<el-tabs v-model="currentTabName" v-loading="isFavoriteLoading" type="card" style="height: 100%">
<el-tab-pane name="friend" :label="t('view.favorite.friends.header')">
<FavoritesFriendTab
:hide-tooltips="hideTooltips"
:edit-favorites-mode="editFavoritesMode"
@change-favorite-group-name="changeFavoriteGroupName" />
</el-tab-pane>
<el-tab-pane name="world" :label="t('view.favorite.worlds.header')" lazy>
<FavoritesWorldTab
:hide-tooltips="hideTooltips"
:edit-favorites-mode="editFavoritesMode"
:refresh-local-world-favorites="refreshLocalWorldFavorites"
@change-favorite-group-name="changeFavoriteGroupName"
@@ -47,7 +42,6 @@
</el-tab-pane>
<el-tab-pane name="avatar" :label="t('view.favorite.avatars.header')" lazy>
<FavoritesAvatarTab
:hide-tooltips="hideTooltips"
:edit-favorites-mode="editFavoritesMode"
:refreshing-local-favorites="refreshingLocalFavorites"
@change-favorite-group-name="changeFavoriteGroupName"
@@ -58,19 +52,19 @@
</template>
<script setup>
import { ref, getCurrentInstance } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Refresh } from '@element-plus/icons-vue';
import { ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import * as workerTimers from 'worker-timers';
import { avatarRequest, favoriteRequest, worldRequest } from '../../api';
import { useAppearanceSettingsStore, useFavoriteStore, useUiStore, useAvatarStore } from '../../stores';
import { useFavoriteStore, useUiStore, useAvatarStore } from '../../stores';
import FavoritesAvatarTab from './components/FavoritesAvatarTab.vue';
import FavoritesFriendTab from './components/FavoritesFriendTab.vue';
import FavoritesWorldTab from './components/FavoritesWorldTab.vue';
const { t } = useI18n();
const { proxy } = getCurrentInstance();
const { hideTooltips } = storeToRefs(useAppearanceSettingsStore());
const {
favoriteFriends,
favoriteWorlds,
@@ -120,21 +114,22 @@
if (elementsTicked.length === 0) {
return;
}
proxy.$confirm(
ElMessageBox.confirm(
`Are you sure you want to unfavorite ${elementsTicked.length} favorites?
This action cannot be undone.`,
`Delete ${elementsTicked.length} favorites?`,
{
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'info',
callback: (action) => {
if (action === 'confirm') {
bulkUnfavoriteSelection(elementsTicked);
}
}
type: 'info'
}
);
)
.then((action) => {
if (action === 'confirm') {
bulkUnfavoriteSelection(elementsTicked);
}
})
.catch(() => {});
}
function bulkUnfavoriteSelection(elementsTicked) {
@@ -146,7 +141,7 @@
editFavoritesMode.value = false;
}
function changeFavoriteGroupName(ctx) {
proxy.$prompt(
ElMessageBox.prompt(
t('prompt.change_favorite_group_name.description'),
t('prompt.change_favorite_group_name.header'),
{
@@ -156,33 +151,32 @@
inputPlaceholder: t('prompt.change_favorite_group_name.input_placeholder'),
inputValue: ctx.displayName,
inputPattern: /\S+/,
inputErrorMessage: t('prompt.change_favorite_group_name.input_error'),
callback: (action, instance) => {
if (action === 'confirm') {
favoriteRequest
.saveFavoriteGroup({
type: ctx.type,
group: ctx.name,
displayName: instance.inputValue
})
.then((args) => {
handleFavoriteGroup({
json: args.json,
params: {
favoriteGroupId: args.json.id
}
});
proxy.$message({
message: t('prompt.change_favorite_group_name.message.success'),
type: 'success'
});
// load new group name
refreshFavoriteGroups();
});
}
}
inputErrorMessage: t('prompt.change_favorite_group_name.input_error')
}
);
)
.then(({ value }) => {
favoriteRequest
.saveFavoriteGroup({
type: ctx.type,
group: ctx.name,
displayName: value
})
.then((args) => {
handleFavoriteGroup({
json: args.json,
params: {
favoriteGroupId: args.json.id
}
});
ElMessage({
message: t('prompt.change_favorite_group_name.message.success'),
type: 'success'
});
// load new group name
refreshFavoriteGroups();
});
})
.catch(() => {});
}
function handleBulkCopyFavoriteSelection() {
@@ -3,32 +3,34 @@
<div class="x-friend-item">
<template v-if="isLocalFavorite ? favorite.name : favorite.ref">
<div class="avatar">
<img v-lazy="smallThumbnail" />
<img :src="smallThumbnail" loading="lazy" />
</div>
<div class="detail">
<span class="name" v-text="localFavFakeRef.name"></span>
<span class="extra" v-text="localFavFakeRef.authorName"></span>
</div>
<template v-if="editFavoritesMode">
<el-dropdown trigger="click" size="mini" style="margin-left: 5px" @click.native.stop>
<el-tooltip placement="top" :content="tooltipContent" :disabled="hideTooltips">
<el-button type="default" icon="el-icon-back" size="mini" circle></el-button>
</el-tooltip>
<el-dropdown-menu slot="dropdown">
<template
v-for="groupAPI in favoriteAvatarGroups"
v-if="isLocalFavorite || groupAPI.name !== group.name">
<el-dropdown-item
:key="groupAPI.name"
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click.native="handleDropdownItemClick(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
<el-dropdown trigger="click" size="small" style="margin-left: 5px">
<div>
<el-tooltip placement="top" :content="tooltipContent">
<el-button type="default" :icon="Back" size="small" circle></el-button>
</el-tooltip>
</div>
<template #dropdown>
<el-dropdown-menu>
<template v-for="groupAPI in favoriteAvatarGroups" :key="groupAPI.name">
<el-dropdown-item
v-if="isLocalFavorite || groupAPI.name !== group.name"
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click="handleDropdownItemClick(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button v-if="!isLocalFavorite" type="text" size="mini" style="margin-left: 5px" @click.stop>
<el-button v-if="!isLocalFavorite" type="text" size="small" style="margin-left: 5px" @click.stop>
<el-checkbox v-model="isSelected"></el-checkbox>
</el-button>
</template>
@@ -37,79 +39,68 @@
v-if="favorite.deleted"
placement="left"
:content="t('view.favorite.unavailable_tooltip')">
<i class="el-icon-warning" style="color: #f56c6c; margin-left: 5px"></i>
<el-icon><Warning /></el-icon>
</el-tooltip>
<el-tooltip
v-if="favorite.ref.releaseStatus === 'private'"
placement="left"
:content="t('view.favorite.private')">
<i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
<el-icon><Warning /></el-icon>
</el-tooltip>
<el-tooltip
v-if="favorite.ref.releaseStatus !== 'private' && !favorite.deleted"
placement="left"
:content="t('view.favorite.select_avatar_tooltip')"
:disabled="hideTooltips">
:content="t('view.favorite.select_avatar_tooltip')">
<el-button
:disabled="currentUser.currentAvatar === favorite.id"
size="mini"
icon="el-icon-check"
size="small"
:icon="Check"
circle
style="margin-left: 5px"
@click.stop="selectAvatarWithConfirmation(favorite.id)"></el-button>
</el-tooltip>
<el-tooltip
placement="right"
:content="t('view.favorite.unfavorite_tooltip')"
:disabled="hideTooltips">
<el-tooltip placement="right" :content="t('view.favorite.unfavorite_tooltip')">
<el-button
v-if="shiftHeld"
size="mini"
icon="el-icon-close"
size="small"
:icon="Close"
circle
style="color: #f56c6c; margin-left: 5px"
@click.stop="deleteFavorite(favorite.id)"></el-button>
<el-button
v-else
type="default"
icon="el-icon-star-on"
size="mini"
:icon="Star"
size="small"
circle
style="margin-left: 5px"
@click.stop="showFavoriteDialog('avatar', favorite.id)"></el-button>
</el-tooltip>
</template>
<template v-else>
<el-tooltip
placement="left"
:content="t('view.favorite.select_avatar_tooltip')"
:disabled="hideTooltips">
<el-tooltip placement="left" :content="t('view.favorite.select_avatar_tooltip')">
<el-button
:disabled="currentUser.currentAvatar === favorite.id"
size="mini"
size="small"
circle
style="margin-left: 5px"
icon="el-icon-check"
:icon="Check"
@click.stop="selectAvatarWithConfirmation(favorite.id)" />
</el-tooltip>
</template>
<el-tooltip
v-if="isLocalFavorite"
placement="right"
:content="t('view.favorite.unfavorite_tooltip')"
:disabled="hideTooltips">
<el-tooltip v-if="isLocalFavorite" placement="right" :content="t('view.favorite.unfavorite_tooltip')">
<el-button
v-if="shiftHeld"
size="mini"
icon="el-icon-close"
size="small"
:icon="Close"
circle
style="color: #f56c6c; margin-left: 5px"
@click.stop="removeLocalAvatarFavorite(favorite.id, favoriteGroupName)" />
<el-button
v-else
type="default"
icon="el-icon-star-on"
size="mini"
:icon="Star"
size="small"
circle
style="margin-left: 5px"
@click.stop="showFavoriteDialog('avatar', favorite.id)"
@@ -123,15 +114,15 @@
<el-button
v-if="isLocalFavorite"
type="text"
icon="el-icon-close"
size="mini"
:icon="Close"
size="small"
style="margin-left: 5px"
@click.stop="removeLocalAvatarFavorite(favorite.id, favoriteGroupName)"></el-button>
<el-button
v-else
type="text"
icon="el-icon-close"
size="mini"
:icon="Close"
size="small"
style="margin-left: 5px"
@click.stop="deleteFavorite(favorite.id)"></el-button>
</template>
@@ -140,18 +131,13 @@
</template>
<script setup>
import { ElMessage } from 'element-plus';
import { Warning, Back, Check, Close, Star } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import { favoriteRequest } from '../../../api';
import { $app } from '../../../app';
import {
useAppearanceSettingsStore,
useAvatarStore,
useFavoriteStore,
useUiStore,
useUserStore
} from '../../../stores';
import { useAvatarStore, useFavoriteStore, useUiStore, useUserStore } from '../../../stores';
const props = defineProps({
favorite: Object,
@@ -163,7 +149,6 @@
const { t } = useI18n();
const { hideTooltips } = storeToRefs(useAppearanceSettingsStore());
const { favoriteAvatarGroups } = storeToRefs(useFavoriteStore());
const { removeLocalAvatarFavorite, showFavoriteDialog } = useFavoriteStore();
const { selectAvatarWithConfirmation } = useAvatarStore();
@@ -211,7 +196,7 @@
tags: groupAPI.name
})
.then((args) => {
$app.$message({
ElMessage({
message: 'Avatar added to favorites',
type: 'success'
});
@@ -2,38 +2,38 @@
<div @click="$emit('click')">
<div class="x-friend-item">
<div class="avatar">
<img v-lazy="smallThumbnail" />
<img :src="smallThumbnail" loading="lazy" />
</div>
<div class="detail">
<span class="name" v-text="favorite.name"></span>
<span class="extra" v-text="favorite.authorName"></span>
</div>
<el-tooltip placement="left" :content="t('view.favorite.select_avatar_tooltip')" :disabled="hideTooltips">
<el-tooltip placement="left" :content="t('view.favorite.select_avatar_tooltip')">
<el-button
:disabled="currentUser.currentAvatar === favorite.id"
size="mini"
icon="el-icon-check"
size="small"
:icon="Check"
circle
style="margin-left: 5px"
@click.stop="selectAvatarWithConfirmation(favorite.id)"></el-button>
</el-tooltip>
<template v-if="cachedFavoritesByObjectId.has(favorite.id)">
<el-tooltip placement="right" content="Favorite" :disabled="hideTooltips">
<el-tooltip placement="right" content="Favorite">
<el-button
type="default"
icon="el-icon-star-on"
size="mini"
:icon="Star"
size="small"
circle
style="margin-left: 5px"
@click.stop="showFavoriteDialog('avatar', favorite.id)"></el-button>
</el-tooltip>
</template>
<template v-else>
<el-tooltip placement="right" content="Favorite" :disabled="hideTooltips">
<el-tooltip placement="right" content="Favorite">
<el-button
type="default"
icon="el-icon-star-off"
size="mini"
:icon="StarFilled"
size="small"
circle
style="margin-left: 5px"
@click.stop="showFavoriteDialog('avatar', favorite.id)"></el-button>
@@ -44,14 +44,14 @@
</template>
<script setup>
import { Check, Star, StarFilled } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { useAppearanceSettingsStore, useAvatarStore, useFavoriteStore, useUserStore } from '../../../stores';
import { useI18n } from 'vue-i18n';
import { useAvatarStore, useFavoriteStore, useUserStore } from '../../../stores';
const { t } = useI18n();
const { hideTooltips } = storeToRefs(useAppearanceSettingsStore());
const { cachedFavoritesByObjectId } = storeToRefs(useFavoriteStore());
const { showFavoriteDialog } = useFavoriteStore();
const { selectAvatarWithConfirmation } = useAvatarStore();
@@ -64,6 +64,8 @@
}
});
defineEmits(['click']);
const smallThumbnail = computed(() => {
return props.favorite.thumbnailImageUrl.replace('256', '128') || props.favorite.thumbnailImageUrl;
});
@@ -24,7 +24,7 @@
<el-input
v-model="avatarFavoriteSearch"
clearable
size="mini"
size="small"
:placeholder="t('view.favorite.avatars.search')"
style="width: 200px"
@input="searchAvatarFavorites" />
@@ -39,7 +39,7 @@
<div class="x-friend-item">
<template v-if="favorite.name">
<div class="avatar">
<img v-lazy="favorite.thumbnailImageUrl" />
<img :src="favorite.thumbnailImageUrl" loading="lazy" />
</div>
<div class="detail">
<span class="name" v-text="favorite.name" />
@@ -60,23 +60,23 @@
</span>
<el-collapse style="border: 0">
<el-collapse-item v-for="group in favoriteAvatarGroups" :key="group.name">
<template slot="title">
<template #title>
<span style="font-weight: bold; font-size: 14px; margin-left: 10px" v-text="group.displayName" />
<span style="color: #909399; font-size: 12px; margin-left: 10px">
{{ group.count }}/{{ group.capacity }}
</span>
<el-tooltip placement="top" :content="t('view.favorite.rename_tooltip')" :disabled="hideTooltips">
<el-tooltip placement="top" :content="t('view.favorite.rename_tooltip')">
<el-button
size="mini"
icon="el-icon-edit"
size="small"
:icon="Edit"
circle
style="margin-left: 10px"
@click.stop="changeFavoriteGroupName(group)" />
</el-tooltip>
<el-tooltip placement="right" :content="t('view.favorite.clear_tooltip')" :disabled="hideTooltips">
<el-tooltip placement="right" :content="t('view.favorite.clear_tooltip')">
<el-button
size="mini"
icon="el-icon-delete"
size="small"
:icon="Delete"
circle
style="margin-left: 5px"
@click.stop="clearFavoriteGroup(group)" />
@@ -88,7 +88,6 @@
:key="favorite.id"
:favorite="favorite"
:group="group"
:hide-tooltips="hideTooltips"
:edit-favorites-mode="editFavoritesMode"
style="display: inline-block; width: 300px; margin-right: 15px"
@handle-select="favorite.$selected = $event"
@@ -108,15 +107,15 @@
</div>
</el-collapse-item>
<el-collapse-item>
<template slot="title">
<template #title>
<span style="font-weight: bold; font-size: 14px; margin-left: 10px">Local History</span>
<span style="color: #909399; font-size: 12px; margin-left: 10px"
>{{ avatarHistoryArray.length }}/100</span
>
<el-tooltip placement="right" content="Clear" :disabled="hideTooltips">
<el-tooltip placement="right" content="Clear">
<el-button
size="mini"
icon="el-icon-delete"
size="small"
:icon="Delete"
circle
style="margin-left: 5px"
@click.stop="promptClearAvatarHistory"></el-button>
@@ -128,7 +127,6 @@
:key="favorite.id"
style="display: inline-block; width: 300px; margin-right: 15px"
:favorite="favorite"
:hide-tooltips="hideTooltips"
@click="showAvatarDialog(favorite.id)" />
</div>
<div
@@ -157,30 +155,27 @@
{{ t('view.favorite.avatars.refresh') }}
</el-button>
<el-button v-else size="small" style="margin-left: 5px" @click="refreshingLocalFavorites = false">
<i class="el-icon-loading" style="margin-right: 5px"></i>
<el-icon class="is-loading"><Loading /></el-icon>
<span>{{ t('view.favorite.avatars.cancel_refresh') }}</span>
</el-button>
<el-collapse-item
v-for="group in localAvatarFavoriteGroups"
v-if="localAvatarFavorites[group]"
:key="group">
<template slot="title">
<el-collapse-item v-for="group in localAvatarFavoriteGroups" :key="group">
<template #title v-if="localAvatarFavorites[group]">
<span :style="{ fontWeight: 'bold', fontSize: '14px', marginLeft: '10px' }">{{ group }}</span>
<span :style="{ color: '#909399', fontSize: '12px', marginLeft: '10px' }">{{
getLocalAvatarFavoriteGroupLength(group)
}}</span>
<el-tooltip placement="top" :content="t('view.favorite.rename_tooltip')" :disabled="hideTooltips">
<el-tooltip placement="top" :content="t('view.favorite.rename_tooltip')">
<el-button
size="mini"
icon="el-icon-edit"
size="small"
:icon="Edit"
circle
:style="{ marginLeft: '5px' }"
@click.stop="promptLocalAvatarFavoriteGroupRename(group)"></el-button>
</el-tooltip>
<el-tooltip placement="right" :content="t('view.favorite.delete_tooltip')" :disabled="hideTooltips">
<el-tooltip placement="right" :content="t('view.favorite.delete_tooltip')">
<el-button
size="mini"
icon="el-icon-delete"
size="small"
:icon="Delete"
circle
:style="{ marginLeft: '5px' }"
@click.stop="promptLocalAvatarFavoriteGroupDelete(group)"></el-button>
@@ -194,7 +189,6 @@
:style="{ display: 'inline-block', width: '300px', marginRight: '15px' }"
:favorite="favorite"
:group="group"
:hide-tooltips="hideTooltips"
:edit-favorites-mode="editFavoritesMode"
@handle-select="favorite.$selected = $event"
@click="showAvatarDialog(favorite.id)" />
@@ -213,14 +207,17 @@
</div>
</el-collapse-item>
</el-collapse>
<AvatarExportDialog :avatar-export-dialog-visible.sync="avatarExportDialogVisible" />
<AvatarExportDialog v-model:avatarExportDialogVisible="avatarExportDialogVisible" />
</div>
</template>
<script setup>
import { ref, computed, getCurrentInstance } from 'vue';
import { Loading, Edit, Delete } from '@element-plus/icons-vue';
import { ElMessageBox } from 'element-plus';
import { ref, computed } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import { favoriteRequest } from '../../../api';
import { useAppearanceSettingsStore, useAvatarStore, useFavoriteStore, useUserStore } from '../../../stores';
import AvatarExportDialog from '../dialogs/AvatarExportDialog.vue';
@@ -238,10 +235,9 @@
}
});
const { proxy } = getCurrentInstance();
const emit = defineEmits(['change-favorite-group-name', 'refresh-local-avatar-favorites']);
const { hideTooltips, sortFavorites } = storeToRefs(useAppearanceSettingsStore());
const { sortFavorites } = storeToRefs(useAppearanceSettingsStore());
const { setSortFavorites } = useAppearanceSettingsStore();
const { favoriteAvatars, favoriteAvatarGroups, localAvatarFavorites, localAvatarFavoriteGroups } =
storeToRefs(useFavoriteStore());
@@ -340,19 +336,20 @@
}
function clearFavoriteGroup(ctx) {
proxy.$confirm('Continue? Clear Group', 'Confirm', {
ElMessageBox.confirm('Continue? Clear Group', 'Confirm', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'info',
callback: (action) => {
type: 'info'
})
.then((action) => {
if (action === 'confirm') {
favoriteRequest.clearFavoriteGroup({
type: ctx.type,
group: ctx.name
});
}
}
});
})
.catch(() => {});
}
function showAvatarExportDialog() {
@@ -364,18 +361,23 @@
}
function promptNewLocalAvatarFavoriteGroup() {
proxy.$prompt(t('prompt.new_local_favorite_group.description'), t('prompt.new_local_favorite_group.header'), {
distinguishCancelAndClose: true,
confirmButtonText: t('prompt.new_local_favorite_group.ok'),
cancelButtonText: t('prompt.new_local_favorite_group.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.new_local_favorite_group.input_error'),
callback: (action, instance) => {
if (action === 'confirm' && instance.inputValue) {
newLocalAvatarFavoriteGroup(instance.inputValue);
}
ElMessageBox.prompt(
t('prompt.new_local_favorite_group.description'),
t('prompt.new_local_favorite_group.header'),
{
distinguishCancelAndClose: true,
confirmButtonText: t('prompt.new_local_favorite_group.ok'),
cancelButtonText: t('prompt.new_local_favorite_group.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.new_local_favorite_group.input_error')
}
});
)
.then(({ value }) => {
if (value) {
newLocalAvatarFavoriteGroup(value);
}
})
.catch(() => {});
}
function refreshLocalAvatarFavorites() {
@@ -383,7 +385,7 @@
}
function promptLocalAvatarFavoriteGroupRename(group) {
proxy.$prompt(
ElMessageBox.prompt(
t('prompt.local_favorite_group_rename.description'),
t('prompt.local_favorite_group_rename.header'),
{
@@ -392,26 +394,28 @@
cancelButtonText: t('prompt.local_favorite_group_rename.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.local_favorite_group_rename.input_error'),
inputValue: group,
callback: (action, instance) => {
if (action === 'confirm' && instance.inputValue) {
renameLocalAvatarFavoriteGroup(instance.inputValue, group);
}
}
inputValue: group
}
);
)
.then(({ value }) => {
if (value) {
renameLocalAvatarFavoriteGroup(value, group);
}
})
.catch(() => {});
}
function promptLocalAvatarFavoriteGroupDelete(group) {
proxy.$confirm(`Delete Group? ${group}`, 'Confirm', {
ElMessageBox.confirm(`Delete Group? ${group}`, 'Confirm', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'info',
callback: (action) => {
type: 'info'
})
.then((action) => {
if (action === 'confirm') {
deleteLocalAvatarFavoriteGroup(group);
}
}
});
})
.catch(() => {});
}
</script>
@@ -3,7 +3,7 @@
<div class="x-friend-item">
<template v-if="favorite.ref">
<div class="avatar" :class="userStatusClass(favorite.ref)">
<img v-lazy="userImage(favorite.ref, true)" />
<img :src="userImage(favorite.ref, true)" loading="lazy" />
</div>
<div class="detail">
<span
@@ -19,47 +19,44 @@
<span v-else v-text="favorite.ref.statusDescription"></span>
</div>
<template v-if="editFavoritesMode">
<el-dropdown trigger="click" size="mini" style="margin-left: 5px" @click.native.stop>
<el-tooltip
placement="left"
:content="$t('view.favorite.move_tooltip')"
:disabled="hideTooltips">
<el-button type="default" icon="el-icon-back" size="mini" circle></el-button>
</el-tooltip>
<el-dropdown-menu slot="dropdown">
<template v-for="groupAPI in favoriteFriendGroups">
<el-dropdown-item
v-if="groupAPI.name !== group.name"
:key="groupAPI.name"
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click.native="moveFavorite(favorite.ref, groupAPI, 'friend')">
{{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
<el-dropdown trigger="click" size="small" style="margin-left: 5px">
<div>
<el-tooltip placement="left" :content="t('view.favorite.move_tooltip')">
<el-button type="default" :icon="Back" size="small" circle></el-button>
</el-tooltip>
</div>
<template #dropdown>
<el-dropdown-menu>
<template v-for="groupAPI in favoriteFriendGroups" :key="groupAPI.name">
<el-dropdown-item
v-if="groupAPI.name !== group.name"
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click="moveFavorite(favorite.ref, groupAPI, 'friend')">
{{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button type="text" size="mini" style="margin-left: 5px" @click.stop>
<el-button type="text" size="small" style="margin-left: 5px" @click.stop>
<el-checkbox v-model="favorite.$selected"></el-checkbox>
</el-button>
</template>
<template v-else>
<el-tooltip
placement="right"
:content="$t('view.favorite.unfavorite_tooltip')"
:disabled="hideTooltips">
<el-tooltip placement="right" :content="t('view.favorite.unfavorite_tooltip')">
<el-button
v-if="shiftHeld"
size="mini"
icon="el-icon-close"
size="small"
:icon="Close"
circle
style="color: #f56c6c; margin-left: 5px"
@click.stop="deleteFavorite(favorite.id)"></el-button>
<el-button
v-else
type="default"
icon="el-icon-star-on"
size="mini"
:icon="Star"
size="small"
circle
style="margin-left: 5px"
@click.stop="showFavoriteDialog('friend', favorite.id)"></el-button>
@@ -73,8 +70,8 @@
</div>
<el-button
type="text"
icon="el-icon-close"
size="mini"
:icon="Close"
size="small"
style="margin-left: 5px"
@click.stop="deleteFavorite(favorite.id)"></el-button>
</template>
@@ -83,10 +80,12 @@
</template>
<script setup>
import { Back, Close, Star } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { favoriteRequest } from '../../../api';
import { userImage, userStatusClass } from '../../../shared/utils';
import { useAppearanceSettingsStore, useFavoriteStore, useUiStore } from '../../../stores';
import { useFavoriteStore, useUiStore } from '../../../stores';
defineProps({
favorite: { type: Object, required: true },
@@ -96,10 +95,10 @@
defineEmits(['click']);
const { hideTooltips } = storeToRefs(useAppearanceSettingsStore());
const { favoriteFriendGroups } = storeToRefs(useFavoriteStore());
const { showFavoriteDialog } = useFavoriteStore();
const { shiftHeld } = storeToRefs(useUiStore());
const { t } = useI18n();
function moveFavorite(ref, group, type) {
favoriteRequest.deleteFavorite({ objectId: ref.id }).then(() => {
@@ -2,45 +2,45 @@
<div>
<div style="display: flex; align-items: center; justify-content: space-between">
<div>
<el-button size="small" @click="showFriendExportDialog">{{ $t('view.favorite.export') }}</el-button>
<el-button size="small" @click="showFriendExportDialog">{{ t('view.favorite.export') }}</el-button>
<el-button size="small" style="margin-left: 5px" @click="showFriendImportDialog">{{
$t('view.favorite.import')
t('view.favorite.import')
}}</el-button>
</div>
<div style="display: flex; align-items: center; font-size: 13px; margin-right: 10px">
<span class="name" style="margin-right: 5px; line-height: 10px">{{ $t('view.favorite.sort_by') }}</span>
<span class="name" style="margin-right: 5px; line-height: 10px">{{ t('view.favorite.sort_by') }}</span>
<el-radio-group v-model="sortFav" @change="saveSortFavoritesOption">
<el-radio :label="false">{{
$t('view.settings.appearance.appearance.sort_favorite_by_name')
t('view.settings.appearance.appearance.sort_favorite_by_name')
}}</el-radio>
<el-radio :label="true">{{
$t('view.settings.appearance.appearance.sort_favorite_by_date')
t('view.settings.appearance.appearance.sort_favorite_by_date')
}}</el-radio>
</el-radio-group>
</div>
</div>
<span style="display: block; margin-top: 30px">{{ $t('view.favorite.avatars.vrchat_favorites') }}</span>
<span style="display: block; margin-top: 30px">{{ t('view.favorite.avatars.vrchat_favorites') }}</span>
<el-collapse style="border: 0">
<el-collapse-item v-for="group in favoriteFriendGroups" :key="group.name">
<template slot="title">
<template #title>
<span
style="font-weight: bold; font-size: 14px; margin-left: 10px"
v-text="group.displayName"></span>
<span style="color: #909399; font-size: 12px; margin-left: 10px"
>{{ group.count }}/{{ group.capacity }}</span
>
<el-tooltip placement="top" :content="$t('view.favorite.rename_tooltip')" :disabled="hideTooltips">
<el-tooltip placement="top" :content="t('view.favorite.rename_tooltip')">
<el-button
size="mini"
icon="el-icon-edit"
size="small"
:icon="Edit"
circle
style="margin-left: 10px"
@click.stop="changeFavoriteGroupName(group)"></el-button>
</el-tooltip>
<el-tooltip placement="right" :content="$t('view.favorite.clear_tooltip')" :disabled="hideTooltips">
<el-tooltip placement="right" :content="t('view.favorite.clear_tooltip')">
<el-button
size="mini"
icon="el-icon-delete"
size="small"
:icon="Delete"
circle
style="margin-left: 5px"
@click.stop="clearFavoriteGroup(group)"></el-button>
@@ -70,13 +70,17 @@
</div>
</el-collapse-item>
</el-collapse>
<FriendExportDialog :friend-export-dialog-visible.sync="friendExportDialogVisible" />
<FriendExportDialog v-model:friendExportDialogVisible="friendExportDialogVisible" />
</div>
</template>
<script setup>
import { ref, getCurrentInstance, computed } from 'vue';
import { Edit, Delete } from '@element-plus/icons-vue';
import { ElMessageBox } from 'element-plus';
import { ref, computed } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { favoriteRequest } from '../../../api';
import { useAppearanceSettingsStore, useFavoriteStore, useUserStore } from '../../../stores';
import FriendExportDialog from '../dialogs/FriendExportDialog.vue';
@@ -91,13 +95,12 @@
const emit = defineEmits(['change-favorite-group-name']);
const { proxy } = getCurrentInstance();
const { hideTooltips, sortFavorites } = storeToRefs(useAppearanceSettingsStore());
const { sortFavorites } = storeToRefs(useAppearanceSettingsStore());
const { setSortFavorites } = useAppearanceSettingsStore();
const { showUserDialog } = useUserStore();
const { favoriteFriendGroups, groupedByGroupKeyFavoriteFriends } = storeToRefs(useFavoriteStore());
const { showFriendImportDialog, saveSortFavoritesOption } = useFavoriteStore();
const { t } = useI18n();
const friendExportDialogVisible = ref(false);
@@ -115,19 +118,20 @@
}
function clearFavoriteGroup(ctx) {
proxy.$confirm('Continue? Clear Group', 'Confirm', {
ElMessageBox.confirm('Continue? Clear Group', 'Confirm', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'info',
callback: (action) => {
type: 'info'
})
.then((action) => {
if (action === 'confirm') {
favoriteRequest.clearFavoriteGroup({
type: ctx.type,
group: ctx.name
});
}
}
});
})
.catch(() => {});
}
function changeFavoriteGroupName(group) {
@@ -1,57 +1,60 @@
<template>
<div @click="$emit('click')" :style="{ display: 'inline-block', width: '300px', marginRight: '15px' }">
<div class="fav-world-item" @click="$emit('click')">
<div class="x-friend-item">
<template v-if="isLocalFavorite ? favorite.name : favorite.ref">
<div class="avatar">
<img v-lazy="smallThumbnail" />
<div class="avatar" v-once>
<img :src="smallThumbnail" loading="lazy" decoding="async" fetchpriority="low" />
</div>
<div class="detail">
<span class="name" v-once>{{ localFavFakeRef.name }}</span>
<span v-if="localFavFakeRef.occupants" class="extra" v-once
>{{ localFavFakeRef.authorName }} ({{ localFavFakeRef.occupants }})</span
>
<span v-else class="extra" v-once>{{ localFavFakeRef.authorName }}</span>
<div class="detail" v-once>
<span class="name">{{ localFavFakeRef.name }}</span>
<span v-if="localFavFakeRef.occupants" class="extra">
{{ localFavFakeRef.authorName }} ({{ localFavFakeRef.occupants }})
</span>
<span v-else class="extra">{{ localFavFakeRef.authorName }}</span>
</div>
<template v-if="editFavoritesMode">
<el-dropdown trigger="click" size="mini" style="margin-left: 5px" @click.native.stop>
<el-tooltip
placement="left"
:content="$t(localFavFakeRef ? 'view.favorite.copy_tooltip' : 'view.favorite.move_tooltip')"
:disabled="hideTooltips">
<el-button type="default" icon="el-icon-back" size="mini" circle></el-button>
</el-tooltip>
<el-dropdown-menu slot="dropdown">
<template v-for="groupAPI in favoriteWorldGroups">
<el-dropdown-item
v-if="isLocalFavorite || groupAPI.name !== group.name"
:key="groupAPI.name"
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click.native="handleDropdownItemClick(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
<el-button v-if="!isLocalFavorite" type="text" size="mini" @click.stop style="margin-left: 5px">
<el-checkbox v-model="isSelected"></el-checkbox>
</el-button>
<el-dropdown trigger="click" size="small" style="margin-left: 5px">
<div>
<el-tooltip
placement="left"
:content="
t(localFavFakeRef ? 'view.favorite.copy_tooltip' : 'view.favorite.move_tooltip')
">
<el-button type="default" :icon="Back" size="small" circle></el-button>
</el-tooltip>
</div>
<template #dropdown>
<el-dropdown-menu>
<template v-for="groupAPI in favoriteWorldGroups" :key="groupAPI.name">
<el-dropdown-item
v-if="isLocalFavorite || groupAPI.name !== group.name"
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click="handleDropdownItemClick(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button v-if="!isLocalFavorite" type="text" size="small" @click.stop style="margin-left: 5px">
<el-checkbox v-model="isSelected"></el-checkbox>
</el-button>
</template>
<template v-else>
<el-tooltip
v-if="!isLocalFavorite && favorite.deleted"
placement="left"
:content="$t('view.favorite.unavailable_tooltip')">
<i class="el-icon-warning" style="color: #f56c6c; margin-left: 5px"></i>
:content="t('view.favorite.unavailable_tooltip')">
<el-icon><Warning /></el-icon>
</el-tooltip>
<el-tooltip
v-if="!isLocalFavorite && favorite.ref.releaseStatus === 'private'"
placement="left"
:content="$t('view.favorite.private')">
<i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
:content="t('view.favorite.private')">
<el-icon><Warning /></el-icon>
</el-tooltip>
<el-tooltip placement="left" :disabled="hideTooltips">
<el-tooltip placement="left">
<template #content>
{{
canOpenInstanceInGame()
@@ -60,8 +63,8 @@
}}
</template>
<el-button
size="mini"
icon="el-icon-message"
size="small"
:icon="Message"
style="margin-left: 5px"
@click.stop="newInstanceSelfInvite(favorite.id)"
circle></el-button>
@@ -69,41 +72,36 @@
<el-tooltip
v-if="!isLocalFavorite"
placement="right"
:content="$t('view.favorite.unfavorite_tooltip')"
:disabled="hideTooltips">
:content="t('view.favorite.unfavorite_tooltip')">
<el-button
v-if="shiftHeld"
size="mini"
icon="el-icon-close"
size="small"
:icon="Close"
circle
style="color: #f56c6c; margin-left: 5px"
@click.stop="deleteFavorite(favorite.id)"></el-button>
<el-button
v-else
icon="el-icon-star-on"
size="mini"
:icon="Star"
size="small"
circle
style="margin-left: 5px"
type="default"
@click.stop="showFavoriteDialog('world', favorite.id)"></el-button>
</el-tooltip>
</template>
<el-tooltip
v-if="isLocalFavorite"
placement="right"
:content="$t('view.favorite.unfavorite_tooltip')"
:disabled="hideTooltips">
<el-tooltip v-if="isLocalFavorite" placement="right" :content="t('view.favorite.unfavorite_tooltip')">
<el-button
v-if="shiftHeld"
size="mini"
icon="el-icon-close"
size="small"
:icon="Close"
circle
style="color: #f56c6c; margin-left: 5px"
@click.stop="$emit('remove-local-world-favorite', favorite.id, group)"></el-button>
<el-button
v-else
icon="el-icon-star-on"
size="mini"
:icon="Star"
size="small"
circle
style="margin-left: 5px"
type="default"
@@ -112,18 +110,18 @@
</template>
<template v-else>
<div class="avatar"></div>
<div class="detail">
<span v-once>{{ favorite.name || favorite.id }}</span>
<div class="detail" v-once>
<span>{{ favorite.name || favorite.id }}</span>
<el-tooltip
v-if="!isLocalFavorite && favorite.deleted"
placement="left"
:content="$t('view.favorite.unavailable_tooltip')">
<i class="el-icon-warning" style="color: #f56c6c; margin-left: 5px"></i>
:content="t('view.favorite.unavailable_tooltip')">
<el-icon><Warning /></el-icon>
</el-tooltip>
<el-button
type="text"
icon="el-icon-close"
size="mini"
:icon="Close"
size="small"
style="margin-left: 5px"
@click.stop="handleDeleteFavorite"></el-button>
</div>
@@ -133,16 +131,13 @@
</template>
<script setup>
import { ElMessage } from 'element-plus';
import { Warning, Back, Message, Close, Star } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { computed, getCurrentInstance } from 'vue';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { favoriteRequest } from '../../../api';
import {
useAppearanceSettingsStore,
useFavoriteStore,
useInviteStore,
useUiStore,
useGameStore
} from '../../../stores';
import { useFavoriteStore, useInviteStore, useUiStore } from '../../../stores';
const props = defineProps({
group: [Object, String],
@@ -152,14 +147,11 @@
});
const emit = defineEmits(['handle-select', 'remove-local-world-favorite', 'click']);
const { proxy } = getCurrentInstance();
const { hideTooltips } = storeToRefs(useAppearanceSettingsStore());
const { favoriteWorldGroups } = storeToRefs(useFavoriteStore());
const { showFavoriteDialog } = useFavoriteStore();
const { newInstanceSelfInvite } = useInviteStore();
const { shiftHeld } = storeToRefs(useUiStore());
const { isGameRunning } = storeToRefs(useGameStore());
const { t } = useI18n();
const { canOpenInstanceInGame } = useInviteStore();
const isSelected = computed({
@@ -213,9 +205,17 @@
})
.then((args) => {
if (message) {
proxy.$message({ message: 'World added to favorites', type: 'success' });
ElMessage({ message: 'World added to favorites', type: 'success' });
}
return args;
});
}
</script>
<style scoped>
.fav-world-item {
display: inline-block;
width: 300px;
margin-right: 15px;
}
</style>
@@ -2,26 +2,26 @@
<div>
<div style="display: flex; align-items: center; justify-content: space-between">
<div>
<el-button size="small" @click="showExportDialog">{{ $t('view.favorite.export') }}</el-button>
<el-button size="small" @click="showExportDialog">{{ t('view.favorite.export') }}</el-button>
<el-button size="small" style="margin-left: 5px" @click="showWorldImportDialog">{{
$t('view.favorite.import')
t('view.favorite.import')
}}</el-button>
</div>
<div style="display: flex; align-items: center; font-size: 13px; margin-right: 10px">
<span class="name" style="margin-right: 5px; line-height: 10px">{{ $t('view.favorite.sort_by') }}</span>
<span class="name" style="margin-right: 5px; line-height: 10px">{{ t('view.favorite.sort_by') }}</span>
<el-radio-group v-model="sortFav" style="margin-right: 12px" @change="saveSortFavoritesOption">
<el-radio :label="false">{{
$t('view.settings.appearance.appearance.sort_favorite_by_name')
t('view.settings.appearance.appearance.sort_favorite_by_name')
}}</el-radio>
<el-radio :label="true">{{
$t('view.settings.appearance.appearance.sort_favorite_by_date')
t('view.settings.appearance.appearance.sort_favorite_by_date')
}}</el-radio>
</el-radio-group>
<el-input
v-model="worldFavoriteSearch"
clearable
size="mini"
:placeholder="$t('view.favorite.worlds.search')"
size="small"
:placeholder="t('view.favorite.worlds.search')"
style="width: 200px"
@input="searchWorldFavorites" />
</div>
@@ -35,7 +35,7 @@
<div class="x-friend-item">
<template v-if="favorite.name">
<div class="avatar">
<img v-lazy="favorite.thumbnailImageUrl" />
<img :src="favorite.thumbnailImageUrl" loading="lazy" />
</div>
<div class="detail">
<span class="name" v-text="favorite.name"></span>
@@ -54,64 +54,58 @@
</div>
</div>
</div>
<span style="display: block; margin-top: 20px">{{ $t('view.favorite.worlds.vrchat_favorites') }}</span>
<span style="display: block; margin-top: 20px">{{ t('view.favorite.worlds.vrchat_favorites') }}</span>
<el-collapse style="border: 0">
<el-collapse-item v-for="group in favoriteWorldGroups" :key="group.name">
<template slot="title">
<template #title>
<div style="display: flex; align-items: center">
<span
style="font-weight: bold; font-size: 14px; margin-left: 10px"
v-text="group.displayName" />
<el-tag
style="margin: 1px 0 0 5px"
size="mini"
size="small"
:type="userFavoriteWorldsStatusForFavTab(group.visibility)"
effect="plain"
>{{ group.visibility.charAt(0).toUpperCase() + group.visibility.slice(1) }}</el-tag
>
<span style="color: #909399; font-size: 12px; margin-left: 10px"
>{{ group.count }}/{{ group.capacity }}</span
>
<el-dropdown trigger="click" size="mini" style="margin-left: 10px" @click.native.stop>
<el-tooltip
placement="top"
:content="$t('view.favorite.visibility_tooltip')"
:disabled="hideTooltips">
<el-button type="default" icon="el-icon-view" size="mini" circle />
</el-tooltip>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="visibility in worldGroupVisibilityOptions"
v-if="group.visibility !== visibility"
:key="visibility"
style="display: block; margin: 10px 0"
@click.native="changeWorldGroupVisibility(group.name, visibility)"
>{{ visibility.charAt(0).toUpperCase() + visibility.slice(1) }}</el-dropdown-item
>
</el-dropdown-menu>
<el-tooltip
placement="top"
:content="$t('view.favorite.rename_tooltip')"
:disabled="hideTooltips">
<el-button
size="mini"
icon="el-icon-edit"
circle
style="margin-left: 5px"
@click.stop="changeFavoriteGroupName(group)" />
</el-tooltip>
<el-tooltip
placement="right"
:content="$t('view.favorite.clear_tooltip')"
:disabled="hideTooltips">
<el-button
size="mini"
icon="el-icon-delete"
circle
style="margin-left: 5px"
@click.stop="clearFavoriteGroup(group)" />
</el-tooltip>
</el-dropdown>
><el-tooltip placement="top" :content="t('view.favorite.visibility_tooltip')">
<el-dropdown trigger="click" size="small" style="margin-left: 10px">
<el-button type="default" :icon="View" size="small" circle @click.stop />
<template #dropdown>
<el-dropdown-menu>
<template v-for="visibility in worldGroupVisibilityOptions" :key="visibility">
<el-dropdown-item
v-if="group.visibility !== visibility"
style="display: block; margin: 10px 0"
@click="changeWorldGroupVisibility(group.name, visibility)"
>{{
visibility.charAt(0).toUpperCase() + visibility.slice(1)
}}</el-dropdown-item
>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-tooltip>
<el-tooltip placement="top" :content="t('view.favorite.rename_tooltip')">
<el-button
size="small"
:icon="Edit"
circle
style="margin-left: 5px"
@click.stop="changeFavoriteGroupName(group)" />
</el-tooltip>
<el-tooltip placement="right" :content="t('view.favorite.clear_tooltip')">
<el-button
size="small"
:icon="Delete"
circle
style="margin-left: 5px"
@click.stop="clearFavoriteGroup(group)" />
</el-tooltip>
</div>
</template>
<div v-if="group.count" class="x-friend-list" style="margin-top: 10px">
@@ -121,7 +115,6 @@
:group="group"
:favorite="favorite"
:edit-favorites-mode="editFavoritesMode"
:hide-tooltips="hideTooltips"
@click="showWorldDialog(favorite.id)"
@handle-select="favorite.$selected = $event" />
</div>
@@ -139,44 +132,41 @@
</div>
</el-collapse-item>
</el-collapse>
<span style="display: block; margin-top: 20px">{{ $t('view.favorite.worlds.local_favorites') }}</span>
<span style="display: block; margin-top: 20px">{{ t('view.favorite.worlds.local_favorites') }}</span>
<br />
<el-button size="small" @click="promptNewLocalWorldFavoriteGroup">{{
$t('view.favorite.worlds.new_group')
t('view.favorite.worlds.new_group')
}}</el-button>
<el-button
v-if="!refreshingLocalFavorites"
size="small"
style="margin-left: 5px"
@click="refreshLocalWorldFavorite"
>{{ $t('view.favorite.worlds.refresh') }}</el-button
>{{ t('view.favorite.worlds.refresh') }}</el-button
>
<el-button v-else size="small" style="margin-left: 5px" @click="refreshingLocalFavorites = false">
<i class="el-icon-loading" style="margin-right: 5px" />
<span>{{ $t('view.favorite.worlds.cancel_refresh') }}</span>
<el-icon style="margin-right: 5px"><Loading /></el-icon>
<span>{{ t('view.favorite.worlds.cancel_refresh') }}</span>
</el-button>
<el-collapse style="border: 0">
<el-collapse-item v-for="group in localWorldFavoriteGroups" v-if="localWorldFavorites[group]" :key="group">
<template slot="title">
<el-collapse-item v-for="group in localWorldFavoriteGroups" :key="group">
<template #title v-if="localWorldFavorites[group]">
<span style="font-weight: bold; font-size: 14px; margin-left: 10px" v-text="group" />
<span style="color: #909399; font-size: 12px; margin-left: 10px">{{
getLocalWorldFavoriteGroupLength(group)
}}</span>
<el-tooltip placement="top" :content="$t('view.favorite.rename_tooltip')" :disabled="hideTooltips">
<el-tooltip placement="top" :content="t('view.favorite.rename_tooltip')">
<el-button
size="mini"
icon="el-icon-edit"
size="small"
:icon="Edit"
circle
style="margin-left: 10px"
@click.stop="promptLocalWorldFavoriteGroupRename(group)" />
</el-tooltip>
<el-tooltip
placement="right"
:content="$t('view.favorite.delete_tooltip')"
:disabled="hideTooltips">
<el-tooltip placement="right" :content="t('view.favorite.delete_tooltip')">
<el-button
size="mini"
icon="el-icon-delete"
size="small"
:icon="Delete"
circle
style="margin-left: 5px"
@click.stop="promptLocalWorldFavoriteGroupDelete(group)" />
@@ -190,7 +180,6 @@
:group="group"
:favorite="favorite"
:edit-favorites-mode="editFavoritesMode"
:hide-tooltips="hideTooltips"
@click="showWorldDialog(favorite.id)"
@remove-local-world-favorite="removeLocalWorldFavorite" />
</div>
@@ -208,14 +197,16 @@
</div>
</el-collapse-item>
</el-collapse>
<WorldExportDialog :world-export-dialog-visible.sync="worldExportDialogVisible" />
<WorldExportDialog v-model:worldExportDialogVisible="worldExportDialogVisible" />
</div>
</template>
<script setup>
import { computed, ref, getCurrentInstance } from 'vue';
import { View, Edit, Delete, Loading } from '@element-plus/icons-vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { computed, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import { favoriteRequest } from '../../../api';
import { useAppearanceSettingsStore, useFavoriteStore, useWorldStore } from '../../../stores';
import WorldExportDialog from '../dialogs/WorldExportDialog.vue';
@@ -238,10 +229,8 @@
'refresh-local-world-favorite'
]);
const { proxy } = getCurrentInstance();
const { t } = useI18n();
const { hideTooltips, sortFavorites } = storeToRefs(useAppearanceSettingsStore());
const { sortFavorites } = storeToRefs(useAppearanceSettingsStore());
const { setSortFavorites } = useAppearanceSettingsStore();
const { favoriteWorlds, favoriteWorldGroups, localWorldFavorites, localWorldFavoriteGroups } =
storeToRefs(useFavoriteStore());
@@ -290,15 +279,13 @@
}
function userFavoriteWorldsStatusForFavTab(visibility) {
let style = '';
if (visibility === 'public') {
style = '';
} else if (visibility === 'friends') {
style = 'success';
} else {
style = 'info';
return 'primary';
}
return style;
if (visibility === 'friends') {
return 'success';
}
return 'info';
}
function changeWorldGroupVisibility(name, visibility) {
@@ -314,7 +301,7 @@
favoriteGroupId: args.json.id
}
});
proxy.$message({
ElMessage({
message: 'Group visibility changed',
type: 'success'
});
@@ -323,22 +310,27 @@
}
function promptNewLocalWorldFavoriteGroup() {
proxy.$prompt(t('prompt.new_local_favorite_group.description'), t('prompt.new_local_favorite_group.header'), {
distinguishCancelAndClose: true,
confirmButtonText: t('prompt.new_local_favorite_group.ok'),
cancelButtonText: t('prompt.new_local_favorite_group.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.new_local_favorite_group.input_error'),
callback: (action, instance) => {
if (action === 'confirm' && instance.inputValue) {
newLocalWorldFavoriteGroup(instance.inputValue);
}
ElMessageBox.prompt(
t('prompt.new_local_favorite_group.description'),
t('prompt.new_local_favorite_group.header'),
{
distinguishCancelAndClose: true,
confirmButtonText: t('prompt.new_local_favorite_group.ok'),
cancelButtonText: t('prompt.new_local_favorite_group.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.new_local_favorite_group.input_error')
}
});
)
.then(({ value }) => {
if (value) {
newLocalWorldFavoriteGroup(value);
}
})
.catch(() => {});
}
function promptLocalWorldFavoriteGroupRename(group) {
proxy.$prompt(
ElMessageBox.prompt(
t('prompt.local_favorite_group_rename.description'),
t('prompt.local_favorite_group_rename.header'),
{
@@ -347,43 +339,46 @@
cancelButtonText: t('prompt.local_favorite_group_rename.cancel'),
inputPattern: /\S+/,
inputErrorMessage: t('prompt.local_favorite_group_rename.input_error'),
inputValue: group,
callback: (action, instance) => {
if (action === 'confirm' && instance.inputValue) {
renameLocalWorldFavoriteGroup(instance.inputValue, group);
}
}
inputValue: group
}
);
)
.then(({ value }) => {
if (value) {
renameLocalWorldFavoriteGroup(value, group);
}
})
.catch(() => {});
}
function promptLocalWorldFavoriteGroupDelete(group) {
proxy.$confirm(`Delete Group? ${group}`, 'Confirm', {
ElMessageBox.confirm(`Delete Group? ${group}`, 'Confirm', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'info',
callback: (action) => {
type: 'info'
})
.then((action) => {
if (action === 'confirm') {
deleteLocalWorldFavoriteGroup(group);
}
}
});
})
.catch(() => {});
}
function clearFavoriteGroup(ctx) {
proxy.$confirm('Continue? Clear Group', 'Confirm', {
ElMessageBox.confirm('Continue? Clear Group', 'Confirm', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'info',
callback: (action) => {
type: 'info'
})
.then((action) => {
if (action === 'confirm') {
favoriteRequest.clearFavoriteGroup({
type: ctx.type,
group: ctx.name
});
}
}
});
})
.catch(() => {});
}
function searchWorldFavorites(worldFavoriteSearch) {
@@ -1,92 +1,96 @@
<template>
<safe-dialog :visible.sync="isDialogVisible" :title="t('dialog.avatar_export.header')" width="650px">
<el-dialog v-model="isDialogVisible" :title="t('dialog.avatar_export.header')" width="650px">
<el-checkbox-group
v-model="exportSelectedOptions"
style="margin-bottom: 10px"
@change="updateAvatarExportDialog()">
<template v-for="option in exportSelectOptions">
<el-checkbox :key="option.value" :label="option.label"></el-checkbox>
<template v-for="option in exportSelectOptions" :key="option.value">
<el-checkbox :label="option.label"></el-checkbox>
</template>
</el-checkbox-group>
<el-dropdown trigger="click" size="small" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small">
<el-button size="small">
<span v-if="avatarExportFavoriteGroup">
{{ avatarExportFavoriteGroup.displayName }} ({{ avatarExportFavoriteGroup.count }}/{{
avatarExportFavoriteGroup.capacity
}})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else>
All Favorites
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item style="display: block; margin: 10px 0" @click.native="selectAvatarExportGroup(null)">
All Favorites
</el-dropdown-item>
<template v-for="groupAPI in favoriteAvatarGroups">
<el-dropdown-item
:key="groupAPI.name"
style="display: block; margin: 10px 0"
@click.native="selectAvatarExportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item style="display: block; margin: 10px 0" @click="selectAvatarExportGroup(null)">
All Favorites
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template v-for="groupAPI in favoriteAvatarGroups" :key="groupAPI.name">
<el-dropdown-item
style="display: block; margin: 10px 0"
@click="selectAvatarExportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown trigger="click" size="small" style="margin-left: 10px" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small" style="margin-left: 10px">
<el-button size="small">
<span v-if="avatarExportLocalFavoriteGroup">
{{ avatarExportLocalFavoriteGroup }} ({{
getLocalAvatarFavoriteGroupLength(avatarExportLocalFavoriteGroup)
}})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else>
Select Group
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
style="display: block; margin: 10px 0"
@click.native="selectAvatarExportLocalGroup(null)">
None
</el-dropdown-item>
<template v-for="group in localAvatarFavoriteGroups">
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
:key="group"
style="display: block; margin: 10px 0"
@click.native="selectAvatarExportLocalGroup(group)">
{{ group }} ({{ getLocalAvatarFavoriteGroupLength(group) }})
@click="selectAvatarExportLocalGroup(null)">
None
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template v-for="group in localAvatarFavoriteGroups" :key="group">
<el-dropdown-item
style="display: block; margin: 10px 0"
@click="selectAvatarExportLocalGroup(group)">
{{ group }} ({{ getLocalAvatarFavoriteGroupLength(group) }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<br />
<el-input
v-model="avatarExportContent"
type="textarea"
size="mini"
rows="15"
size="small"
:rows="15"
resize="none"
readonly
style="margin-top: 15px"
@click.native="handleCopyAvatarExportData"></el-input>
</safe-dialog>
@click="handleCopyAvatarExportData"></el-input>
</el-dialog>
</template>
<script setup>
import { ref, computed, watch, getCurrentInstance } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { ArrowDown } from '@element-plus/icons-vue';
import { ref, computed, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { useAvatarStore, useFavoriteStore } from '../../../stores';
const { t } = useI18n();
const { proxy } = getCurrentInstance();
const props = defineProps({
avatarExportDialogVisible: {
@@ -106,8 +110,7 @@
localAvatarFavoriteGroups
} = storeToRefs(favoriteStore);
const { getLocalAvatarFavoriteGroupLength } = favoriteStore;
const avatarStore = useAvatarStore();
const { cachedAvatars } = storeToRefs(avatarStore);
const { cachedAvatars } = useAvatarStore();
const avatarExportContent = ref('');
const avatarExportFavoriteGroup = ref(null);
@@ -151,7 +154,7 @@
navigator.clipboard
.writeText(avatarExportContent.value)
.then(() => {
proxy.$message({
ElMessage({
message: 'Copied successfully!',
type: 'success',
duration: 2000
@@ -159,7 +162,7 @@
})
.catch((err) => {
console.error('Copy failed:', err);
proxy.$message.error('Copy failed!');
ElMessage.error('Copy failed!');
});
}
function updateAvatarExportDialog() {
@@ -209,7 +212,7 @@
});
for (let i = 0; i < localAvatarFavoritesList.value.length; ++i) {
const avatarId = localAvatarFavoritesList.value[i];
const ref = cachedAvatars.value.get(avatarId);
const ref = cachedAvatars.get(avatarId);
if (typeof ref !== 'undefined') {
lines.push(resText(ref));
}
@@ -1,7 +1,7 @@
<template>
<safe-dialog
ref="avatarImportDialogRef"
:visible.sync="isVisible"
<el-dialog
:z-index="avatarImportDialogIndex"
v-model="isVisible"
:title="t('dialog.avatar_import.header')"
width="650px">
<div style="display: flex; align-items: center; justify-content: space-between">
@@ -10,7 +10,7 @@
<div v-if="avatarImportDialog.progress">
{{ t('dialog.avatar_import.process_progress') }} {{ avatarImportDialog.progress }} /
{{ avatarImportDialog.progressTotal }}
<i class="el-icon-loading" style="margin: 0 5px"></i>
<el-icon style="margin: 0 5px"><Loading /></el-icon>
</div>
<el-button v-if="avatarImportDialog.loading" size="small" @click="cancelAvatarImport">
{{ t('dialog.avatar_import.cancel') }}
@@ -23,60 +23,62 @@
<el-input
v-model="avatarImportDialog.input"
type="textarea"
size="mini"
rows="10"
size="small"
:rows="10"
resize="none"
style="margin-top: 10px"></el-input>
<div style="display: flex; align-items: center; justify-content: space-between; margin-top: 5px">
<div>
<el-dropdown trigger="click" size="small" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small" style="margin-right: 5px" @click.stop>
<el-button size="small">
<span v-if="avatarImportDialog.avatarImportFavoriteGroup">
{{ avatarImportDialog.avatarImportFavoriteGroup.displayName }} ({{
avatarImportDialog.avatarImportFavoriteGroup.count
}}/{{ avatarImportDialog.avatarImportFavoriteGroup.capacity }})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else>
{{ t('dialog.avatar_import.select_group_placeholder') }}
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<el-dropdown-menu slot="dropdown">
<template v-for="groupAPI in favoriteAvatarGroups">
<el-dropdown-item
:key="groupAPI.name"
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click.native="selectAvatarImportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template #dropdown>
<el-dropdown-menu>
<template v-for="groupAPI in favoriteAvatarGroups" :key="groupAPI.name">
<el-dropdown-item
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click="selectAvatarImportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown trigger="click" size="small" style="margin: 5px" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small">
<el-button size="small">
<span v-if="avatarImportDialog.avatarImportLocalFavoriteGroup">
{{ avatarImportDialog.avatarImportLocalFavoriteGroup }} ({{
getLocalAvatarFavoriteGroupLength(avatarImportDialog.avatarImportLocalFavoriteGroup)
}})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else>
{{ t('dialog.avatar_import.select_group_placeholder') }}
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<el-dropdown-menu slot="dropdown">
<template v-for="group in localAvatarFavoriteGroups">
<el-dropdown-item
:key="group"
style="display: block; margin: 10px 0"
@click.native="selectAvatarImportLocalGroup(group)">
{{ group }} ({{ getLocalAvatarFavoriteGroupLength(group) }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template #dropdown>
<el-dropdown-menu>
<template v-for="group in localAvatarFavoriteGroups" :key="group">
<el-dropdown-item
style="display: block; margin: 10px 0"
@click="selectAvatarImportLocalGroup(group)">
{{ group }} ({{ getLocalAvatarFavoriteGroupLength(group) }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<span v-if="avatarImportDialog.avatarImportFavoriteGroup" style="margin-left: 5px">
{{ avatarImportTable.data.length }} /
@@ -105,7 +107,7 @@
</div>
</div>
<span v-if="avatarImportDialog.importProgress" style="margin: 10px">
<i class="el-icon-loading" style="margin-right: 5px"></i>
<el-icon style="margin-right: 5px"><Loading /></el-icon>
{{ t('dialog.avatar_import.import_progress') }}
{{ avatarImportDialog.importProgress }}/{{ avatarImportDialog.importProgressTotal }}
</span>
@@ -119,70 +121,73 @@
</h2>
<pre style="white-space: pre-wrap; font-size: 12px" v-text="avatarImportDialog.errors"></pre>
</template>
<data-tables v-loading="avatarImportDialog.loading" v-bind="avatarImportTable" style="margin-top: 10px">
<DataTable v-loading="avatarImportDialog.loading" v-bind="avatarImportTable" style="margin-top: 10px">
<el-table-column :label="t('table.import.image')" width="70" prop="thumbnailImageUrl">
<template slot-scope="scope">
<el-popover placement="right" height="500px" trigger="hover">
<img slot="reference" v-lazy="scope.row.thumbnailImageUrl" class="friends-list-avatar" />
<template #default="{ row }">
<el-popover placement="right" :width="500" trigger="hover">
<template #reference>
<img :src="row.thumbnailImageUrl" class="friends-list-avatar" loading="lazy" />
</template>
<img
v-lazy="scope.row.imageUrl"
class="friends-list-avatar"
style="height: 500px; cursor: pointer"
@click="showFullscreenImageDialog(scope.row.imageUrl)" />
:src="row.imageUrl"
:class="['friends-list-avatar', 'x-popover-image']"
style="cursor: pointer"
@click="showFullscreenImageDialog(row.imageUrl)"
loading="lazy" />
</el-popover>
</template>
</el-table-column>
<el-table-column :label="t('table.import.name')" prop="name">
<template slot-scope="scope">
<span class="x-link" @click="showAvatarDialog(scope.row.id)">
{{ scope.row.name }}
<template #default="{ row }">
<span class="x-link" @click="showAvatarDialog(row.id)">
{{ row.name }}
</span>
</template>
</el-table-column>
<el-table-column :label="t('table.import.author')" width="120" prop="authorName">
<template slot-scope="scope">
<span class="x-link" @click="showUserDialog(scope.row.authorId)">
{{ scope.row.authorName }}
<template #default="{ row }">
<span class="x-link" @click="showUserDialog(row.authorId)">
{{ row.authorName }}
</span>
</template>
</el-table-column>
<el-table-column :label="t('table.import.status')" width="70" prop="releaseStatus">
<template slot-scope="scope">
<template #default="{ row }">
<span
:style="{
color:
scope.row.releaseStatus === 'public'
row.releaseStatus === 'public'
? '#67c23a'
: scope.row.releaseStatus === 'private'
: row.releaseStatus === 'private'
? '#f56c6c'
: undefined
}">
{{ scope.row.releaseStatus.charAt(0).toUpperCase() + scope.row.releaseStatus.slice(1) }}
{{ row.releaseStatus.charAt(0).toUpperCase() + row.releaseStatus.slice(1) }}
</span>
</template>
</el-table-column>
<el-table-column :label="t('table.import.action')" width="90" align="right">
<template slot-scope="scope">
<el-button type="text" icon="el-icon-close" size="mini" @click="deleteItemAvatarImport(scope.row)">
</el-button>
<template #default="{ row }">
<el-button type="text" :icon="Close" size="small" @click="deleteItemAvatarImport(row)"> </el-button>
</template>
</el-table-column>
</data-tables>
</safe-dialog>
</DataTable>
</el-dialog>
</template>
<script setup>
import { ref, computed, watch, getCurrentInstance } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { Close, Loading, ArrowDown } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { ref, computed, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { avatarRequest, favoriteRequest } from '../../../api';
import { adjustDialogZ, removeFromArray } from '../../../shared/utils';
import { getNextDialogIndex, removeFromArray } from '../../../shared/utils';
import { useAvatarStore, useFavoriteStore, useGalleryStore, useUserStore } from '../../../stores';
const emit = defineEmits(['update:avatarImportDialogInput']);
const { t } = useI18n();
const { proxy } = getCurrentInstance();
const { showUserDialog } = useUserStore();
const { favoriteAvatarGroups, avatarImportDialogInput, avatarImportDialogVisible, localAvatarFavoriteGroups } =
storeToRefs(useFavoriteStore());
@@ -212,7 +217,7 @@
layout: 'table'
});
const avatarImportDialogRef = ref(null);
const avatarImportDialogIndex = ref(2000);
const isVisible = computed({
get() {
@@ -227,7 +232,7 @@
() => avatarImportDialogVisible.value,
(value) => {
if (value) {
adjustDialogZ(avatarImportDialogRef.value.$el);
avatarImportDialogIndex.value = getNextDialogIndex();
clearAvatarImportTable();
resetAvatarImport();
if (avatarImportDialogInput.value) {
@@ -318,7 +323,7 @@
})
.then((args) => {
if (message) {
proxy.$message({
ElMessage({
message: 'Avatar added to favorites',
type: 'success'
});
@@ -334,7 +339,7 @@
D.loading = true;
const data = [...avatarImportTable.value.data].reverse();
D.importProgressTotal = data.length;
let ref = '';
let ref = null;
try {
for (let i = data.length - 1; i >= 0; i--) {
if (!D.loading || !isVisible.value) {
@@ -351,7 +356,7 @@
D.importProgress++;
}
} catch (err) {
D.errors = `Name: ${ref.name}\nAvatarId: ${ref.id}\n${err}\n\n`;
D.errors = `Name: ${ref?.name}\nAvatarId: ${ref?.id}\n${err}\n\n`;
} finally {
D.importProgress = 0;
D.importProgressTotal = 0;
@@ -1,55 +1,60 @@
<template>
<safe-dialog
:visible.sync="isDialogVisible"
<el-dialog
v-model="isDialogVisible"
class="x-dialog"
:title="t('dialog.friend_export.header')"
width="650px"
destroy-on-close>
<el-dropdown trigger="click" size="small" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small">
<el-button size="small">
<span v-if="friendExportFavoriteGroup">
{{ friendExportFavoriteGroup.displayName }} ({{ friendExportFavoriteGroup.count }}/{{
friendExportFavoriteGroup.capacity
}})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else>All Favorites <i class="el-icon-arrow-down el-icon--right"></i></span>
<span v-else
>All Favorites <el-icon class="el-icon--right"><ArrowDown /></el-icon
></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item style="display: block; margin: 10px 0" @click.native="selectFriendExportGroup(null)">
All Favorites
</el-dropdown-item>
<template v-for="groupAPI in favoriteFriendGroups">
<el-dropdown-item
:key="groupAPI.name"
style="display: block; margin: 10px 0"
@click.native="selectFriendExportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item style="display: block; margin: 10px 0" @click="selectFriendExportGroup(null)">
All Favorites
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template v-for="groupAPI in favoriteFriendGroups" :key="groupAPI.name">
<el-dropdown-item
style="display: block; margin: 10px 0"
@click="selectFriendExportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<br />
<el-input
v-model="friendExportContent"
type="textarea"
size="mini"
rows="15"
size="small"
:rows="15"
resize="none"
readonly
style="margin-top: 15px"
@click.native="handleCopyFriendExportData"></el-input>
</safe-dialog>
@click="handleCopyFriendExportData"></el-input>
</el-dialog>
</template>
<script setup>
import { ref, computed, watch, getCurrentInstance } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { ArrowDown } from '@element-plus/icons-vue';
import { ref, computed, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { useFavoriteStore } from '../../../stores';
const { t } = useI18n();
const { proxy } = getCurrentInstance();
const props = defineProps({
friendExportDialogVisible: {
@@ -96,7 +101,7 @@
navigator.clipboard
.writeText(friendExportContent.value)
.then(() => {
proxy.$message({
ElMessage({
message: 'Copied successfully!',
type: 'success',
duration: 2000
@@ -104,7 +109,7 @@
})
.catch((err) => {
console.error('Copy failed:', err);
proxy.$message.error('Copy failed!');
ElMessage.error('Copy failed!');
});
}
@@ -1,7 +1,7 @@
<template>
<safe-dialog
ref="friendImportDialogRef"
:visible.sync="isVisible"
<el-dialog
:z-index="friendImportDialogIndex"
v-model="isVisible"
:title="t('dialog.friend_import.header')"
width="650px">
<div style="display: flex; align-items: center; justify-content: space-between">
@@ -10,7 +10,7 @@
<div v-if="friendImportDialog.progress">
{{ t('dialog.friend_import.process_progress') }} {{ friendImportDialog.progress }} /
{{ friendImportDialog.progressTotal }}
<i class="el-icon-loading" style="margin: 0 5px"></i>
<el-icon style="margin: 0 5px"><Loading /></el-icon>
</div>
<el-button v-if="friendImportDialog.loading" size="small" @click="cancelFriendImport">
{{ t('dialog.friend_import.cancel') }}
@@ -23,36 +23,37 @@
<el-input
v-model="friendImportDialog.input"
type="textarea"
size="mini"
rows="10"
size="small"
:rows="10"
resize="none"
style="margin-top: 10px" />
<div style="display: flex; align-items: center; justify-content: space-between; margin-top: 5px">
<div>
<el-dropdown trigger="click" size="small" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small">
<el-button size="small">
<span v-if="friendImportDialog.friendImportFavoriteGroup">
{{ friendImportDialog.friendImportFavoriteGroup.displayName }} ({{
friendImportDialog.friendImportFavoriteGroup.count
}}/{{ friendImportDialog.friendImportFavoriteGroup.capacity }})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else
>{{ t('dialog.friend_import.select_group_placeholder') }}
<i class="el-icon-arrow-down el-icon--right"></i
<el-icon class="el-icon--right"><ArrowDown /></el-icon
></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<template v-for="groupAPI in favoriteFriendGroups">
<el-dropdown-item
:key="groupAPI.name"
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click.native="selectFriendImportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template #dropdown>
<el-dropdown-menu>
<template v-for="groupAPI in favoriteFriendGroups" :key="groupAPI.name">
<el-dropdown-item
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click="selectFriendImportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<span v-if="friendImportDialog.friendImportFavoriteGroup" style="margin-left: 5px">
{{ friendImportTable.data.length }} /
@@ -77,7 +78,7 @@
</div>
</div>
<span v-if="friendImportDialog.importProgress" style="margin: 10px">
<i class="el-icon-loading" style="margin-right: 5px"></i>
<el-icon style="margin-right: 5px"><Loading /></el-icon>
{{ t('dialog.friend_import.import_progress') }} {{ friendImportDialog.importProgress }}/{{
friendImportDialog.importProgressTotal
}}
@@ -90,47 +91,47 @@
<h2 style="font-weight: bold; margin: 5px 0">{{ t('dialog.friend_import.errors') }}</h2>
<pre style="white-space: pre-wrap; font-size: 12px" v-text="friendImportDialog.errors"></pre>
</template>
<data-tables v-loading="friendImportDialog.loading" v-bind="friendImportTable" style="margin-top: 10px">
<DataTable v-loading="friendImportDialog.loading" v-bind="friendImportTable" style="margin-top: 10px">
<el-table-column :label="t('table.import.image')" width="70" prop="currentAvatarThumbnailImageUrl">
<template slot-scope="scope">
<el-popover placement="right" height="500px" trigger="hover">
<template slot="reference">
<img class="friends-list-avatar" :src="userImage(scope.row)" />
<template #default="{ row }">
<el-popover placement="right" :width="500" trigger="hover">
<template #reference>
<img class="friends-list-avatar" :src="userImage(row)" />
</template>
<img
class="friends-list-avatar"
:src="userImageFull(scope.row)"
style="height: 500px; cursor: pointer"
@click="showFullscreenImageDialog(userImageFull(scope.row))" />
:src="userImageFull(row)"
:class="['friends-list-avatar', 'x-popover-image']"
style="cursor: pointer"
@click="showFullscreenImageDialog(userImageFull(row))" />
</el-popover>
</template>
</el-table-column>
<el-table-column :label="t('table.import.name')" prop="displayName">
<template slot-scope="scope">
<span class="x-link" :title="scope.row.displayName" @click="showUserDialog(scope.row.id)">
{{ scope.row.displayName }}
<template #default="{ row }">
<span class="x-link" :title="row.displayName" @click="showUserDialog(row.id)">
{{ row.displayName }}
</span>
</template>
</el-table-column>
<el-table-column :label="t('table.import.action')" width="90" align="right">
<template slot-scope="scope">
<el-button type="text" icon="el-icon-close" size="mini" @click="deleteItemFriendImport(scope.row)">
</el-button>
<template #default="{ row }">
<el-button type="text" :icon="Close" size="small" @click="deleteItemFriendImport(row)"> </el-button>
</template>
</el-table-column>
</data-tables>
</safe-dialog>
</DataTable>
</el-dialog>
</template>
<script setup>
import { ref, computed, watch, getCurrentInstance } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n-bridge';
import { favoriteRequest, userRequest } from '../../../api';
import { adjustDialogZ, removeFromArray, userImage, userImageFull } from '../../../shared/utils';
import { useFavoriteStore, useGalleryStore, useUserStore } from '../../../stores';
import { Close, Loading, ArrowDown } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
const { proxy } = getCurrentInstance();
import { ref, computed, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { favoriteRequest, userRequest } from '../../../api';
import { getNextDialogIndex, removeFromArray, userImage, userImageFull } from '../../../shared/utils';
import { useFavoriteStore, useGalleryStore, useUserStore } from '../../../stores';
const { t } = useI18n();
@@ -157,12 +158,12 @@
data: [],
tableProps: {
stripe: true,
size: 'mini'
size: 'small'
},
layout: 'table'
});
const friendImportDialogRef = ref(null);
const friendImportDialogIndex = ref(2000);
const isVisible = computed({
get() {
@@ -177,7 +178,7 @@
() => friendImportDialogVisible.value,
(value) => {
if (value) {
adjustDialogZ(friendImportDialogRef.value.$el);
friendImportDialogIndex.value = getNextDialogIndex();
clearFriendImportTable();
resetFriendImport();
if (friendImportDialogInput.value) {
@@ -211,7 +212,7 @@
}
const data = [...friendImportTable.value.data].reverse();
D.importProgressTotal = data.length;
let ref = '';
let ref = null;
try {
for (let i = data.length - 1; i >= 0; i--) {
if (!D.loading || !isVisible.value) {
@@ -224,7 +225,7 @@
D.importProgress++;
}
} catch (err) {
D.errors = `Name: ${ref.displayName}\nUserId: ${ref.id}\n${err}\n\n`;
D.errors = `Name: ${ref?.displayName}\nUserId: ${ref?.id}\n${err}\n\n`;
} finally {
D.importProgress = 0;
D.importProgressTotal = 0;
@@ -240,7 +241,7 @@
})
.then((args) => {
if (message) {
proxy.$message({
ElMessage({
message: 'Friend added to favorites',
type: 'success'
});
@@ -1,70 +1,70 @@
<template>
<safe-dialog :visible.sync="isDialogVisible" :title="t('dialog.world_export.header')" width="650px">
<el-dialog v-model="isDialogVisible" :title="t('dialog.world_export.header')" width="650px">
<el-checkbox-group
v-model="exportSelectedOptions"
style="margin-bottom: 10px"
@change="updateWorldExportDialog">
<template v-for="option in exportSelectOptions">
<el-checkbox :key="option.value" :label="option.label"></el-checkbox>
<template v-for="option in exportSelectOptions" :key="option.value">
<el-checkbox :label="option.label"></el-checkbox>
</template>
</el-checkbox-group>
<el-dropdown trigger="click" size="small" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small">
<el-button size="small">
<span v-if="worldExportFavoriteGroup">
{{ worldExportFavoriteGroup.displayName }} ({{ worldExportFavoriteGroup.count }}/{{
worldExportFavoriteGroup.capacity
}})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else>
All Favorites
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item style="display: block; margin: 10px 0" @click.native="selectWorldExportGroup(null)">
None
</el-dropdown-item>
<template v-for="groupAPI in favoriteWorldGroups">
<el-dropdown-item
:key="groupAPI.name"
style="display: block; margin: 10px 0"
@click.native="selectWorldExportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item style="display: block; margin: 10px 0" @click="selectWorldExportGroup(null)">
None
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template v-for="groupAPI in favoriteWorldGroups" :key="groupAPI.name">
<el-dropdown-item
style="display: block; margin: 10px 0"
@click="selectWorldExportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown trigger="click" size="small" style="margin-left: 10px" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small" style="margin-left: 10px">
<el-button size="small">
<span v-if="worldExportLocalFavoriteGroup">
{{ worldExportLocalFavoriteGroup }} ({{
getLocalWorldFavoriteGroupLength(worldExportLocalFavoriteGroup)
}})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else>
Select Group
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
style="display: block; margin: 10px 0"
@click.native="selectWorldExportLocalGroup(null)">
None
</el-dropdown-item>
<template v-for="group in localWorldFavoriteGroups">
<el-dropdown-item
:key="group"
style="display: block; margin: 10px 0"
@click.native="selectWorldExportLocalGroup(group)">
{{ group }} ({{ localWorldFavorites[group].length }})
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item style="display: block; margin: 10px 0" @click="selectWorldExportLocalGroup(null)">
None
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template v-for="group in localWorldFavoriteGroups" :key="group">
<el-dropdown-item
style="display: block; margin: 10px 0"
@click="selectWorldExportLocalGroup(group)">
{{ group }} ({{ localWorldFavorites[group].length }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<br />
@@ -72,18 +72,21 @@
<el-input
v-model="worldExportContent"
type="textarea"
size="mini"
rows="15"
size="small"
:rows="15"
resize="none"
readonly
style="margin-top: 15px"
@click.native="handleCopyWorldExportData"></el-input>
</safe-dialog>
@click="handleCopyWorldExportData"></el-input>
</el-dialog>
</template>
<script setup>
import { ref, computed, watch, getCurrentInstance } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { ArrowDown } from '@element-plus/icons-vue';
import { ref, computed, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { useFavoriteStore, useWorldStore } from '../../../stores';
@@ -97,7 +100,6 @@
const emit = defineEmits(['update:worldExportDialogVisible']);
const { t } = useI18n();
const { proxy } = getCurrentInstance();
const favoriteStore = useFavoriteStore();
const {
@@ -108,7 +110,7 @@
localWorldFavoritesList
} = storeToRefs(favoriteStore);
const { getLocalWorldFavoriteGroupLength } = favoriteStore;
const { cachedWorlds } = storeToRefs(useWorldStore());
const { cachedWorlds } = useWorldStore();
const worldExportContent = ref('');
const worldExportFavoriteGroup = ref(null);
@@ -154,7 +156,7 @@
navigator.clipboard
.writeText(worldExportContent.value)
.then(() => {
proxy.$message({
ElMessage({
message: 'Copied successfully!',
type: 'success',
duration: 2000
@@ -162,7 +164,7 @@
})
.catch((err) => {
console.error('Copy failed:', err);
proxy.$message.error('Copy failed!');
ElMessage.error('Copy failed!');
});
}
@@ -214,7 +216,7 @@
});
for (let i = 0; i < localWorldFavoritesList.value.length; ++i) {
const worldId = localWorldFavoritesList.value[i];
const ref = cachedWorlds.value.get(worldId);
const ref = cachedWorlds.get(worldId);
if (typeof ref !== 'undefined') {
lines.push(resText(ref));
}
@@ -1,7 +1,7 @@
<template>
<safe-dialog
ref="worldImportDialogRef"
:visible.sync="isVisible"
<el-dialog
:z-index="worldImportDialogIndex"
v-model="isVisible"
:title="t('dialog.world_import.header')"
width="650px"
class="x-dialog">
@@ -11,7 +11,7 @@
<div v-if="worldImportDialog.progress">
{{ t('dialog.world_import.process_progress') }}
{{ worldImportDialog.progress }} / {{ worldImportDialog.progressTotal }}
<i class="el-icon-loading" style="margin: 0 5px"></i>
<el-icon style="margin: 0 5px"><Loading /></el-icon>
</div>
<el-button v-if="worldImportDialog.loading" size="small" @click="cancelWorldImport">
{{ t('dialog.world_import.cancel') }}
@@ -24,60 +24,62 @@
<el-input
v-model="worldImportDialog.input"
type="textarea"
size="mini"
rows="10"
size="small"
:rows="10"
resize="none"
style="margin-top: 10px"></el-input>
<div style="display: flex; align-items: center; justify-content: space-between; margin-top: 5px">
<div>
<el-dropdown trigger="click" size="small" style="margin-right: 5px" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small" style="margin-right: 5px" @click.stop>
<el-button size="small">
<span v-if="worldImportDialog.worldImportFavoriteGroup">
{{ worldImportDialog.worldImportFavoriteGroup.displayName }}
({{ worldImportDialog.worldImportFavoriteGroup.count }}/{{
worldImportDialog.worldImportFavoriteGroup.capacity
}})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else>
{{ t('dialog.world_import.select_vrchat_group_placeholder') }}
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<el-dropdown-menu slot="dropdown">
<template v-for="groupAPI in favoriteWorldGroups">
<el-dropdown-item
:key="groupAPI.name"
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click.native="selectWorldImportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template #dropdown>
<el-dropdown-menu>
<template v-for="groupAPI in favoriteWorldGroups" :key="groupAPI.name">
<el-dropdown-item
style="display: block; margin: 10px 0"
:disabled="groupAPI.count >= groupAPI.capacity"
@click="selectWorldImportGroup(groupAPI)">
{{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown trigger="click" size="small" style="margin: 5px" @click.native.stop>
<el-button size="mini">
<el-dropdown trigger="click" size="small" @click.stop>
<el-button size="small">
<span v-if="worldImportDialog.worldImportLocalFavoriteGroup">
{{ worldImportDialog.worldImportLocalFavoriteGroup }}
({{ getLocalWorldFavoriteGroupLength(worldImportDialog.worldImportLocalFavoriteGroup) }})
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
<span v-else>
{{ t('dialog.world_import.select_local_group_placeholder') }}
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<el-dropdown-menu slot="dropdown">
<template v-for="group in localWorldFavoriteGroups">
<el-dropdown-item
:key="group"
style="display: block; margin: 10px 0"
@click.native="selectWorldImportLocalGroup(group)">
{{ group }} ({{ getLocalWorldFavoriteGroupLength(group) }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
<template #dropdown>
<el-dropdown-menu>
<template v-for="group in localWorldFavoriteGroups" :key="group">
<el-dropdown-item
style="display: block; margin: 10px 0"
@click="selectWorldImportLocalGroup(group)">
{{ group }} ({{ getLocalWorldFavoriteGroupLength(group) }})
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<span v-if="worldImportDialog.worldImportFavoriteGroup" style="margin-left: 5px">
{{ worldImportTable.data.length }} /
@@ -106,7 +108,7 @@
</div>
</div>
<span v-if="worldImportDialog.importProgress" style="margin: 10px">
<i class="el-icon-loading" style="margin-right: 5px"></i>
<el-icon style="margin-right: 5px"><Loading /></el-icon>
{{ t('dialog.world_import.import_progress') }}
{{ worldImportDialog.importProgress }}/{{ worldImportDialog.importProgressTotal }}
</span>
@@ -120,67 +122,64 @@
</h2>
<pre style="white-space: pre-wrap; font-size: 12px" v-text="worldImportDialog.errors"></pre>
</template>
<data-tables v-loading="worldImportDialog.loading" v-bind="worldImportTable" style="margin-top: 10px">
<DataTable v-loading="worldImportDialog.loading" v-bind="worldImportTable" style="margin-top: 10px">
<el-table-column :label="t('table.import.image')" width="70" prop="thumbnailImageUrl">
<template slot-scope="scope">
<el-popover placement="right" height="500px" trigger="hover">
<img slot="reference" v-lazy="scope.row.thumbnailImageUrl" class="friends-list-avatar" />
<template #default="{ row }">
<el-popover placement="right" :width="500" trigger="hover">
<template #reference>
<img :src="row.thumbnailImageUrl" class="friends-list-avatar" loading="lazy" />
</template>
<img
v-lazy="scope.row.imageUrl"
class="friends-list-avatar"
style="height: 500px; cursor: pointer"
@click="showFullscreenImageDialog(scope.row.imageUrl)" />
:src="row.imageUrl"
:class="['friends-list-avatar', 'x-popover-image']"
style="cursor: pointer"
@click="showFullscreenImageDialog(row.imageUrl)"
loading="lazy" />
</el-popover>
</template>
</el-table-column>
<el-table-column :label="t('table.import.name')" prop="name">
<template slot-scope="scope">
<span class="x-link" @click="showWorldDialog(scope.row.id)" v-text="scope.row.name"></span>
<template #default="{ row }">
<span class="x-link" @click="showWorldDialog(row.id)" v-text="row.name"></span>
</template>
</el-table-column>
<el-table-column :label="t('table.import.author')" width="120" prop="authorName">
<template slot-scope="scope">
<span
class="x-link"
@click="showUserDialog(scope.row.authorId)"
v-text="scope.row.authorName"></span>
<template #default="{ row }">
<span class="x-link" @click="showUserDialog(row.authorId)" v-text="row.authorName"></span>
</template>
</el-table-column>
<el-table-column :label="t('table.import.status')" width="70" prop="releaseStatus">
<template slot-scope="scope">
<template #default="{ row }">
<span
:style="{
color:
scope.row.releaseStatus === 'public'
row.releaseStatus === 'public'
? '#67c23a'
: scope.row.releaseStatus === 'private'
: row.releaseStatus === 'private'
? '#f56c6c'
: undefined
}"
v-text="
scope.row.releaseStatus.charAt(0).toUpperCase() + scope.row.releaseStatus.slice(1)
"></span>
v-text="row.releaseStatus.charAt(0).toUpperCase() + row.releaseStatus.slice(1)"></span>
</template>
</el-table-column>
<el-table-column :label="t('table.import.action')" width="90" align="right">
<template slot-scope="scope">
<el-button
type="text"
icon="el-icon-close"
size="mini"
@click="deleteItemWorldImport(scope.row)"></el-button>
<template #default="{ row }">
<el-button type="text" :icon="Close" size="small" @click="deleteItemWorldImport(row)"></el-button>
</template>
</el-table-column>
</data-tables>
</safe-dialog>
</DataTable>
</el-dialog>
</template>
<script setup>
import { ref, watch, computed, getCurrentInstance } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { Close, Loading, ArrowDown } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { ref, watch, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { favoriteRequest, worldRequest } from '../../../api';
import { adjustDialogZ, removeFromArray } from '../../../shared/utils';
import { getNextDialogIndex, removeFromArray } from '../../../shared/utils';
import { useFavoriteStore, useGalleryStore, useUserStore, useWorldStore } from '../../../stores';
const { showUserDialog } = useUserStore();
@@ -192,10 +191,9 @@
const emit = defineEmits(['update:worldImportDialogInput']);
const { proxy } = getCurrentInstance();
const { t } = useI18n();
const worldImportDialogRef = ref(null);
const worldImportDialogIndex = ref(2000);
const worldImportDialog = ref({
loading: false,
@@ -214,7 +212,7 @@
data: [],
tableProps: {
stripe: true,
size: 'mini'
size: 'small'
},
layout: 'table'
});
@@ -232,7 +230,7 @@
() => worldImportDialogVisible.value,
(visible) => {
if (visible) {
adjustDialogZ(worldImportDialogRef.value.$el);
worldImportDialogIndex.value = getNextDialogIndex();
clearWorldImportTable();
resetWorldImport();
if (worldImportDialogInput.value) {
@@ -356,7 +354,7 @@
})
.then((args) => {
if (message) {
proxy.$message({
ElMessage({
message: 'World added to favorites',
type: 'success'
});