mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-18 06:13:52 +02:00
refactor: resolve lag issues when opening the world dialog in the favorites worlds tab (#1156) (#1168)
* refactor: resolve lag issues when opening the world dialog in the favorite world tab (#1156) * fix
This commit is contained in:
@@ -146,7 +146,3 @@
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* your component styles here */
|
||||
</style>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
import Location from '../../components/common/Location.vue';
|
||||
|
||||
export default {
|
||||
name: 'PreviousInstanceInfo',
|
||||
name: 'PreviousInstanceInfoDialog',
|
||||
components: {
|
||||
Location
|
||||
},
|
||||
931
src/views/dialogs/WorldDialog.vue
Normal file
931
src/views/dialogs/WorldDialog.vue
Normal file
@@ -0,0 +1,931 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
ref="worldDialog"
|
||||
class="x-dialog x-world-dialog"
|
||||
:visible.sync="worldDialog.visible"
|
||||
:show-close="false"
|
||||
width="770px">
|
||||
<div v-loading="worldDialog.loading">
|
||||
<div style="display: flex">
|
||||
<el-popover placement="right" width="500px" trigger="click">
|
||||
<img
|
||||
slot="reference"
|
||||
v-lazy="worldDialog.ref.thumbnailImageUrl"
|
||||
class="x-link"
|
||||
style="flex: none; width: 160px; height: 120px; border-radius: 12px" />
|
||||
<img
|
||||
v-lazy="worldDialog.ref.imageUrl"
|
||||
class="x-link"
|
||||
style="width: 500px; height: 375px"
|
||||
@click="showFullscreenImageDialog(worldDialog.ref.imageUrl)" />
|
||||
</el-popover>
|
||||
<div style="flex: 1; display: flex; align-items: center; margin-left: 15px">
|
||||
<div style="flex: 1">
|
||||
<div>
|
||||
<i
|
||||
v-show="
|
||||
API.currentUser.$homeLocation &&
|
||||
API.currentUser.$homeLocation.worldId === worldDialog.id
|
||||
"
|
||||
class="el-icon-s-home"
|
||||
style="margin-right: 5px" />
|
||||
<span class="dialog-title" v-text="worldDialog.ref.name" />
|
||||
</div>
|
||||
<div style="margin-top: 5px">
|
||||
<span
|
||||
class="x-link x-grey"
|
||||
style="font-family: monospace"
|
||||
@click="showUserDialog(worldDialog.ref.authorId)"
|
||||
v-text="worldDialog.ref.authorName" />
|
||||
</div>
|
||||
<div>
|
||||
<el-tag
|
||||
v-if="worldDialog.ref.$isLabs"
|
||||
type="primary"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.labs') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-else-if="worldDialog.ref.releaseStatus === 'public'"
|
||||
type="success"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.public') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-else
|
||||
type="danger"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.private') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.isPC"
|
||||
class="x-tag-platform-pc"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
PC
|
||||
</el-tag>
|
||||
<span
|
||||
v-if="worldDialog.bundleSizes['standalonewindows']"
|
||||
class="x-grey"
|
||||
style="margin-left: 5px; border-left: inherit; padding-left: 5px">
|
||||
{{ worldDialog.bundleSizes['standalonewindows'].fileSize }}
|
||||
</span>
|
||||
<el-tag
|
||||
v-if="worldDialog.isQuest"
|
||||
class="x-tag-platform-quest"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
Android
|
||||
</el-tag>
|
||||
<span
|
||||
v-if="worldDialog.bundleSizes['android']"
|
||||
class="x-grey"
|
||||
style="margin-left: 5px; border-left: inherit; padding-left: 5px">
|
||||
{{ worldDialog.bundleSizes['android'].fileSize }}
|
||||
</span>
|
||||
<el-tag
|
||||
v-if="worldDialog.isIos"
|
||||
class="x-tag-platform-ios"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
iOS
|
||||
</el-tag>
|
||||
<span
|
||||
v-if="worldDialog.bundleSizes['ios']"
|
||||
class="x-grey"
|
||||
style="margin-left: 5px; border-left: inherit; padding-left: 5px">
|
||||
{{ worldDialog.bundleSizes['ios'].fileSize }}
|
||||
</span>
|
||||
<el-tag
|
||||
v-if="worldDialog.avatarScalingDisabled"
|
||||
type="warning"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.avatar_scaling_disabled') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.focusViewDisabled"
|
||||
type="warning"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.focus_view_disabled') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.stickersDisabled"
|
||||
type="warning"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.stickers_disabled') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.ref.unityPackageUrl"
|
||||
type="success"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
{{ $t('dialog.world.tags.future_proofing') }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="worldDialog.inCache"
|
||||
class="x-link"
|
||||
type="info"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px"
|
||||
@click="openFolderGeneric(worldDialog.cachePath)">
|
||||
<span v-text="worldDialog.cacheSize" />
|
||||
| {{ $t('dialog.world.tags.cache') }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div>
|
||||
<template v-for="tag in worldDialog.ref.tags">
|
||||
<el-tag
|
||||
v-if="tag.startsWith('content_')"
|
||||
:key="tag"
|
||||
effect="plain"
|
||||
size="mini"
|
||||
style="margin-right: 5px; margin-top: 5px">
|
||||
<template v-if="tag === 'content_horror'">
|
||||
{{ $t('dialog.world.tags.content_horror') }}
|
||||
</template>
|
||||
<template v-else-if="tag === 'content_gore'">
|
||||
{{ $t('dialog.world.tags.content_gore') }}
|
||||
</template>
|
||||
<template v-else-if="tag === 'content_violence'">
|
||||
{{ $t('dialog.world.tags.content_violence') }}
|
||||
</template>
|
||||
<template v-else-if="tag === 'content_adult'">
|
||||
{{ $t('dialog.world.tags.content_adult') }}
|
||||
</template>
|
||||
<template v-else-if="tag === 'content_sex'">
|
||||
{{ $t('dialog.world.tags.content_sex') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ tag.replace('content_', '') }}
|
||||
</template>
|
||||
</el-tag>
|
||||
</template>
|
||||
</div>
|
||||
<div style="margin-top: 5px">
|
||||
<span
|
||||
v-show="worldDialog.ref.name !== worldDialog.ref.description"
|
||||
style="font-size: 12px"
|
||||
>{{ worldDialog.ref.description }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div style="flex: none; margin-left: 10px">
|
||||
<el-tooltip
|
||||
v-if="worldDialog.inCache"
|
||||
placement="top"
|
||||
:content="$t('dialog.world.actions.delete_cache_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
icon="el-icon-delete"
|
||||
circle
|
||||
:disabled="isGameRunning && worldDialog.cacheLocked"
|
||||
@click="deleteVRChatCache(worldDialog.ref)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
v-if="worldDialog.isFavorite"
|
||||
placement="top"
|
||||
:content="$t('dialog.world.actions.favorites_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
type="default"
|
||||
:icon="worldDialog.isFavorite ? 'el-icon-star-on' : 'el-icon-star-off'"
|
||||
circle
|
||||
style="margin-left: 5px"
|
||||
@click="worldDialogCommand('Add Favorite')" />
|
||||
</el-tooltip>
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
size="small"
|
||||
style="margin-left: 5px"
|
||||
@command="worldDialogCommand">
|
||||
<el-button type="default" icon="el-icon-more" circle />
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item icon="el-icon-refresh" command="Refresh">
|
||||
{{ $t('dialog.world.actions.refresh') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-share" command="Share">
|
||||
{{ $t('dialog.world.actions.share') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-s-flag" command="New Instance" divided>
|
||||
{{ $t('dialog.world.actions.new_instance') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-message" command="New Instance and Self Invite">
|
||||
{{ $t('dialog.world.actions.new_instance_and_self_invite') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="
|
||||
API.currentUser.$homeLocation &&
|
||||
API.currentUser.$homeLocation.worldId === worldDialog.id
|
||||
"
|
||||
icon="el-icon-magic-stick"
|
||||
command="Reset Home"
|
||||
divided>
|
||||
{{ $t('dialog.world.actions.reset_home') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-else icon="el-icon-s-home" command="Make Home" divided>
|
||||
{{ $t('dialog.world.actions.make_home') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-tickets" command="Previous Instances">
|
||||
{{ $t('dialog.world.actions.show_previous_instances') }}
|
||||
</el-dropdown-item>
|
||||
<template v-if="API.currentUser.id !== worldDialog.ref.authorId">
|
||||
<el-dropdown-item icon="el-icon-picture-outline" command="Previous Images">
|
||||
{{ $t('dialog.world.actions.show_previous_images') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:disabled="!worldDialog.hasPersistData"
|
||||
icon="el-icon-upload"
|
||||
command="Delete Persistent Data">
|
||||
{{ $t('dialog.world.actions.delete_persistent_data') }}
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Rename">
|
||||
{{ $t('dialog.world.actions.rename') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Description">
|
||||
{{ $t('dialog.world.actions.change_description') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Capacity">
|
||||
{{ $t('dialog.world.actions.change_capacity') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Recommended Capacity">
|
||||
{{ $t('dialog.world.actions.change_recommended_capacity') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change YouTube Preview">
|
||||
{{ $t('dialog.world.actions.change_preview') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Tags">
|
||||
{{ $t('dialog.world.actions.change_tags') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-edit" command="Change Allowed Domains">
|
||||
{{ $t('dialog.world.actions.change_allowed_video_player_domains') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-picture-outline" command="Change Image">
|
||||
{{ $t('dialog.world.actions.change_image') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="worldDialog.ref.unityPackageUrl"
|
||||
icon="el-icon-download"
|
||||
command="Download Unity Package">
|
||||
{{ $t('dialog.world.actions.download_package') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="
|
||||
worldDialog.ref?.tags?.includes('system_approved') ||
|
||||
worldDialog.ref?.tags?.includes('system_labs')
|
||||
"
|
||||
icon="el-icon-view"
|
||||
command="Unpublish"
|
||||
divided>
|
||||
{{ $t('dialog.world.actions.unpublish') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-else icon="el-icon-view" command="Publish" divided>
|
||||
{{ $t('dialog.world.actions.publish_to_labs') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:disabled="!worldDialog.hasPersistData"
|
||||
icon="el-icon-upload"
|
||||
command="Delete Persistent Data">
|
||||
{{ $t('dialog.world.actions.delete_persistent_data') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-delete" command="Delete" style="color: #f56c6c">
|
||||
{{ $t('dialog.world.actions.delete') }}
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-tabs>
|
||||
<el-tab-pane :label="$t('dialog.world.instances.header')">
|
||||
<div class="">
|
||||
<i class="el-icon-user" />
|
||||
{{ $t('dialog.world.instances.public_count', { count: worldDialog.ref.publicOccupants }) }}
|
||||
<i class="el-icon-user-solid" style="margin-left: 10px" />
|
||||
{{ $t('dialog.world.instances.private_count', { count: worldDialog.ref.privateOccupants }) }}
|
||||
<i class="el-icon-check" style="margin-left: 10px" />
|
||||
{{
|
||||
$t('dialog.world.instances.capacity_count', {
|
||||
count: worldDialog.ref.recommendedCapacity,
|
||||
max: worldDialog.ref.capacity
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
<div v-for="room in worldDialog.rooms" :key="room.id">
|
||||
<div style="margin: 5px 0">
|
||||
<location-world
|
||||
:locationobject="room.$location"
|
||||
:currentuserid="API.currentUser.id"
|
||||
:worlddialogshortname="worldDialog.$location.shortName"
|
||||
@show-launch-dialog="showLaunchDialog" />
|
||||
<launch
|
||||
:location="room.tag"
|
||||
style="margin-left: 5px"
|
||||
@show-launch-dialog="showLaunchDialog" />
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
:content="$t('dialog.world.instances.self_invite_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<invite-yourself
|
||||
:location="room.$location.tag"
|
||||
:shortname="room.$location.shortName"
|
||||
style="margin-left: 5px" />
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
:content="$t('dialog.world.instances.refresh_instance_info')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-refresh"
|
||||
style="margin-left: 5px"
|
||||
circle
|
||||
@click="refreshInstancePlayerCount(room.tag)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
v-if="instanceJoinHistory.get(room.$location.tag)"
|
||||
placement="top"
|
||||
:content="$t('dialog.previous_instances.info')"
|
||||
:disabled="hideTooltips">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-s-data"
|
||||
style="margin-left: 5px"
|
||||
plain
|
||||
circle
|
||||
@click="showPreviousInstanceInfoDialog(room.location)" />
|
||||
</el-tooltip>
|
||||
<last-join :location="room.$location.tag" :currentlocation="lastLocation.location" />
|
||||
<instance-info
|
||||
:location="room.tag"
|
||||
:instance="room.ref"
|
||||
:friendcount="room.friendCount"
|
||||
:updateelement="updateInstanceInfo" />
|
||||
<div
|
||||
v-if="room.$location.userId || room.users.length"
|
||||
class="x-friend-list"
|
||||
style="margin: 10px 0; max-height: unset">
|
||||
<div
|
||||
v-if="room.$location.userId"
|
||||
class="x-friend-item x-friend-item-border"
|
||||
@click="showUserDialog(room.$location.userId)">
|
||||
<template v-if="room.$location.user">
|
||||
<div class="avatar" :class="userStatusClass(room.$location.user)">
|
||||
<img v-lazy="userImage(room.$location.user)" />
|
||||
</div>
|
||||
<div class="detail">
|
||||
<span
|
||||
class="name"
|
||||
:style="{ color: room.$location.user.$userColour }"
|
||||
v-text="room.$location.user.displayName" />
|
||||
<span class="extra">
|
||||
{{ $t('dialog.world.instances.instance_creator') }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<span v-else v-text="room.$location.userId" />
|
||||
</div>
|
||||
<div
|
||||
v-for="user in room.users"
|
||||
:key="user.id"
|
||||
class="x-friend-item x-friend-item-border"
|
||||
@click="showUserDialog(user.id)">
|
||||
<div class="avatar" :class="userStatusClass(user)">
|
||||
<img v-lazy="userImage(user)" />
|
||||
</div>
|
||||
<div class="detail">
|
||||
<span
|
||||
class="name"
|
||||
:style="{ color: user.$userColour }"
|
||||
v-text="user.displayName" />
|
||||
<span v-if="user.location === 'traveling'" class="extra">
|
||||
<i class="el-icon-loading" style="margin-right: 5px" />
|
||||
<timer :epoch="user.$travelingToTime" />
|
||||
</span>
|
||||
<span v-else class="extra">
|
||||
<timer :epoch="user.$location_at" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('dialog.world.info.header')" lazy>
|
||||
<div class="x-friend-list" style="max-height: none">
|
||||
<div class="x-friend-item" style="width: 100%; cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.memo') }}
|
||||
</span>
|
||||
<el-input
|
||||
v-model="worldDialog.memo"
|
||||
class="extra"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
:autosize="{ minRows: 1, maxRows: 20 }"
|
||||
:placeholder="$t('dialog.world.info.memo_placeholder')"
|
||||
size="mini"
|
||||
resize="none"
|
||||
@change="onWorldMemoChange" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 100%; display: flex">
|
||||
<div class="x-friend-item" style="width: 100%; cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.id') }}
|
||||
</span>
|
||||
<span class="extra" style="display: inline">
|
||||
{{ worldDialog.id }}
|
||||
</span>
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
:content="$t('dialog.world.info.id_tooltip')"
|
||||
:disabled="hideTooltips">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
size="mini"
|
||||
style="margin-left: 5px"
|
||||
@click.native.stop>
|
||||
<el-button type="default" icon="el-icon-s-order" size="mini" circle />
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="copyWorldId(worldDialog.id)">
|
||||
{{ $t('dialog.world.info.copy_id') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="copyWorldUrl(worldDialog.id)">
|
||||
{{ $t('dialog.world.info.copy_url') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="copyWorldName(worldDialog.ref.name)">
|
||||
{{ $t('dialog.world.info.copy_name') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="worldDialog.ref.previewYoutubeId"
|
||||
class="x-friend-item"
|
||||
style="width: 350px"
|
||||
@click="
|
||||
openExternalLink(`https://www.youtube.com/watch?v=${worldDialog.ref.previewYoutubeId}`)
|
||||
">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.youtube_preview') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
https://www.youtube.com/watch?v={{ worldDialog.ref.previewYoutubeId }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="width: 100%; cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.author_tags') }}
|
||||
</span>
|
||||
<span
|
||||
v-if="
|
||||
worldDialog.ref.tags?.filter((tag) => tag.startsWith('author_tag')).length > 0
|
||||
"
|
||||
class="extra">
|
||||
{{ worldTags }}
|
||||
</span>
|
||||
<span v-else class="extra"> - </span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.players') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.occupants | commaNumber }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.favorites') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.favorites | commaNumber
|
||||
}}<span
|
||||
v-if="worldDialog.ref?.favorites > 0 && worldDialog.ref?.visits > 0"
|
||||
class="extra">
|
||||
({{ favoriteRate }}%)
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.visits') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.visits | commaNumber }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.capacity') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.recommendedCapacity | commaNumber }} ({{
|
||||
worldDialog.ref.capacity | commaNumber
|
||||
}})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.created_at') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.created_at | formatDate('long') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.last_updated') }}
|
||||
</span>
|
||||
<span v-if="worldDialog.lastUpdated" class="extra">
|
||||
{{ worldDialog.lastUpdated | formatDate('long') }}
|
||||
</span>
|
||||
<span v-else class="extra">
|
||||
{{ worldDialog.ref.updated_at | formatDate('long') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="worldDialog.ref.labsPublicationDate !== 'none'"
|
||||
class="x-friend-item"
|
||||
style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.labs_publication_date') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.labsPublicationDate | formatDate('long') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="worldDialog.ref.publicationDate !== 'none'"
|
||||
class="x-friend-item"
|
||||
style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name" style="display: inline">
|
||||
{{ $t('dialog.world.info.publication_date') }}
|
||||
</span>
|
||||
<el-tooltip v-if="isTimeInLabVisible" placement="top" style="margin-left: 5px">
|
||||
<template slot="content">
|
||||
<span>
|
||||
{{ $t('dialog.world.info.time_in_labs') }}
|
||||
{{ timeInLab }}
|
||||
</span>
|
||||
</template>
|
||||
<i class="el-icon-arrow-down" />
|
||||
</el-tooltip>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.publicationDate | formatDate('long') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.version') }}
|
||||
</span>
|
||||
<span class="extra" v-text="worldDialog.ref.version" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.heat') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.heat | commaNumber }} {{ '🔥'.repeat(worldDialog.ref.heat) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.popularity') }}
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.ref.popularity | commaNumber }}
|
||||
{{ '💖'.repeat(worldDialog.ref.popularity) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="width: 100%; cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.platform') }}
|
||||
</span>
|
||||
<span class="extra" style="white-space: normal">{{ worldDialogPlatform }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.last_visited') }}
|
||||
<el-tooltip
|
||||
v-if="!hideTooltips"
|
||||
placement="top"
|
||||
style="margin-left: 5px"
|
||||
:content="$t('dialog.world.info.accuracy_notice')"
|
||||
><i class="el-icon-warning"></i
|
||||
></el-tooltip>
|
||||
</span>
|
||||
<span class="extra">{{ worldDialog.lastVisit | formatDate('long') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-tooltip
|
||||
:disabled="hideTooltips"
|
||||
placement="top"
|
||||
:content="$t('dialog.user.info.open_previouse_instance')">
|
||||
<div class="x-friend-item" @click="showPreviousInstancesWorldDialog(worldDialog.ref)">
|
||||
<div class="detail">
|
||||
<span class="name">
|
||||
{{ $t('dialog.world.info.visit_count') }}
|
||||
<el-tooltip
|
||||
v-if="!hideTooltips"
|
||||
placement="top"
|
||||
style="margin-left: 5px"
|
||||
:content="$t('dialog.world.info.accuracy_notice')"
|
||||
><i class="el-icon-warning"></i
|
||||
></el-tooltip>
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.visitCount }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name"
|
||||
>{{ $t('dialog.world.info.time_spent') }}
|
||||
<el-tooltip
|
||||
v-if="!hideTooltips"
|
||||
placement="top"
|
||||
style="margin-left: 5px"
|
||||
:content="$t('dialog.world.info.accuracy_notice')">
|
||||
<i class="el-icon-warning"></i>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<span class="extra">
|
||||
{{ worldDialog.timeSpent === 0 ? ' - ' : timeSpent }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('dialog.world.json.header')" style="max-height: 50vh" lazy>
|
||||
<el-button
|
||||
type="default"
|
||||
size="mini"
|
||||
icon="el-icon-refresh"
|
||||
circle
|
||||
@click="refreshWorldDialogTreeData()"></el-button>
|
||||
<el-button
|
||||
type="default"
|
||||
size="mini"
|
||||
icon="el-icon-download"
|
||||
circle
|
||||
style="margin-left: 5px"
|
||||
@click="downloadAndSaveJson(worldDialog.id, worldDialog.ref)"></el-button>
|
||||
<el-tree :data="treeData" style="margin-top: 5px; font-size: 12px">
|
||||
<template slot-scope="scope">
|
||||
<span>
|
||||
<span style="font-weight: bold; margin-right: 5px" v-text="scope.data.key"></span>
|
||||
<span v-if="!scope.data.children" v-text="scope.data.value"></span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import utils from '../../classes/utils';
|
||||
import database from '../../repository/database.js';
|
||||
export default {
|
||||
name: 'WorldDialog',
|
||||
inject: ['API', 'showUserDialog', 'userStatusClass', 'userImage', 'adjustDialogZ'],
|
||||
props: {
|
||||
worldDialog: Object,
|
||||
hideTooltips: Boolean,
|
||||
isGameRunning: Boolean,
|
||||
lastLocation: Object,
|
||||
instanceJoinHistory: Map,
|
||||
|
||||
// ok
|
||||
updateInstanceInfo: Number
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
treeData: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isTimeInLabVisible() {
|
||||
return (
|
||||
this.worldDialog.ref.publicationDate &&
|
||||
this.worldDialog.ref.publicationDate !== 'none' &&
|
||||
this.worldDialog.ref.labsPublicationDate &&
|
||||
this.worldDialog.ref.labsPublicationDate !== 'none'
|
||||
);
|
||||
},
|
||||
|
||||
timeInLab() {
|
||||
return utils.timeToText(
|
||||
new Date(this.worldDialog.ref?.publicationDate) -
|
||||
new Date(this.worldDialog.ref?.labsPublicationDate)
|
||||
);
|
||||
},
|
||||
favoriteRate() {
|
||||
return (
|
||||
Math.round(
|
||||
(((this.worldDialog.ref?.favorites - this.worldDialog.ref?.visits) /
|
||||
this.worldDialog.ref?.visits) *
|
||||
100 +
|
||||
100) *
|
||||
100
|
||||
) / 100
|
||||
);
|
||||
},
|
||||
worldTags() {
|
||||
return this.worldDialog.ref?.tags
|
||||
.filter((tag) => tag.startsWith('author_tag'))
|
||||
.map((tag) => tag.replace('author_tag_', ''))
|
||||
.join(', ');
|
||||
},
|
||||
timeSpent() {
|
||||
return utils.timeToText(this.worldDialog.timeSpent);
|
||||
},
|
||||
worldDialogPlatform() {
|
||||
const { ref } = this.worldDialog;
|
||||
const platforms = [];
|
||||
if (ref.unityPackages) {
|
||||
for (const unityPackage of ref.unityPackages) {
|
||||
let platform = 'PC';
|
||||
if (unityPackage.platform === 'standalonewindows') {
|
||||
platform = 'PC';
|
||||
} else if (unityPackage.platform === 'android') {
|
||||
platform = 'Android';
|
||||
} else if (unityPackage.platform) {
|
||||
({ platform } = unityPackage);
|
||||
}
|
||||
platforms.unshift(`${platform}/${unityPackage.unityVersion}`);
|
||||
}
|
||||
}
|
||||
return platforms.join(', ');
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'worldDialog.visible'(value) {
|
||||
if (value) {
|
||||
this.$nextTick(() => this.adjustDialogZ(this.$refs.worldDialog.$el));
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showFullscreenImageDialog(imageUrl) {
|
||||
this.$emit('show-fullscreen-image-dialog', imageUrl);
|
||||
},
|
||||
openFolderGeneric(path) {
|
||||
this.$emit('open-folder-generic', path);
|
||||
},
|
||||
deleteVRChatCache(world) {
|
||||
this.$emit('delete-vrchat-cache', world);
|
||||
},
|
||||
worldDialogCommand(command) {
|
||||
if (command === 'Share') {
|
||||
this.copyWorldUrl();
|
||||
} else {
|
||||
this.$emit('world-dialog-command', command);
|
||||
}
|
||||
},
|
||||
showLaunchDialog(location, shortName) {
|
||||
this.$emit('show-launch-dialog', location, shortName);
|
||||
},
|
||||
refreshInstancePlayerCount(tag) {
|
||||
this.$emit('refresh-instance-player-count', tag);
|
||||
},
|
||||
showPreviousInstanceInfoDialog(location) {
|
||||
this.$emit('show-previous-instance-info-dialog', location);
|
||||
},
|
||||
onWorldMemoChange() {
|
||||
const worldId = this.worldDialog.id;
|
||||
const memo = this.worldDialog.memo;
|
||||
if (memo) {
|
||||
database.setWorldMemo({
|
||||
worldId,
|
||||
editedAt: new Date().toJSON(),
|
||||
memo
|
||||
});
|
||||
} else {
|
||||
database.deleteWorldMemo(id);
|
||||
}
|
||||
},
|
||||
showPreviousInstancesWorldDialog(world) {
|
||||
this.$emit('show-previous-instances-world-dialog', world);
|
||||
},
|
||||
refreshWorldDialogTreeData() {
|
||||
this.treeData = utils.buildTreeData(this.worldDialog.ref);
|
||||
},
|
||||
downloadAndSaveJson(id, ref) {
|
||||
this.$emit('download-and-save-json', id, ref);
|
||||
},
|
||||
copyWorldId() {
|
||||
navigator.clipboard
|
||||
.writeText(this.worldDialog.id)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
message: 'World ID copied to clipboard',
|
||||
type: 'success'
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('copy failed:', err);
|
||||
this.$message({
|
||||
message: 'Copy failed',
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
copyWorldUrl() {
|
||||
navigator.clipboard
|
||||
.writeText(`https://vrchat.com/home/world/${this.worldDialog.id}`)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
message: 'World URL copied to clipboard',
|
||||
type: 'success'
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('copy failed:', err);
|
||||
this.$message({
|
||||
message: 'Copy failed',
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
copyWorldName() {
|
||||
navigator.clipboard
|
||||
.writeText(this.worldDialog.ref.name)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
message: 'World name copied to clipboard',
|
||||
type: 'success'
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('copy failed:', err);
|
||||
this.$message({
|
||||
message: 'Copy failed',
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user