mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-07 14:56:06 +02:00
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:
@@ -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'
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user