<template>
    <safe-dialog
        ref="userDialogRef"
        class="x-dialog x-user-dialog"
        :visible.sync="userDialog.visible"
        :show-close="false"
        width="770px"
        top="10vh">
        <div v-loading="userDialog.loading">
            <div style="display: flex">
                <el-popover
                    v-if="userDialog.ref.profilePicOverrideThumbnail || userDialog.ref.profilePicOverride"
                    placement="right"
                    width="500px"
                    trigger="click">
                    <img
                        slot="reference"
                        class="x-link"
                        :src="userDialog.ref.profilePicOverrideThumbnail || userDialog.ref.profilePicOverride"
                        style="flex: none; height: 120px; width: 213.33px; border-radius: 12px; object-fit: cover" />
                    <img
                        v-lazy="userDialog.ref.profilePicOverride"
                        class="x-link"
                        style="height: 400px"
                        @click="showFullscreenImageDialog(userDialog.ref.profilePicOverride)" />
                </el-popover>
                <el-popover v-else placement="right" width="500px" trigger="click">
                    <img
                        slot="reference"
                        class="x-link"
                        :src="userDialog.ref.currentAvatarThumbnailImageUrl"
                        style="flex: none; height: 120px; width: 160px; border-radius: 12px; object-fit: cover" />
                    <img
                        v-lazy="userDialog.ref.currentAvatarImageUrl"
                        class="x-link"
                        style="height: 500px"
                        @click="showFullscreenImageDialog(userDialog.ref.currentAvatarImageUrl)" />
                </el-popover>

                <div style="flex: 1; display: flex; align-items: center; margin-left: 15px">
                    <div style="flex: 1">
                        <div>
                            <el-tooltip v-if="userDialog.ref.status" placement="top">
                                <template #content>
                                    <span v-if="userDialog.ref.state === 'active'">{{
                                        t('dialog.user.status.active')
                                    }}</span>
                                    <span v-else-if="userDialog.ref.state === 'offline'">{{
                                        t('dialog.user.status.offline')
                                    }}</span>
                                    <span v-else-if="userDialog.ref.status === 'active'">{{
                                        t('dialog.user.status.online')
                                    }}</span>
                                    <span v-else-if="userDialog.ref.status === 'join me'">{{
                                        t('dialog.user.status.join_me')
                                    }}</span>
                                    <span v-else-if="userDialog.ref.status === 'ask me'">{{
                                        t('dialog.user.status.ask_me')
                                    }}</span>
                                    <span v-else-if="userDialog.ref.status === 'busy'">{{
                                        t('dialog.user.status.busy')
                                    }}</span>
                                    <span v-else>{{ t('dialog.user.status.offline') }}</span>
                                </template>
                                <i class="x-user-status" :class="userStatusClass(userDialog.ref)"></i>
                            </el-tooltip>
                            <template v-if="userDialog.previousDisplayNames.length > 0">
                                <el-tooltip placement="bottom">
                                    <template #content>
                                        <span>{{ t('dialog.user.previous_display_names') }}</span>
                                        <div
                                            v-for="displayName in userDialog.previousDisplayNames"
                                            :key="displayName"
                                            placement="top">
                                            <span v-text="displayName"></span>
                                        </div>
                                    </template>
                                    <i class="el-icon-caret-bottom"></i>
                                </el-tooltip>
                            </template>
                            <el-popover placement="top" trigger="click">
                                <span
                                    slot="reference"
                                    class="dialog-title"
                                    style="margin-left: 5px; margin-right: 5px; cursor: pointer"
                                    v-text="userDialog.ref.displayName"></span>
                                <span style="display: block; text-align: center; font-family: monospace">{{
                                    userDialog.ref.displayName | textToHex
                                }}</span>
                            </el-popover>
                            <el-tooltip
                                v-if="userDialog.ref.pronouns"
                                placement="top"
                                :content="t('dialog.user.pronouns')"
                                :disabled="hideTooltips">
                                <span
                                    class="x-grey"
                                    style="margin-right: 5px; font-family: monospace; font-size: 12px"
                                    v-text="userDialog.ref.pronouns"></span>
                            </el-tooltip>
                            <el-tooltip v-for="item in userDialog.ref.$languages" :key="item.key" placement="top">
                                <template #content>
                                    <span>{{ item.value }} ({{ item.key }})</span>
                                </template>
                                <span
                                    class="flags"
                                    :class="languageClass(item.key)"
                                    style="display: inline-block; margin-right: 5px"></span>
                            </el-tooltip>
                            <template v-if="userDialog.ref.id === API.currentUser.id">
                                <br />
                                <el-popover placement="top" trigger="click">
                                    <span
                                        slot="reference"
                                        class="x-grey"
                                        style="
                                            margin-right: 10px;
                                            font-family: monospace;
                                            font-size: 12px;
                                            cursor: pointer;
                                        "
                                        v-text="API.currentUser.username"></span>
                                    <span style="display: block; text-align: center; font-family: monospace">{{
                                        API.currentUser.username | textToHex
                                    }}</span>
                                </el-popover>
                            </template>
                        </div>
                        <div style="margin-top: 5px">
                            <el-tag
                                type="info"
                                effect="plain"
                                size="mini"
                                class="name"
                                :class="userDialog.ref.$trustClass"
                                style="margin-right: 5px; margin-top: 5px"
                                v-text="userDialog.ref.$trustLevel"></el-tag>
                            <el-tag
                                v-if="userDialog.isFriend && userDialog.friend"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="x-tag-friend"
                                style="margin-right: 5px; margin-top: 5px">
                                {{
                                    t('dialog.user.tags.friend_no', {
                                        number: userDialog.ref.$friendNumber ? userDialog.ref.$friendNumber : ''
                                    })
                                }}
                            </el-tag>
                            <el-tag
                                v-if="userDialog.ref.$isTroll"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="x-tag-troll"
                                style="margin-right: 5px; margin-top: 5px">
                                Nuisance
                            </el-tag>
                            <el-tag
                                v-if="userDialog.ref.$isProbableTroll"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="x-tag-troll"
                                style="margin-right: 5px; margin-top: 5px">
                                Almost Nuisance
                            </el-tag>
                            <el-tag
                                v-if="userDialog.ref.$isModerator"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="x-tag-vip"
                                style="margin-right: 5px; margin-top: 5px">
                                {{ t('dialog.user.tags.vrchat_team') }}
                            </el-tag>
                            <el-tag
                                v-if="userDialog.ref.last_platform === 'standalonewindows'"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="x-tag-platform-pc"
                                style="margin-right: 5px; margin-top: 5px">
                                PC
                            </el-tag>
                            <el-tag
                                v-else-if="userDialog.ref.last_platform === 'android'"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="x-tag-platform-quest"
                                style="margin-right: 5px; margin-top: 5px">
                                Android
                            </el-tag>
                            <el-tag
                                v-else-if="userDialog.ref.last_platform === 'ios'"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="x-tag-platform-ios"
                                style="margin-right: 5px; margin-top: 5px"
                                >iOS</el-tag
                            >
                            <el-tag
                                v-else-if="userDialog.ref.last_platform"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="x-tag-platform-other"
                                style="margin-right: 5px; margin-top: 5px">
                                {{ userDialog.ref.last_platform }}
                            </el-tag>
                            <el-tag
                                v-if="userDialog.ref.ageVerified || userDialog.ref.ageVerificationStatus !== 'hidden'"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="x-tag-age-verification"
                                style="margin-right: 5px; margin-top: 5px">
                                {{ userDialog.ref.ageVerificationStatus }}
                            </el-tag>
                            <el-tag
                                v-if="userDialog.ref.$customTag"
                                type="info"
                                effect="plain"
                                size="mini"
                                class="name"
                                :style="{
                                    color: userDialog.ref.$customTagColour,
                                    'border-color': userDialog.ref.$customTagColour
                                }"
                                style="margin-right: 5px; margin-top: 5px"
                                v-text="userDialog.ref.$customTag"></el-tag>
                            <br />
                            <template v-for="badge in userDialog.ref.badges">
                                <el-tooltip :key="badge.badgeId" placement="top">
                                    <template #content>
                                        <span>{{ badge.badgeName }}</span>
                                        <span v-if="badge.hidden">&nbsp;(Hidden)</span>
                                    </template>
                                    <el-popover placement="right" width="300px" trigger="click">
                                        <img
                                            slot="reference"
                                            class="x-link x-user-badge"
                                            :src="badge.badgeImageUrl"
                                            style="
                                                flex: none;
                                                height: 32px;
                                                width: 32px;
                                                border-radius: 3px;
                                                object-fit: cover;
                                                margin-top: 5px;
                                                margin-right: 5px;
                                            "
                                            :class="{ 'x-user-badge-hidden': badge.hidden }" />
                                        <img
                                            v-lazy="badge.badgeImageUrl"
                                            class="x-link"
                                            style="width: 300px"
                                            @click="showFullscreenImageDialog(badge.badgeImageUrl)" />
                                        <br />
                                        <div style="display: block; width: 300px; word-break: normal">
                                            <span>{{ badge.badgeName }}</span>
                                            <br />
                                            <span class="x-grey" style="font-size: 12px">{{
                                                badge.badgeDescription
                                            }}</span>
                                            <br />
                                            <span
                                                v-if="badge.assignedAt"
                                                class="x-grey"
                                                style="font-family: monospace; font-size: 12px">
                                                {{ t('dialog.user.badges.assigned') }}:
                                                {{ badge.assignedAt | formatDate('long') }}
                                            </span>
                                            <template v-if="userDialog.id === API.currentUser.id">
                                                <br />
                                                <el-checkbox
                                                    v-model="badge.hidden"
                                                    style="margin-top: 5px"
                                                    @change="toggleBadgeVisibility(badge)">
                                                    {{ t('dialog.user.badges.hidden') }}
                                                </el-checkbox>
                                                <br />
                                                <el-checkbox
                                                    v-model="badge.showcased"
                                                    style="margin-top: 5px"
                                                    @change="toggleBadgeShowcased(badge)">
                                                    {{ t('dialog.user.badges.showcased') }}
                                                </el-checkbox>
                                            </template>
                                        </div>
                                    </el-popover>
                                </el-tooltip>
                            </template>
                        </div>
                        <div style="margin-top: 5px">
                            <span style="font-size: 12px" v-text="userDialog.ref.statusDescription"></span>
                        </div>
                    </div>

                    <div v-if="userDialog.ref.userIcon" style="flex: none; margin-right: 10px">
                        <el-popover placement="right" width="500px" trigger="click">
                            <img
                                slot="reference"
                                class="x-link"
                                :src="userImage(userDialog.ref, true, '256', true)"
                                style="
                                    flex: none;
                                    width: 120px;
                                    height: 120px;
                                    border-radius: 12px;
                                    object-fit: cover;
                                " />
                            <img
                                v-lazy="userDialog.ref.userIcon"
                                class="x-link"
                                style="height: 500px"
                                @click="showFullscreenImageDialog(userDialog.ref.userIcon)" />
                        </el-popover>
                    </div>

                    <div style="flex: none">
                        <template
                            v-if="
                                (API.currentUser.id !== userDialog.ref.id && userDialog.isFriend) ||
                                userDialog.isFavorite
                            ">
                            <el-tooltip
                                v-if="userDialog.isFavorite"
                                placement="top"
                                :content="t('dialog.user.actions.unfavorite_tooltip')"
                                :disabled="hideTooltips">
                                <el-button
                                    type="warning"
                                    icon="el-icon-star-on"
                                    circle
                                    @click="userDialogCommand('Add Favorite')"></el-button>
                            </el-tooltip>
                            <el-tooltip
                                v-else
                                placement="top"
                                :content="t('dialog.user.actions.favorite_tooltip')"
                                :disabled="hideTooltips">
                                <el-button
                                    type="default"
                                    icon="el-icon-star-off"
                                    circle
                                    @click="userDialogCommand('Add Favorite')"></el-button>
                            </el-tooltip>
                        </template>
                        <el-dropdown trigger="click" size="small" @command="userDialogCommand">
                            <el-button
                                :type="
                                    userDialog.incomingRequest || userDialog.outgoingRequest
                                        ? 'success'
                                        : userDialog.isBlock || userDialog.isMute
                                          ? 'danger'
                                          : 'default'
                                "
                                icon="el-icon-more"
                                circle
                                style="margin-left: 5px"></el-button>
                            <el-dropdown-menu slot="dropdown">
                                <el-dropdown-item icon="el-icon-refresh" command="Refresh">{{
                                    t('dialog.user.actions.refresh')
                                }}</el-dropdown-item>
                                <el-dropdown-item icon="el-icon-share" command="Share">{{
                                    t('dialog.user.actions.share')
                                }}</el-dropdown-item>
                                <template v-if="userDialog.ref.id === API.currentUser.id">
                                    <el-dropdown-item icon="el-icon-picture-outline" command="Manage Gallery" divided>{{
                                        t('dialog.user.actions.manage_gallery_icon')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-s-custom" command="Show Avatar Author">{{
                                        t('dialog.user.actions.show_avatar_author')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-s-custom" command="Show Fallback Avatar Details">{{
                                        t('dialog.user.actions.show_fallback_avatar')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-edit" command="Edit Social Status" divided>{{
                                        t('dialog.user.actions.edit_status')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-edit" command="Edit Language">{{
                                        t('dialog.user.actions.edit_language')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-edit" command="Edit Bio">{{
                                        t('dialog.user.actions.edit_bio')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-edit" command="Edit Pronouns">{{
                                        t('dialog.user.actions.edit_pronouns')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-switch-button" command="Logout" divided>{{
                                        t('dialog.user.actions.logout')
                                    }}</el-dropdown-item>
                                </template>
                                <template v-else>
                                    <template v-if="userDialog.isFriend">
                                        <el-dropdown-item icon="el-icon-postcard" command="Request Invite" divided>{{
                                            t('dialog.user.actions.request_invite')
                                        }}</el-dropdown-item>
                                        <el-dropdown-item icon="el-icon-postcard" command="Request Invite Message">{{
                                            t('dialog.user.actions.request_invite_with_message')
                                        }}</el-dropdown-item>
                                        <template
                                            v-if="
                                                lastLocation.location &&
                                                isGameRunning &&
                                                checkCanInvite(lastLocation.location)
                                            ">
                                            <el-dropdown-item icon="el-icon-message" command="Invite">{{
                                                t('dialog.user.actions.invite')
                                            }}</el-dropdown-item>
                                            <el-dropdown-item icon="el-icon-message" command="Invite Message">{{
                                                t('dialog.user.actions.invite_with_message')
                                            }}</el-dropdown-item>
                                        </template>
                                    </template>
                                    <template v-else-if="userDialog.incomingRequest">
                                        <el-dropdown-item icon="el-icon-check" command="Accept Friend Request">{{
                                            t('dialog.user.actions.accept_friend_request')
                                        }}</el-dropdown-item>
                                        <el-dropdown-item icon="el-icon-close" command="Decline Friend Request">{{
                                            t('dialog.user.actions.decline_friend_request')
                                        }}</el-dropdown-item>
                                    </template>
                                    <el-dropdown-item
                                        v-else-if="userDialog.outgoingRequest"
                                        icon="el-icon-close"
                                        command="Cancel Friend Request">
                                        {{ t('dialog.user.actions.cancel_friend_request') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item v-else icon="el-icon-plus" command="Send Friend Request">{{
                                        t('dialog.user.actions.send_friend_request')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-message" command="Invite To Group">{{
                                        t('dialog.user.actions.invite_to_group')
                                    }}</el-dropdown-item>
                                    <!--//- el-dropdown-item(icon="el-icon-thumb" command="Send Boop" :disabled="!API.currentUser.isBoopingEnabled") {{ t('dialog.user.actions.send_boop') }}-->
                                    <el-dropdown-item icon="el-icon-s-custom" command="Show Avatar Author" divided>{{
                                        t('dialog.user.actions.show_avatar_author')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-s-custom" command="Show Fallback Avatar Details">{{
                                        t('dialog.user.actions.show_fallback_avatar')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-tickets" command="Previous Instances">{{
                                        t('dialog.user.actions.show_previous_instances')
                                    }}</el-dropdown-item>
                                    <el-dropdown-item
                                        v-if="userDialog.ref.currentAvatarImageUrl"
                                        icon="el-icon-picture-outline"
                                        command="Previous Images">
                                        {{ t('dialog.user.actions.show_previous_images') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item
                                        v-if="userDialog.isBlock"
                                        icon="el-icon-circle-check"
                                        command="Moderation Unblock"
                                        divided
                                        style="color: #f56c6c">
                                        {{ t('dialog.user.actions.moderation_unblock') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item
                                        v-else
                                        icon="el-icon-circle-close"
                                        command="Moderation Block"
                                        divided
                                        :disabled="userDialog.ref.$isModerator">
                                        {{ t('dialog.user.actions.moderation_block') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item
                                        v-if="userDialog.isMute"
                                        icon="el-icon-microphone"
                                        command="Moderation Unmute"
                                        style="color: #f56c6c">
                                        {{ t('dialog.user.actions.moderation_unmute') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item
                                        v-else
                                        icon="el-icon-turn-off-microphone"
                                        command="Moderation Mute"
                                        :disabled="userDialog.ref.$isModerator">
                                        {{ t('dialog.user.actions.moderation_mute') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item
                                        v-if="userDialog.isMuteChat"
                                        icon="el-icon-chat-line-round"
                                        command="Moderation Enable Chatbox"
                                        style="color: #f56c6c">
                                        {{ t('dialog.user.actions.moderation_enable_chatbox') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item
                                        v-else
                                        icon="el-icon-chat-dot-round"
                                        command="Moderation Disable Chatbox">
                                        {{ t('dialog.user.actions.moderation_disable_chatbox') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-user-solid" command="Show Avatar">
                                        <i v-if="userDialog.isShowAvatar" class="el-icon-check el-icon--left"></i>
                                        <span>{{ t('dialog.user.actions.moderation_show_avatar') }}</span>
                                    </el-dropdown-item>
                                    <el-dropdown-item icon="el-icon-user" command="Hide Avatar">
                                        <i v-if="userDialog.isHideAvatar" class="el-icon-check el-icon--left"></i>
                                        <span>{{ t('dialog.user.actions.moderation_hide_avatar') }}</span>
                                    </el-dropdown-item>
                                    <el-dropdown-item
                                        v-if="userDialog.isInteractOff"
                                        icon="el-icon-thumb"
                                        command="Moderation Enable Avatar Interaction"
                                        style="color: #f56c6c">
                                        {{ t('dialog.user.actions.moderation_enable_avatar_interaction') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item
                                        v-else
                                        icon="el-icon-circle-close"
                                        command="Moderation Disable Avatar Interaction">
                                        {{ t('dialog.user.actions.moderation_disable_avatar_interaction') }}
                                    </el-dropdown-item>
                                    <el-dropdown-item
                                        icon="el-icon-s-flag"
                                        command="Report Hacking"
                                        :disabled="userDialog.ref.$isModerator">
                                        {{ t('dialog.user.actions.report_hacking') }}
                                    </el-dropdown-item>
                                    <template v-if="userDialog.isFriend">
                                        <el-dropdown-item
                                            icon="el-icon-delete"
                                            command="Unfriend"
                                            divided
                                            style="color: #f56c6c">
                                            {{ t('dialog.user.actions.unfriend') }}
                                        </el-dropdown-item>
                                    </template>
                                </template>
                            </el-dropdown-menu>
                        </el-dropdown>
                    </div>
                </div>
            </div>

            <el-tabs ref="userDialogTabsRef" @tab-click="userDialogTabClick">
                <el-tab-pane :label="t('dialog.user.info.header')">
                    <template v-if="isFriendOnline(userDialog.friend) || API.currentUser.id === userDialog.id">
                        <div
                            v-if="userDialog.ref.location"
                            style="
                                display: flex;
                                flex-direction: column;
                                margin-bottom: 10px;
                                padding-bottom: 10px;
                                border-bottom: 1px solid #e4e7ed14;
                            ">
                            <div style="flex: none">
                                <template v-if="isRealInstance(userDialog.$location.tag)">
                                    <launch
                                        :location="userDialog.$location.tag"
                                        @show-launch-dialog="showLaunchDialog"></launch>
                                    <el-tooltip
                                        placement="top"
                                        :content="t('dialog.user.info.self_invite_tooltip')"
                                        :disabled="hideTooltips">
                                        <invite-yourself
                                            :location="userDialog.$location.tag"
                                            :shortname="userDialog.$location.shortName"
                                            style="margin-left: 5px"></invite-yourself>
                                    </el-tooltip>
                                    <el-tooltip
                                        placement="top"
                                        :content="t('dialog.user.info.refresh_instance_info')"
                                        :disabled="hideTooltips">
                                        <el-button
                                            size="mini"
                                            icon="el-icon-refresh"
                                            style="margin-left: 5px"
                                            circle
                                            @click="refreshInstancePlayerCount(userDialog.$location.tag)"></el-button>
                                    </el-tooltip>
                                    <last-join
                                        :location="userDialog.$location.tag"
                                        :currentlocation="lastLocation.location"></last-join>
                                    <instance-info
                                        :location="userDialog.$location.tag"
                                        :instance="userDialog.instance.ref"
                                        :friendcount="userDialog.instance.friendCount"
                                        :updateelement="updateInstanceInfo"></instance-info>
                                </template>
                                <location
                                    :location="userDialog.ref.location"
                                    :traveling="userDialog.ref.travelingToLocation"
                                    style="display: block; margin-top: 5px"></location>
                            </div>
                            <div class="x-friend-list" style="flex: 1; margin-top: 10px; max-height: 150px">
                                <div
                                    v-if="userDialog.$location.userId"
                                    class="x-friend-item x-friend-item-border"
                                    @click="showUserDialog(userDialog.$location.userId)">
                                    <template v-if="userDialog.$location.user">
                                        <div class="avatar" :class="userStatusClass(userDialog.$location.user)">
                                            <img :src="userImage(userDialog.$location.user, true)" />
                                        </div>
                                        <div class="detail">
                                            <span
                                                class="name"
                                                :style="{ color: userDialog.$location.user.$userColour }"
                                                v-text="userDialog.$location.user.displayName"></span>
                                            <span class="extra">{{ t('dialog.user.info.instance_creator') }}</span>
                                        </div>
                                    </template>
                                    <span v-else v-text="userDialog.$location.userId"></span>
                                </div>
                                <div
                                    v-for="user in userDialog.users"
                                    :key="user.id"
                                    class="x-friend-item x-friend-item-border"
                                    @click="showUserDialog(user.id)">
                                    <div class="avatar" :class="userStatusClass(user)">
                                        <img :src="userImage(user, true)" />
                                    </div>
                                    <div class="detail">
                                        <span
                                            class="name"
                                            :style="{ color: user.$userColour }"
                                            v-text="user.displayName"></span>
                                        <span v-if="user.location === 'traveling'" class="extra">
                                            <i class="el-icon-loading" style="margin-right: 5px"></i>
                                            <timer :epoch="user.$travelingToTime"></timer>
                                        </span>
                                        <span v-else class="extra">
                                            <timer :epoch="user.$location_at"></timer>
                                        </span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </template>

                    <div class="x-friend-list" style="max-height: none">
                        <div v-if="!hideUserNotes" class="x-friend-item" style="width: 100%; cursor: default">
                            <div class="detail">
                                <span class="name">{{ t('dialog.user.info.note') }}</span>
                                <el-input
                                    v-model="userDialog.note"
                                    type="textarea"
                                    maxlength="256"
                                    show-word-limit
                                    :rows="2"
                                    :autosize="{ minRows: 1, maxRows: 20 }"
                                    :placeholder="t('dialog.user.info.note_placeholder')"
                                    size="mini"
                                    resize="none"
                                    @change="checkNote(userDialog.ref, userDialog.note)"
                                    @input="cleanNote(userDialog.note)"></el-input>
                                <div style="float: right">
                                    <i
                                        v-if="userDialog.noteSaving"
                                        class="el-icon-loading"
                                        style="margin-left: 5px"></i>
                                    <i
                                        v-else-if="userDialog.note !== userDialog.ref.note"
                                        class="el-icon-more-outline"
                                        style="margin-left: 5px"></i>
                                    <el-button
                                        v-if="userDialog.note"
                                        type="text"
                                        icon="el-icon-delete"
                                        size="mini"
                                        style="margin-left: 5px"
                                        @click="deleteNote(userDialog.id)"></el-button>
                                </div>
                            </div>
                        </div>
                        <div v-if="!hideUserMemos" class="x-friend-item" style="width: 100%; cursor: default">
                            <div class="detail">
                                <span class="name">{{ t('dialog.user.info.memo') }}</span>
                                <el-input
                                    v-model="userDialog.memo"
                                    class="extra"
                                    type="textarea"
                                    :rows="2"
                                    :autosize="{ minRows: 1, maxRows: 20 }"
                                    :placeholder="t('dialog.user.info.memo_placeholder')"
                                    size="mini"
                                    resize="none"
                                    @change="onUserMemoChange"></el-input>
                            </div>
                        </div>
                        <div class="x-friend-item" style="width: 100%; cursor: default">
                            <div class="detail">
                                <span
                                    v-if="
                                        userDialog.id !== API.currentUser.id &&
                                        userDialog.ref.profilePicOverride &&
                                        userDialog.ref.currentAvatarImageUrl
                                    "
                                    class="name">
                                    {{ t('dialog.user.info.avatar_info_last_seen') }}
                                </span>
                                <span v-else class="name">{{ t('dialog.user.info.avatar_info') }}</span>
                                <div class="extra">
                                    <avatar-info
                                        :imageurl="userDialog.ref.currentAvatarImageUrl"
                                        :userid="userDialog.id"
                                        :avatartags="userDialog.ref.currentAvatarTags"
                                        style="display: inline-block"></avatar-info>
                                    <el-tooltip
                                        v-if="
                                            userDialog.ref.profilePicOverride &&
                                            !userDialog.ref.currentAvatarImageUrl &&
                                            !hideTooltips
                                        "
                                        placement="top"
                                        :content="t('dialog.user.info.vrcplus_hides_avatar')">
                                        <i class="el-icon-warning"></i>
                                    </el-tooltip>
                                </div>
                            </div>
                        </div>
                        <div class="x-friend-item" style="width: 100%; cursor: default">
                            <div class="detail">
                                <span class="name" style="margin-bottom: 5px">{{
                                    t('dialog.user.info.represented_group')
                                }}</span>
                                <div
                                    v-if="
                                        userDialog.isRepresentedGroupLoading ||
                                        (userDialog.representedGroup && userDialog.representedGroup.isRepresenting)
                                    "
                                    class="extra">
                                    <div style="display: inline-block; flex: none; margin-right: 5px">
                                        <el-popover placement="right" width="500px" trigger="click">
                                            <el-image
                                                slot="reference"
                                                v-loading="userDialog.isRepresentedGroupLoading"
                                                class="x-link"
                                                :src="userDialog.representedGroup.$thumbnailUrl"
                                                style="
                                                    flex: none;
                                                    width: 60px;
                                                    height: 60px;
                                                    border-radius: 4px;
                                                    object-fit: cover;
                                                "
                                                :style="{
                                                    background: userDialog.isRepresentedGroupLoading ? '#f5f7fa' : ''
                                                }"
                                                @load="userDialog.isRepresentedGroupLoading = false">
                                                <div slot="error"></div>
                                            </el-image>
                                            <img
                                                v-lazy="userDialog.representedGroup.iconUrl"
                                                class="x-link"
                                                style="height: 500px"
                                                @click="
                                                    showFullscreenImageDialog(userDialog.representedGroup.iconUrl)
                                                " />
                                        </el-popover>
                                    </div>
                                    <span
                                        v-if="userDialog.representedGroup.isRepresenting"
                                        style="vertical-align: top; cursor: pointer"
                                        @click="showGroupDialog(userDialog.representedGroup.groupId)">
                                        <span
                                            v-if="userDialog.representedGroup.ownerId === userDialog.id"
                                            style="margin-right: 5px"
                                            >👑</span
                                        >
                                        <span
                                            style="margin-right: 5px"
                                            v-text="userDialog.representedGroup.name"></span>
                                        <span>({{ userDialog.representedGroup.memberCount }})</span>
                                    </span>
                                </div>
                                <div v-else class="extra">-</div>
                            </div>
                        </div>
                        <div class="x-friend-item" style="width: 100%; cursor: default">
                            <div class="detail">
                                <span class="name">{{ t('dialog.user.info.bio') }}</span>
                                <pre
                                    class="extra"
                                    style="
                                        font-family: inherit;
                                        font-size: 12px;
                                        white-space: pre-wrap;
                                        margin: 0 0.5em 0 0;
                                        max-height: 40vh;
                                        overflow-y: auto;
                                    "
                                    >{{ userDialog.ref.bio || '-' }}</pre
                                >
                                <div v-if="userDialog.id === API.currentUser.id" style="float: right">
                                    <el-button
                                        type="text"
                                        icon="el-icon-edit"
                                        size="mini"
                                        style="margin-left: 5px"
                                        @click="showBioDialog"></el-button>
                                </div>
                                <div style="margin-top: 5px">
                                    <el-tooltip v-for="(link, index) in userDialog.ref.bioLinks" :key="index">
                                        <template #content>
                                            <span v-text="link"></span>
                                        </template>
                                        <img
                                            :src="getFaviconUrl(link)"
                                            onerror="this.onerror=null;this.class='el-icon-error'"
                                            style="
                                                width: 16px;
                                                height: 16px;
                                                vertical-align: middle;
                                                margin-right: 5px;
                                                cursor: pointer;
                                            "
                                            @click.stop="openExternalLink(link)" />
                                    </el-tooltip>
                                </div>
                            </div>
                        </div>
                        <template v-if="API.currentUser.id !== userDialog.id">
                            <div class="x-friend-item" style="cursor: default">
                                <div class="detail">
                                    <span class="name">
                                        {{ t('dialog.user.info.last_seen') }}
                                        <el-tooltip
                                            v-if="!hideTooltips"
                                            placement="top"
                                            style="margin-left: 5px"
                                            :content="t('dialog.user.info.accuracy_notice')">
                                            <i class="el-icon-warning"></i>
                                        </el-tooltip>
                                    </span>
                                    <span class="extra">{{ userDialog.lastSeen | 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="showPreviousInstancesUserDialog(userDialog.ref)">
                                    <div class="detail">
                                        <span class="name">
                                            {{ t('dialog.user.info.join_count') }}
                                            <el-tooltip
                                                v-if="!hideTooltips"
                                                placement="top"
                                                style="margin-left: 5px"
                                                :content="t('dialog.user.info.accuracy_notice')">
                                                <i class="el-icon-warning"></i>
                                            </el-tooltip>
                                        </span>
                                        <span v-if="userDialog.joinCount === 0" class="extra">-</span>
                                        <span v-else class="extra" v-text="userDialog.joinCount"></span>
                                    </div>
                                </div>
                            </el-tooltip>
                            <div class="x-friend-item" style="cursor: default">
                                <div class="detail">
                                    <span class="name">
                                        {{ t('dialog.user.info.time_together') }}
                                        <el-tooltip
                                            v-if="!hideTooltips"
                                            placement="top"
                                            style="margin-left: 5px"
                                            :content="t('dialog.user.info.accuracy_notice')">
                                            <i class="el-icon-warning"></i>
                                        </el-tooltip>
                                    </span>
                                    <span v-if="userDialog.timeSpent === 0" class="extra">-</span>
                                    <span v-else class="extra">{{ timeToText(userDialog.timeSpent) }}</span>
                                </div>
                            </div>
                        </template>
                        <template v-else>
                            <el-tooltip
                                :disabled="hideTooltips || API.currentUser.id !== userDialog.id"
                                placement="top"
                                :content="t('dialog.user.info.open_previouse_instance')">
                                <div class="x-friend-item" @click="showPreviousInstancesUserDialog(userDialog.ref)">
                                    <div class="detail">
                                        <span class="name">
                                            {{ t('dialog.user.info.play_time') }}
                                            <el-tooltip
                                                v-if="!hideTooltips"
                                                placement="top"
                                                style="margin-left: 5px"
                                                :content="t('dialog.user.info.accuracy_notice')">
                                                <i class="el-icon-warning"></i>
                                            </el-tooltip>
                                        </span>
                                        <span v-if="userDialog.timeSpent === 0" class="extra">-</span>
                                        <span v-else class="extra">{{ timeToText(userDialog.timeSpent) }}</span>
                                    </div>
                                </div>
                            </el-tooltip>
                        </template>
                        <div class="x-friend-item" style="cursor: default">
                            <el-tooltip :placement="API.currentUser.id !== userDialog.id ? 'bottom' : 'top'">
                                <template #content>
                                    <span>{{ userOnlineForTimestamp(userDialog) | formatDate('short') }}</span>
                                </template>
                                <div class="detail">
                                    <span
                                        v-if="userDialog.ref.state === 'online' && userDialog.ref.$online_for"
                                        class="name">
                                        {{ t('dialog.user.info.online_for') }}
                                        <el-tooltip
                                            v-if="!hideTooltips"
                                            placement="top"
                                            style="margin-left: 5px"
                                            :content="t('dialog.user.info.accuracy_notice')">
                                            <i class="el-icon-warning"></i>
                                        </el-tooltip>
                                    </span>
                                    <span v-else class="name">
                                        {{ t('dialog.user.info.offline_for') }}
                                        <el-tooltip
                                            v-if="!hideTooltips"
                                            placement="top"
                                            style="margin-left: 5px"
                                            :content="t('dialog.user.info.accuracy_notice')">
                                            <i class="el-icon-warning"></i>
                                        </el-tooltip>
                                    </span>
                                    <span class="extra">{{ userOnlineFor(userDialog) }}</span>
                                </div>
                            </el-tooltip>
                        </div>
                        <div class="x-friend-item" style="cursor: default">
                            <el-tooltip :placement="API.currentUser.id !== userDialog.id ? 'bottom' : 'top'">
                                <template #content>
                                    <span
                                        >{{ t('dialog.user.info.last_login') }}
                                        {{ userDialog.ref.last_login | formatDate('short') }}</span
                                    >
                                </template>
                                <div class="detail">
                                    <span class="name">{{ t('dialog.user.info.last_activity') }}</span>
                                    <span class="extra">{{ userDialog.ref.last_activity | formatDate('long') }}</span>
                                </div>
                            </el-tooltip>
                        </div>
                        <div class="x-friend-item" style="cursor: default">
                            <div class="detail">
                                <span class="name">{{ t('dialog.user.info.date_joined') }}</span>
                                <span class="extra" v-text="userDialog.ref.date_joined"></span>
                            </div>
                        </div>
                        <div v-if="API.currentUser.id !== userDialog.id" class="x-friend-item" style="cursor: default">
                            <el-tooltip placement="top" :disabled="!userDialog.dateFriendedInfo.length">
                                <template v-if="userDialog.dateFriendedInfo.length" #content>
                                    <template v-for="ref in userDialog.dateFriendedInfo">
                                        <span>{{ ref.type }}: {{ ref.created_at | formatDate('long') }}</span
                                        ><br />
                                    </template>
                                </template>
                                <div class="detail">
                                    <span v-if="userDialog.unFriended" class="name">
                                        {{ t('dialog.user.info.unfriended') }}
                                        <el-tooltip
                                            v-if="!hideTooltips"
                                            placement="top"
                                            style="margin-left: 5px"
                                            :content="t('dialog.user.info.accuracy_notice')">
                                            <i class="el-icon-warning"></i>
                                        </el-tooltip>
                                    </span>
                                    <span v-else class="name">
                                        {{ t('dialog.user.info.friended') }}
                                        <el-tooltip
                                            v-if="!hideTooltips"
                                            placement="top"
                                            style="margin-left: 5px"
                                            :content="t('dialog.user.info.accuracy_notice')">
                                            <i class="el-icon-warning"></i>
                                        </el-tooltip>
                                    </span>
                                    <span class="extra">{{ userDialog.dateFriended | formatDate('long') }}</span>
                                </div>
                            </el-tooltip>
                        </div>
                        <template v-if="API.currentUser.id === userDialog.id">
                            <div class="x-friend-item" @click="toggleAvatarCopying">
                                <div class="detail">
                                    <span class="name">{{ t('dialog.user.info.avatar_cloning') }}</span>
                                    <span
                                        v-if="API.currentUser.allowAvatarCopying"
                                        class="extra"
                                        style="color: #67c23a"
                                        >{{ t('dialog.user.info.avatar_cloning_allow') }}</span
                                    >
                                    <span v-else class="extra" style="color: #f56c6c">{{
                                        t('dialog.user.info.avatar_cloning_deny')
                                    }}</span>
                                </div>
                            </div>
                            <!--//- .x-friend-item(@click="toggleAllowBooping")-->
                            <!--//-     .detail-->
                            <!--//-         span.name {{ t('dialog.user.info.booping') }}-->
                            <!--//-         span.extra(v-if="API.currentUser.isBoopingEnabled" style="color:#67C23A") {{ t('dialog.user.info.avatar_cloning_allow') }}-->
                            <!--//-         span.extra(v-else style="color:#F56C6C") {{ t('dialog.user.info.avatar_cloning_deny') }}-->
                        </template>
                        <template v-else>
                            <div class="x-friend-item" style="cursor: default">
                                <div class="detail">
                                    <span class="name">{{ t('dialog.user.info.avatar_cloning') }}</span>
                                    <span
                                        v-if="userDialog.ref.allowAvatarCopying"
                                        class="extra"
                                        style="color: #67c23a"
                                        >{{ t('dialog.user.info.avatar_cloning_allow') }}</span
                                    >
                                    <span v-else class="extra" style="color: #f56c6c">{{
                                        t('dialog.user.info.avatar_cloning_deny')
                                    }}</span>
                                </div>
                            </div>
                        </template>
                        <div
                            v-if="userDialog.ref.id === API.currentUser.id && API.currentUser.homeLocation"
                            class="x-friend-item"
                            style="width: 100%"
                            @click="showWorldDialog(API.currentUser.homeLocation)">
                            <div class="detail">
                                <span class="name">{{ t('dialog.user.info.home_location') }}</span>
                                <span class="extra">
                                    <span v-text="userDialog.$homeLocationName"></span>
                                    <el-button
                                        size="mini"
                                        icon="el-icon-delete"
                                        circle
                                        style="margin-left: 5px"
                                        @click.stop="resetHome()">
                                    </el-button>
                                </span>
                            </div>
                        </div>
                        <div class="x-friend-item" style="width: 100%; cursor: default">
                            <div class="detail">
                                <span class="name">{{ t('dialog.user.info.id') }}</span>
                                <span class="extra">
                                    {{ userDialog.id }}
                                    <el-tooltip
                                        placement="top"
                                        :content="t('dialog.user.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-button>
                                            <el-dropdown-menu slot="dropdown">
                                                <el-dropdown-item @click.native="copyUserId(userDialog.id)">{{
                                                    t('dialog.user.info.copy_id')
                                                }}</el-dropdown-item>
                                                <el-dropdown-item @click.native="copyUserURL(userDialog.id)">{{
                                                    t('dialog.user.info.copy_url')
                                                }}</el-dropdown-item>
                                                <el-dropdown-item
                                                    @click.native="copyUserDisplayName(userDialog.ref.displayName)"
                                                    >{{ t('dialog.user.info.copy_display_name') }}</el-dropdown-item
                                                >
                                            </el-dropdown-menu>
                                        </el-dropdown>
                                    </el-tooltip>
                                </span>
                            </div>
                        </div>
                    </div>
                </el-tab-pane>

                <el-tab-pane :label="t('dialog.user.groups.header')" lazy>
                    <div style="display: flex; align-items: center; justify-content: space-between">
                        <div style="display: flex; align-items: center">
                            <el-button
                                type="default"
                                :loading="userDialog.isGroupsLoading"
                                size="mini"
                                icon="el-icon-refresh"
                                circle
                                @click="getUserGroups(userDialog.id)">
                            </el-button>
                            <span style="margin-left: 5px">{{
                                t('dialog.user.groups.total_count', { count: userGroups.groups.length })
                            }}</span>
                            <template v-if="userDialogGroupEditMode">
                                <span style="margin-left: 10px; color: #909399; font-size: 10px">{{
                                    t('dialog.user.groups.hold_shift')
                                }}</span>
                            </template>
                        </div>
                        <div style="display: flex; align-items: center">
                            <template v-if="!userDialogGroupEditMode">
                                <span style="margin-right: 5px">{{ t('dialog.user.groups.sort_by') }}</span>
                                <el-dropdown
                                    trigger="click"
                                    size="small"
                                    style="margin-right: 5px"
                                    :disabled="userDialog.isGroupsLoading"
                                    @click.native.stop>
                                    <el-button size="mini">
                                        <span
                                            >{{ t(userDialog.groupSorting.name) }}
                                            <i class="el-icon-arrow-down el-icon--right"></i
                                        ></span>
                                    </el-button>
                                    <el-dropdown-menu slot="dropdown">
                                        <el-dropdown-item
                                            v-for="(item, key) in userDialogGroupSortingOptions"
                                            :key="key"
                                            :disabled="
                                                item === userDialogGroupSortingOptions.inGame &&
                                                userDialog.id !== API.currentUser.id
                                            "
                                            @click.native="setUserDialogGroupSorting(item)"
                                            >{{ t(item.name) }}
                                        </el-dropdown-item>
                                    </el-dropdown-menu>
                                </el-dropdown>
                            </template>
                            <el-button
                                v-if="userDialogGroupEditMode"
                                size="small"
                                icon="el-icon-edit"
                                style="margin-right: 5px; height: 29px; padding: 7px 15px"
                                @click="exitEditModeCurrentUserGroups">
                                {{ t('dialog.user.groups.exit_edit_mode') }}
                            </el-button>
                            <el-button
                                v-else-if="API.currentUser.id === userDialog.id"
                                size="small"
                                icon="el-icon-edit"
                                style="margin-right: 5px; height: 29px; padding: 7px 15px"
                                @click="editModeCurrentUserGroups">
                                {{ t('dialog.user.groups.edit_mode') }}
                            </el-button>
                        </div>
                    </div>
                    <div v-loading="userDialog.isGroupsLoading" style="margin-top: 10px">
                        <template v-if="userDialogGroupEditMode">
                            <div class="x-friend-list" style="margin-top: 10px; margin-bottom: 15px; max-height: unset">
                                <div
                                    v-for="group in userDialogGroupEditGroups"
                                    :key="group.id"
                                    class="x-friend-item x-friend-item-border"
                                    style="width: 100%"
                                    @click="showGroupDialog(group.id)">
                                    <div style="margin-right: 3px; margin-left: 5px" @click.stop>
                                        <el-button
                                            size="mini"
                                            icon="el-icon-download"
                                            style="
                                                display: block;
                                                padding: 7px;
                                                font-size: 9px;
                                                margin-left: 0;
                                                rotate: 180deg;
                                            "
                                            @click="moveGroupTop(group.id)">
                                        </el-button>
                                        <el-button
                                            size="mini"
                                            icon="el-icon-download"
                                            style="display: block; padding: 7px; font-size: 9px; margin-left: 0"
                                            @click="moveGroupBottom(group.id)">
                                        </el-button>
                                    </div>
                                    <div style="margin-right: 10px" @click.stop>
                                        <el-button
                                            size="mini"
                                            icon="el-icon-top"
                                            style="display: block; padding: 7px; font-size: 9px; margin-left: 0"
                                            @click="moveGroupUp(group.id)">
                                        </el-button>
                                        <el-button
                                            size="mini"
                                            icon="el-icon-bottom"
                                            style="display: block; padding: 7px; font-size: 9px; margin-left: 0"
                                            @click="moveGroupDown(group.id)">
                                        </el-button>
                                    </div>
                                    <div class="avatar">
                                        <img v-lazy="group.iconUrl" />
                                    </div>
                                    <div class="detail">
                                        <span class="name" v-text="group.name"></span>
                                        <span class="extra">
                                            <el-tooltip
                                                v-if="group.isRepresenting"
                                                placement="top"
                                                :content="t('dialog.group.members.representing')">
                                                <i class="el-icon-collection-tag" style="margin-right: 5px"></i>
                                            </el-tooltip>
                                            <el-tooltip v-if="group.myMember.visibility !== 'visible'" placement="top">
                                                <template #content>
                                                    <span
                                                        >{{ t('dialog.group.members.visibility') }}
                                                        {{ group.myMember.visibility }}</span
                                                    >
                                                </template>
                                                <i class="el-icon-view" style="margin-right: 5px"></i>
                                            </el-tooltip>
                                            <span>({{ group.memberCount }})</span>
                                        </span>
                                    </div>
                                    <el-dropdown
                                        :disabled="group.privacy !== 'default'"
                                        trigger="click"
                                        size="small"
                                        style="margin-right: 5px"
                                        @click.native.stop>
                                        <el-button size="mini">
                                            <span v-if="group.myMember.visibility === 'visible'">{{
                                                t('dialog.group.tags.visible')
                                            }}</span>
                                            <span v-else-if="group.myMember.visibility === 'friends'">{{
                                                t('dialog.group.tags.friends')
                                            }}</span>
                                            <span v-else-if="group.myMember.visibility === 'hidden'">{{
                                                t('dialog.group.tags.hidden')
                                            }}</span>
                                            <span v-else>{{ group.myMember.visibility }}</span>
                                            <i class="el-icon-arrow-down el-icon--right" style="margin-left: 5px"></i>
                                        </el-button>
                                        <el-dropdown-menu>
                                            <el-dropdown-item @click.native="setGroupVisibility(group.id, 'visible')"
                                                ><i
                                                    v-if="group.myMember.visibility === 'visible'"
                                                    class="el-icon-check"></i>
                                                {{ t('dialog.group.actions.visibility_everyone') }}</el-dropdown-item
                                            >
                                            <el-dropdown-item @click.native="setGroupVisibility(group.id, 'friends')"
                                                ><i
                                                    v-if="group.myMember.visibility === 'friends'"
                                                    class="el-icon-check"></i>
                                                {{ t('dialog.group.actions.visibility_friends') }}</el-dropdown-item
                                            >
                                            <el-dropdown-item @click.native="setGroupVisibility(group.id, 'hidden')"
                                                ><i
                                                    v-if="group.myMember.visibility === 'hidden'"
                                                    class="el-icon-check"></i>
                                                {{ t('dialog.group.actions.visibility_hidden') }}</el-dropdown-item
                                            >
                                        </el-dropdown-menu>
                                    </el-dropdown>
                                    <!--//- JSON is missing isSubscribedToAnnouncements, can't be implemented-->
                                    <!--//- el-dropdown(@click.native.stop trigger="click" size="small" style="margin-right:5px")-->
                                    <!--//-     el-tooltip(placement="top" :disabled="hideTooltips")-->
                                    <!--//-         template(#content)-->
                                    <!--//-             span(v-if="group.myMember.isSubscribedToAnnouncements") {{ t('dialog.group.actions.unsubscribe') }}-->
                                    <!--//-             span(v-else) {{ t('dialog.group.actions.subscribe') }}-->
                                    <!--//-         el-button(v-if="group.myMember.isSubscribedToAnnouncements" @click.stop="setGroupSubscription(group.id, false)" circle size="mini")-->
                                    <!--//-             i.el-icon-chat-line-square-->
                                    <!--//-         el-button(v-else circle @click.stop="setGroupSubscription(group.id, true)" size="mini")-->
                                    <!--//-             i.el-icon-chat-square(style="color:#f56c6c")-->
                                    <el-tooltip
                                        placement="right"
                                        :content="t('dialog.user.groups.leave_group_tooltip')"
                                        :disabled="hideTooltips">
                                        <el-button
                                            v-if="shiftHeld"
                                            size="mini"
                                            icon="el-icon-close"
                                            circle
                                            style="color: #f56c6c; margin-left: 5px"
                                            @click.stop="leaveGroupPrompt(group.id)">
                                        </el-button>
                                        <el-button
                                            v-else
                                            size="mini"
                                            icon="el-icon-delete"
                                            circle
                                            style="margin-left: 5px"
                                            @click.stop="leaveGroupPrompt(group.id)">
                                        </el-button>
                                    </el-tooltip>
                                </div>
                            </div>
                        </template>
                        <template v-else>
                            <template v-if="userGroups.ownGroups.length > 0">
                                <span style="font-weight: bold; font-size: 16px">{{
                                    t('dialog.user.groups.own_groups')
                                }}</span>
                                <span style="color: #909399; font-size: 12px; margin-left: 5px"
                                    >{{ userGroups.ownGroups.length }}/{{
                                        API.cachedConfig?.constants?.GROUPS?.MAX_OWNED
                                    }}</span
                                >
                                <div
                                    class="x-friend-list"
                                    style="margin-top: 10px; margin-bottom: 15px; min-height: 60px">
                                    <div
                                        v-for="group in userGroups.ownGroups"
                                        :key="group.id"
                                        class="x-friend-item x-friend-item-border"
                                        @click="showGroupDialog(group.id)">
                                        <div class="avatar">
                                            <img v-lazy="group.iconUrl" />
                                        </div>
                                        <div class="detail">
                                            <span class="name" v-text="group.name"></span>
                                            <span class="extra">
                                                <el-tooltip
                                                    v-if="group.isRepresenting"
                                                    placement="top"
                                                    :content="t('dialog.group.members.representing')">
                                                    <i class="el-icon-collection-tag" style="margin-right: 5px"></i>
                                                </el-tooltip>
                                                <el-tooltip v-if="group.memberVisibility !== 'visible'" placement="top">
                                                    <template #content>
                                                        <span
                                                            >{{ t('dialog.group.members.visibility') }}
                                                            {{ group.memberVisibility }}</span
                                                        >
                                                    </template>
                                                    <i class="el-icon-view" style="margin-right: 5px"></i>
                                                </el-tooltip>
                                                <span>({{ group.memberCount }})</span>
                                            </span>
                                        </div>
                                    </div>
                                </div>
                            </template>
                            <template v-if="userGroups.mutualGroups.length > 0">
                                <span style="font-weight: bold; font-size: 16px">{{
                                    t('dialog.user.groups.mutual_groups')
                                }}</span>
                                <span style="color: #909399; font-size: 12px; margin-left: 5px">{{
                                    userGroups.mutualGroups.length
                                }}</span>
                                <div
                                    class="x-friend-list"
                                    style="margin-top: 10px; margin-bottom: 15px; min-height: 60px">
                                    <div
                                        v-for="group in userGroups.mutualGroups"
                                        :key="group.id"
                                        class="x-friend-item x-friend-item-border"
                                        @click="showGroupDialog(group.id)">
                                        <div class="avatar">
                                            <img v-lazy="group.iconUrl" />
                                        </div>
                                        <div class="detail">
                                            <span class="name" v-text="group.name"></span>
                                            <span class="extra">
                                                <el-tooltip
                                                    v-if="group.isRepresenting"
                                                    placement="top"
                                                    :content="t('dialog.group.members.representing')">
                                                    <i class="el-icon-collection-tag" style="margin-right: 5px"></i>
                                                </el-tooltip>
                                                <el-tooltip v-if="group.memberVisibility !== 'visible'" placement="top">
                                                    <template #content>
                                                        <span
                                                            >{{ t('dialog.group.members.visibility') }}
                                                            {{ group.memberVisibility }}</span
                                                        >
                                                    </template>
                                                    <i class="el-icon-view" style="margin-right: 5px"></i>
                                                </el-tooltip>
                                                <span>({{ group.memberCount }})</span>
                                            </span>
                                        </div>
                                    </div>
                                </div>
                            </template>
                            <template v-if="userGroups.remainingGroups.length > 0">
                                <span style="font-weight: bold; font-size: 16px">{{
                                    t('dialog.user.groups.groups')
                                }}</span>
                                <span style="color: #909399; font-size: 12px; margin-left: 5px">
                                    {{ userGroups.remainingGroups.length }}
                                    <template v-if="API.currentUser.id === userDialog.id">
                                        /
                                        <template v-if="API.currentUser.$isVRCPlus">
                                            {{ API.cachedConfig?.constants?.GROUPS?.MAX_JOINED_PLUS }}
                                        </template>
                                        <template v-else>
                                            {{ API.cachedConfig?.constants?.GROUPS?.MAX_JOINED }}
                                        </template>
                                    </template>
                                </span>
                                <div
                                    class="x-friend-list"
                                    style="margin-top: 10px; margin-bottom: 15px; min-height: 60px">
                                    <div
                                        v-for="group in userGroups.remainingGroups"
                                        :key="group.id"
                                        class="x-friend-item x-friend-item-border"
                                        @click="showGroupDialog(group.id)">
                                        <div class="avatar">
                                            <img v-lazy="group.iconUrl" />
                                        </div>
                                        <div class="detail">
                                            <span class="name" v-text="group.name"></span>
                                            <span class="extra">
                                                <el-tooltip
                                                    v-if="group.isRepresenting"
                                                    placement="top"
                                                    :content="t('dialog.group.members.representing')">
                                                    <i class="el-icon-collection-tag" style="margin-right: 5px"></i>
                                                </el-tooltip>
                                                <el-tooltip v-if="group.memberVisibility !== 'visible'" placement="top">
                                                    <template #content>
                                                        <span
                                                            >{{ t('dialog.group.members.visibility') }}
                                                            {{ group.memberVisibility }}</span
                                                        >
                                                    </template>
                                                    <i class="el-icon-view" style="margin-right: 5px"></i>
                                                </el-tooltip>
                                                <span>({{ group.memberCount }})</span>
                                            </span>
                                        </div>
                                    </div>
                                </div>
                            </template>
                        </template>
                    </div>
                </el-tab-pane>

                <el-tab-pane :label="t('dialog.user.worlds.header')" lazy>
                    <div style="display: flex; align-items: center; justify-content: space-between">
                        <div style="display: flex; align-items: center">
                            <el-button
                                type="default"
                                :loading="userDialog.isWorldsLoading"
                                size="mini"
                                icon="el-icon-refresh"
                                circle
                                @click="refreshUserDialogWorlds()">
                            </el-button>
                            <span style="margin-left: 5px">{{
                                t('dialog.user.worlds.total_count', { count: userDialog.worlds.length })
                            }}</span>
                        </div>
                        <div style="display: flex; align-items: center">
                            <span style="margin-right: 5px">{{ t('dialog.user.worlds.sort_by') }}</span>
                            <el-dropdown
                                trigger="click"
                                size="small"
                                style="margin-right: 5px"
                                :disabled="userDialog.isWorldsLoading"
                                @click.native.stop>
                                <el-button size="mini">
                                    <span
                                        >{{ userDialog.worldSorting.name }}
                                        <i class="el-icon-arrow-down el-icon--right"></i
                                    ></span>
                                </el-button>
                                <el-dropdown-menu slot="dropdown">
                                    <el-dropdown-item
                                        v-for="(item, key) in userDialogWorldSortingOptions"
                                        :key="key"
                                        @click.native="setUserDialogWorldSorting(item)"
                                        v-text="item.name">
                                    </el-dropdown-item>
                                </el-dropdown-menu>
                            </el-dropdown>
                            <span style="margin: 0 5px">{{ t('dialog.user.worlds.order_by') }}</span>
                            <el-dropdown
                                trigger="click"
                                size="small"
                                style="margin-right: 5px"
                                :disabled="userDialog.isWorldsLoading"
                                @click.native.stop>
                                <el-button size="mini">
                                    <span
                                        >{{ userDialog.worldOrder.name }}
                                        <i class="el-icon-arrow-down el-icon--right"></i
                                    ></span>
                                </el-button>
                                <el-dropdown-menu slot="dropdown">
                                    <el-dropdown-item
                                        v-for="(item, key) in userDialogWorldOrderOptions"
                                        :key="key"
                                        @click.native="setUserDialogWorldOrder(item)"
                                        v-text="item.name">
                                    </el-dropdown-item>
                                </el-dropdown-menu>
                            </el-dropdown>
                        </div>
                    </div>
                    <div
                        v-loading="userDialog.isWorldsLoading"
                        class="x-friend-list"
                        style="margin-top: 10px; min-height: 60px">
                        <div
                            v-for="world in userDialog.worlds"
                            :key="world.id"
                            class="x-friend-item x-friend-item-border"
                            @click="showWorldDialog(world.id)">
                            <div class="avatar">
                                <img v-lazy="world.thumbnailImageUrl" />
                            </div>
                            <div class="detail">
                                <span class="name" v-text="world.name"></span>
                                <span v-if="world.occupants" class="extra">({{ world.occupants }})</span>
                            </div>
                        </div>
                    </div>
                </el-tab-pane>

                <el-tab-pane :label="t('dialog.user.favorite_worlds.header')" lazy>
                    <el-button
                        v-if="userFavoriteWorlds && userFavoriteWorlds.length > 0"
                        type="default"
                        :loading="userDialog.isFavoriteWorldsLoading"
                        size="small"
                        icon="el-icon-refresh"
                        circle
                        style="position: absolute; right: 15px; bottom: 15px; z-index: 99"
                        @click="getUserFavoriteWorlds(userDialog.id)">
                    </el-button>
                    <el-tabs
                        ref="favoriteWorldsRef"
                        v-loading="userDialog.isFavoriteWorldsLoading"
                        class="zero-margin-tabs"
                        type="card"
                        stretch
                        style="margin-top: 10px; height: 50vh">
                        <template v-if="userFavoriteWorlds && userFavoriteWorlds.length > 0">
                            <el-tab-pane v-for="(list, index) in userFavoriteWorlds" :key="index" lazy>
                                <span slot="label">
                                    <i
                                        class="x-status-icon"
                                        style="margin-right: 6px"
                                        :class="userFavoriteWorldsStatus(list[1])">
                                    </i>
                                    <span style="font-weight: bold; font-size: 14px" v-text="list[0]"></span>
                                    <span style="color: #909399; font-size: 10px; margin-left: 5px"
                                        >{{ list[2].length }}/{{ API.favoriteLimits.maxFavoritesPerGroup.world }}</span
                                    >
                                </span>
                                <div
                                    class="x-friend-list"
                                    style="margin-top: 10px; margin-bottom: 15px; min-height: 60px; max-height: none">
                                    <div
                                        v-for="world in list[2]"
                                        :key="world.favoriteId"
                                        class="x-friend-item x-friend-item-border"
                                        @click="showWorldDialog(world.id)">
                                        <div class="avatar">
                                            <img v-lazy="world.thumbnailImageUrl" />
                                        </div>
                                        <div class="detail">
                                            <span class="name" v-text="world.name"></span>
                                            <span v-if="world.occupants" class="extra">({{ world.occupants }})</span>
                                        </div>
                                    </div>
                                </div>
                            </el-tab-pane>
                        </template>
                        <template v-else-if="!userDialog.isFavoriteWorldsLoading">
                            <div style="display: flex; justify-content: center; align-items: center; height: 100%">
                                <span style="font-size: 16px">No favorite worlds found.</span>
                            </div>
                        </template>
                    </el-tabs>
                </el-tab-pane>

                <el-tab-pane :label="t('dialog.user.avatars.header')" lazy>
                    <div style="display: flex; align-items: center; justify-content: space-between">
                        <div style="display: flex; align-items: center">
                            <el-button
                                v-if="userDialog.ref.id === API.currentUser.id"
                                type="default"
                                :loading="userDialog.isAvatarsLoading"
                                size="mini"
                                icon="el-icon-refresh"
                                circle
                                @click="refreshUserDialogAvatars()">
                            </el-button>
                            <el-button
                                v-else
                                type="default"
                                :loading="userDialog.isAvatarsLoading"
                                size="mini"
                                icon="el-icon-refresh"
                                circle
                                @click="setUserDialogAvatarsRemote(userDialog.id)">
                            </el-button>
                            <span style="margin-left: 5px">{{
                                t('dialog.user.avatars.total_count', { count: userDialogAvatars.length })
                            }}</span>
                        </div>
                        <div>
                            <template v-if="userDialog.ref.id === API.currentUser.id">
                                <span style="margin-right: 5px">{{ t('dialog.user.avatars.sort_by') }}</span>
                                <el-dropdown
                                    trigger="click"
                                    size="small"
                                    style="margin-right: 5px"
                                    :disabled="userDialog.isWorldsLoading"
                                    @click.native.stop>
                                    <el-button size="mini">
                                        <span
                                            >{{ t(`dialog.user.avatars.sort_by_${userDialog.avatarSorting}`) }}
                                            <i class="el-icon-arrow-down el-icon--right"></i
                                        ></span>
                                    </el-button>
                                    <el-dropdown-menu slot="dropdown">
                                        <el-dropdown-item
                                            @click.native="changeUserDialogAvatarSorting('name')"
                                            v-text="t('dialog.user.avatars.sort_by_name')">
                                        </el-dropdown-item>
                                        <el-dropdown-item
                                            @click.native="changeUserDialogAvatarSorting('update')"
                                            v-text="t('dialog.user.avatars.sort_by_update')">
                                        </el-dropdown-item>
                                    </el-dropdown-menu>
                                </el-dropdown>
                                <span style="margin-right: 5px; margin-left: 10px">{{
                                    t('dialog.user.avatars.group_by')
                                }}</span>
                                <el-dropdown
                                    trigger="click"
                                    size="small"
                                    style="margin-right: 5px"
                                    :disabled="userDialog.isWorldsLoading"
                                    @click.native.stop>
                                    <el-button size="mini">
                                        <span
                                            >{{ t(`dialog.user.avatars.${userDialog.avatarReleaseStatus}`) }}
                                            <i class="el-icon-arrow-down el-icon--right"></i
                                        ></span>
                                    </el-button>
                                    <el-dropdown-menu slot="dropdown">
                                        <el-dropdown-item
                                            @click.native="userDialog.avatarReleaseStatus = 'all'"
                                            v-text="t('dialog.user.avatars.all')">
                                        </el-dropdown-item>
                                        <el-dropdown-item
                                            @click.native="userDialog.avatarReleaseStatus = 'public'"
                                            v-text="t('dialog.user.avatars.public')">
                                        </el-dropdown-item>
                                        <el-dropdown-item
                                            @click.native="userDialog.avatarReleaseStatus = 'private'"
                                            v-text="t('dialog.user.avatars.private')">
                                        </el-dropdown-item>
                                    </el-dropdown-menu>
                                </el-dropdown>
                            </template>
                        </div>
                    </div>
                    <div class="x-friend-list" style="margin-top: 10px; min-height: 60px; max-height: 50vh">
                        <div
                            v-for="avatar in userDialogAvatars"
                            :key="avatar.id"
                            class="x-friend-item x-friend-item-border"
                            @click="showAvatarDialog(avatar.id)">
                            <div class="avatar">
                                <img v-if="avatar.thumbnailImageUrl" v-lazy="avatar.thumbnailImageUrl" />
                            </div>
                            <div class="detail">
                                <span class="name" v-text="avatar.name"></span>
                                <span
                                    v-if="avatar.releaseStatus === 'public'"
                                    class="extra"
                                    style="color: #67c23a"
                                    v-text="avatar.releaseStatus">
                                </span>
                                <span
                                    v-else-if="avatar.releaseStatus === 'private'"
                                    class="extra"
                                    style="color: #f56c6c"
                                    v-text="avatar.releaseStatus">
                                </span>
                                <span v-else class="extra" v-text="avatar.releaseStatus"></span>
                            </div>
                        </div>
                    </div>
                </el-tab-pane>

                <el-tab-pane :label="t('dialog.user.json.header')" lazy style="height: 50vh">
                    <el-button
                        type="default"
                        size="mini"
                        icon="el-icon-refresh"
                        circle
                        @click="refreshUserDialogTreeData()">
                    </el-button>
                    <el-button
                        type="default"
                        size="mini"
                        icon="el-icon-download"
                        circle
                        style="margin-left: 5px"
                        @click="downloadAndSaveJson(userDialog.id, userDialog.ref)">
                    </el-button>
                    <el-tree :data="userDialog.treeData" style="margin-top: 5px; font-size: 12px">
                        <template #default="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>
        <SendInviteDialog
            :send-invite-dialog-visible.sync="sendInviteDialogVisible"
            :invite-message-table="inviteMessageTable"
            :send-invite-dialog="sendInviteDialog"
            :upload-image="uploadImage" />
        <SendInviteRequestDialog
            :send-invite-request-dialog-visible.sync="sendInviteRequestDialogVisible"
            :invite-request-message-table="inviteRequestMessageTable"
            :send-invite-dialog="sendInviteDialog"
            :upload-image="uploadImage"
            @inviteImageUpload="inviteImageUpload" />
        <PreviousInstancesUserDialog
            :previous-instances-user-dialog.sync="previousInstancesUserDialog"
            :shift-held="shiftHeld" />
        <PreviousImagesDialog
            :previous-images-dialog-visible.sync="previousImagesDialogVisible"
            :previous-images-table="previousImagesTable" />
        <InviteGroupDialog
            :dialog-data.sync="inviteGroupDialog"
            :vip-friends="vipFriends"
            :online-friends="onlineFriends"
            :offline-friends="offlineFriends"
            :active-friends="activeFriends" />
        <SocialStatusDialog
            :social-status-dialog="socialStatusDialog"
            :social-status-history-table="socialStatusHistoryTable" />
        <LanguageDialog :language-dialog="languageDialog" />
        <BioDialog :bio-dialog="bioDialog" />
        <PronounsDialog :pronouns-dialog="pronounsDialog" />
        <GalleryDialog
            :gallery-dialog-visible.sync="galleryDialogVisible"
            :gallery-dialog-gallery-loading="galleryDialogGalleryLoading"
            :gallery-dialog-icons-loading="galleryDialogIconsLoading"
            :gallery-dialog-emojis-loading="galleryDialogEmojisLoading"
            :gallery-dialog-stickers-loading="galleryDialogStickersLoading"
            :gallery-dialog-prints-loading="galleryDialogPrintsLoading"
            :gallery-table="galleryTable"
            :VRCPlusIconsTable="VRCPlusIconsTable"
            :emoji-table="emojiTable"
            :sticker-table="stickerTable"
            :print-upload-note="printUploadNote"
            :print-crop-border="printCropBorder"
            :print-table="printTable"
            @refreshGalleryTable="refreshGalleryTable"
            @refreshVRCPlusIconsTable="refreshVRCPlusIconsTable"
            @refreshStickerTable="refreshStickerTable"
            @refreshEmojiTable="refreshEmojiTable"
            @refreshPrintTable="refreshPrintTable"
            @closeGalleryDialog="closeGalleryDialog" />
    </safe-dialog>
</template>

<script setup>
    import { computed, getCurrentInstance, inject, nextTick, ref, watch } from 'vue';
    import { useI18n } from 'vue-i18n-bridge';
    import {
        favoriteRequest,
        friendRequest,
        groupRequest,
        imageRequest,
        inviteMessagesRequest,
        miscRequest,
        notificationRequest,
        playerModerationRequest,
        userRequest,
        worldRequest
    } from '../../../api';
    import utils from '../../../classes/utils';
    import { isRealInstance, parseLocation, refreshInstancePlayerCount } from '../../../composables/instance/utils';
    import {
        copyToClipboard,
        downloadAndSaveJson,
        extractFileId,
        getFaviconUrl
    } from '../../../composables/shared/utils';
    import { userDialogGroupSortingOptions } from '../../../composables/user/constants/userDialogGroupSortingOptions';
    import { isFriendOnline, languageClass, userOnlineForTimestamp } from '../../../composables/user/utils';
    import database from '../../../service/database';
    import Location from '../../Location.vue';
    import SendInviteDialog from '../InviteDialog/SendInviteDialog.vue';
    import InviteGroupDialog from '../InviteGroupDialog.vue';
    import PreviousImagesDialog from '../PreviousImagesDialog.vue';
    import BioDialog from './BioDialog.vue';
    import GalleryDialog from './GalleryDialog.vue';
    import LanguageDialog from './LanguageDialog.vue';
    import PreviousInstancesUserDialog from './PreviousInstancesUserDialog.vue';
    import PronounsDialog from './PronounsDialog.vue';
    import SendInviteRequestDialog from './SendInviteRequestDialog.vue';
    import SocialStatusDialog from './SocialStatusDialog.vue';

    const { t } = useI18n();

    const { proxy } = getCurrentInstance();
    const { $message, $confirm } = proxy;

    const API = inject('API');
    const showFullscreenImageDialog = inject('showFullscreenImageDialog');

    const userImage = inject('userImage');
    const showLaunchDialog = inject('showLaunchDialog');
    const showUserDialog = inject('showUserDialog');
    const showGroupDialog = inject('showGroupDialog');
    const openExternalLink = inject('openExternalLink');
    const showWorldDialog = inject('showWorldDialog');
    const showAvatarDialog = inject('showAvatarDialog');
    const showFavoriteDialog = inject('showFavoriteDialog');
    const adjustDialogZ = inject('adjustDialogZ');
    const userStatusClass = inject('userStatusClass');

    const props = defineProps({
        userDialog: {
            type: Object,
            default: () => ({})
        },
        languageDialog: {
            type: Object,
            required: true
        },
        hideTooltips: {
            type: Boolean,
            default: false
        },
        lastLocation: {
            type: Object,
            default: () => ({})
        },
        lastLocationDestination: {
            type: String,
            default: ''
        },
        isGameRunning: {
            type: Boolean,
            default: false
        },
        checkCanInvite: {
            type: Function,
            default: () => {}
        },
        updateInstanceInfo: {
            type: Number,
            default: () => {}
        },
        hideUserNotes: {
            type: Boolean,
            default: false
        },
        hideUserMemos: {
            type: Boolean,
            default: false
        },
        userOnlineFor: {
            type: Function,
            default: () => {}
        },
        userDialogWorldSortingOptions: {
            type: Object,
            default: () => ({})
        },
        userDialogWorldOrderOptions: {
            type: Object,
            default: () => ({})
        },
        avatarRemoteDatabase: {
            type: Boolean,
            default: false
        },
        friendLogTable: {
            type: Object,
            default: () => ({})
        },
        lookupAvatars: {
            type: Function,
            default: () => {}
        },
        updateInGameGroupOrder: {
            type: Function,
            default: () => {}
        },
        // SendInviteDialog
        inviteMessageTable: {
            type: Object,
            default: () => ({})
        },
        uploadImage: {
            type: String
        },
        inviteRequestMessageTable: {
            type: Object,
            default: () => ({})
        },
        inGameGroupOrder: {
            type: Array,
            default: () => []
        },
        shiftHeld: {
            type: Boolean,
            default: false
        },
        vipFriends: {
            type: Array,
            default: () => []
        },
        onlineFriends: {
            type: Array,
            default: () => []
        },
        offlineFriends: {
            type: Array,
            default: () => []
        },
        activeFriends: {
            type: Array,
            default: () => []
        },
        // Gallery Dialog
        galleryDialogVisible: {
            type: Boolean,
            required: true
        },
        galleryDialogGalleryLoading: {
            type: Boolean,
            required: true
        },
        galleryDialogIconsLoading: {
            type: Boolean,
            required: true
        },
        galleryDialogEmojisLoading: {
            type: Boolean,
            required: true
        },
        galleryDialogStickersLoading: {
            type: Boolean,
            required: true
        },
        galleryDialogPrintsLoading: {
            type: Boolean,
            required: true
        },
        galleryTable: {
            type: Array,
            required: true
        },
        // eslint-disable-next-line vue/prop-name-casing
        VRCPlusIconsTable: {
            type: Array,
            required: true
        },
        emojiTable: {
            type: Array,
            required: true
        },
        stickerTable: {
            type: Array,
            required: true
        },
        printUploadNote: {
            type: String,
            required: true
        },
        printCropBorder: {
            type: Boolean,
            required: true
        },
        printTable: {
            type: Array,
            required: true
        }
    });

    const emit = defineEmits([
        'sortUserDialogAvatars',
        'logout',
        'showAvatarAuthorDialog',
        'showGalleryDialog',
        'saveCurrentUserGroups',
        'refreshUserDialogAvatars',
        'refreshUserDialogTreeData',
        'saveUserMemo',
        'setGroupVisibility',
        'leaveGroupPrompt',
        'clearInviteImageUpload',
        'refreshGalleryTable',
        'refreshVRCPlusIconsTable',
        'refreshStickerTable',
        'refreshEmojiTable',
        'refreshPrintTable',
        'closeGalleryDialog'
    ]);

    watch(
        () => props.userDialog.loading,
        () => {
            if (props.userDialog.visible) {
                nextTick(() => adjustDialogZ(userDialogRef.value.$el));
                !props.userDialog.loading && toggleLastActiveTab(props.userDialog.id);
            }
        }
    );

    const userDialogTabsRef = ref(null);
    const userDialogRef = ref(null);

    const userDialogGroupEditMode = ref(false);
    const userDialogGroupEditGroups = ref([]);
    const userDialogLastActiveTab = ref('');
    const userDialogLastGroup = ref('');
    const userDialogLastAvatar = ref('');
    const userDialogLastWorld = ref('');
    const userDialogLastFavoriteWorld = ref('');
    const userFavoriteWorlds = ref([]);
    const userGroups = ref({
        groups: [],
        ownGroups: [],
        mutualGroups: [],
        remainingGroups: []
    });

    const favoriteWorldsRef = ref(null);

    const sendInviteDialogVisible = ref(false);
    const sendInviteDialog = ref({ message: '', messageSlot: 0, userId: '', messageType: '', params: {} });
    const sendInviteRequestDialogVisible = ref(false);

    const previousInstancesUserDialog = ref({
        visible: false,
        openFlg: false,
        userRef: {}
    });

    const previousImagesDialogVisible = ref(false);
    const previousImagesTable = ref([]);

    const inviteGroupDialog = ref({
        visible: false,
        loading: false,
        groupId: '',
        groupName: '',
        userId: '',
        userIds: [],
        userObject: {}
    });

    const socialStatusDialog = ref({
        visible: false,
        loading: false,
        status: '',
        statusDescription: ''
    });
    const socialStatusHistoryTable = ref({
        data: [],
        tableProps: {
            stripe: true,
            size: 'mini'
        },
        layout: 'table'
    });

    const bioDialog = ref({
        visible: false,
        loading: false,
        bio: '',
        bioLinks: []
    });

    const pronounsDialog = ref({
        visible: false,
        loading: false,
        pronouns: ''
    });

    const userDialogAvatars = computed(() => {
        const { avatars, avatarReleaseStatus } = props.userDialog;
        if (avatarReleaseStatus === 'public' || avatarReleaseStatus === 'private') {
            return avatars.filter((avatar) => avatar.releaseStatus === avatarReleaseStatus);
        }
        return avatars;
    });

    function userFavoriteWorldsStatus(visibility) {
        const style = {};
        if (visibility === 'public') {
            style.green = true;
        } else if (visibility === 'friends') {
            style.blue = true;
        } else {
            style.red = true;
        }
        return style;
    }

    function cleanNote(note) {
        // remove newlines because they aren't supported
        props.userDialog.note = note.replace(/[\r\n]/g, '');
    }

    function closeGalleryDialog() {
        emit('closeGalleryDialog');
    }

    function toggleLastActiveTab(userId) {
        if (userDialogTabsRef.value.currentName === '0') {
            userDialogLastActiveTab.value = t('dialog.user.info.header');
        } else if (userDialogTabsRef.value.currentName === '1') {
            userDialogLastActiveTab.value = t('dialog.user.groups.header');
            if (userDialogLastGroup.value !== userId) {
                userDialogLastGroup.value = userId;
                getUserGroups(userId);
            }
        } else if (userDialogTabsRef.value.currentName === '2') {
            userDialogLastActiveTab.value = t('dialog.user.worlds.header');
            setUserDialogWorlds(userId);
            if (userDialogLastWorld.value !== userId) {
                userDialogLastWorld.value = userId;
                refreshUserDialogWorlds();
            }
        } else if (userDialogTabsRef.value.currentName === '3') {
            userDialogLastActiveTab.value = t('dialog.user.favorite_worlds.header');
            if (userDialogLastFavoriteWorld.value !== userId) {
                userDialogLastFavoriteWorld.value = userId;
                getUserFavoriteWorlds(userId);
            }
        } else if (userDialogTabsRef.value.currentName === '4') {
            userDialogLastActiveTab.value = t('dialog.user.avatars.header');
            setUserDialogAvatars(userId);
            userDialogLastAvatar.value = userId;
            if (userId === API.currentUser.id) {
                refreshUserDialogAvatars();
            }
            setUserDialogAvatarsRemote(userId);
        } else if (userDialogTabsRef.value.currentName === '5') {
            userDialogLastActiveTab.value = t('dialog.user.json.header');
            refreshUserDialogTreeData();
        }
    }

    function showPronounsDialog() {
        const D = pronounsDialog.value;
        D.pronouns = API.currentUser.pronouns;
        D.visible = true;
    }

    function showLanguageDialog() {
        const D = props.languageDialog;
        D.visible = true;
    }

    function showSocialStatusDialog() {
        // this.$nextTick(() =>
        //     $app.adjustDialogZ(this.$refs.socialStatusDialog.$el)
        // );
        const D = socialStatusDialog.value;
        const { statusHistory } = API.currentUser;
        const statusHistoryArray = [];
        for (let i = 0; i < statusHistory.length; ++i) {
            const addStatus = {
                no: i + 1,
                status: statusHistory[i]
            };
            statusHistoryArray.push(addStatus);
        }
        socialStatusHistoryTable.value.data = statusHistoryArray;
        D.status = API.currentUser.status;
        D.statusDescription = API.currentUser.statusDescription;
        D.visible = true;
    }

    async function setUserDialogAvatarsRemote(userId) {
        if (props.avatarRemoteDatabase && userId !== API.currentUser.id) {
            props.userDialog.isAvatarsLoading = true;
            const data = await props.lookupAvatars('authorId', userId);
            const avatars = new Set();
            userDialogAvatars.value.forEach((avatar) => {
                avatars.add(avatar.id, avatar);
            });
            if (data && typeof data === 'object') {
                data.forEach((avatar) => {
                    if (avatar.id && !avatars.has(avatar.id)) {
                        if (avatar.authorId === userId) {
                            props.userDialog.avatars.push(avatar);
                        } else {
                            console.error(`Avatar authorId mismatch for ${avatar.id} - ${avatar.name}`);
                        }
                    }
                });
            }
            props.userDialog.avatarSorting = 'name';
            props.userDialog.avatarReleaseStatus = 'all';
            props.userDialog.isAvatarsLoading = false;
        }
        sortUserDialogAvatars(props.userDialog.avatars);
    }

    async function toggleBadgeVisibility(badge) {
        if (badge.hidden) {
            badge.showcased = false;
        }
        const args = await miscRequest.updateBadge({
            badgeId: badge.badgeId,
            hidden: badge.hidden,
            showcased: badge.showcased
        });
        handleBadgeUpdate(args);
    }

    async function toggleBadgeShowcased(badge) {
        if (badge.showcased) {
            badge.hidden = false;
        }
        const args = await miscRequest.updateBadge({
            badgeId: badge.badgeId,
            hidden: badge.hidden,
            showcased: badge.showcased
        });
        handleBadgeUpdate(args);
    }

    function handleBadgeUpdate(args) {
        // API.$on('BADGE:UPDATE')
        if (args.json) {
            $message({
                message: t('message.badge.updated'),
                type: 'success'
            });
        }
    }

    function setPlayerModeration(userId, type) {
        const D = props.userDialog;
        AppApi.SetVRChatUserModeration(API.currentUser.id, userId, type).then((result) => {
            if (result) {
                if (type === 4) {
                    D.isShowAvatar = false;
                    D.isHideAvatar = true;
                } else if (type === 5) {
                    D.isShowAvatar = true;
                    D.isHideAvatar = false;
                } else {
                    D.isShowAvatar = false;
                    D.isHideAvatar = false;
                }
            } else {
                $message({
                    message: t('message.avatar.change_moderation_failed'),
                    type: 'error'
                });
            }
        });
    }

    function showSendInviteDialog(params, userId) {
        sendInviteDialog.value = {
            params,
            userId,
            messageType: 'invite'
        };
        inviteMessagesRequest.refreshInviteMessageTableData('message');
        clearInviteImageUpload();
        sendInviteDialogVisible.value = true;
    }

    function showSendInviteRequestDialog(params, userId) {
        sendInviteDialog.value = {
            params,
            userId,
            messageType: 'requestInvite'
        };
        inviteMessagesRequest.refreshInviteMessageTableData('request');
        clearInviteImageUpload();
        sendInviteRequestDialogVisible.value = true;
    }

    async function checkPreviousImageAvailable(images) {
        previousImagesTable.value = [];
        for (const image of images) {
            if (image.file && image.file.url) {
                const response = await fetch(image.file.url, {
                    method: 'HEAD',
                    redirect: 'follow'
                }).catch((error) => {
                    console.log(error);
                });
                if (response.status === 200) {
                    previousImagesTable.value.push(image);
                }
            }
        }
    }

    function displayPreviousImages() {
        previousImagesTable.value = [];
        const imageUrl = props.userDialog.ref.currentAvatarImageUrl;

        const fileId = extractFileId(imageUrl);
        if (!fileId) {
            return;
        }
        const params = {
            fileId
        };
        previousImagesDialogVisible.value = true;

        imageRequest.getAvatarImages(params).then((args) => {
            const images = [];
            args.json.versions.forEach((item) => {
                if (!item.deleted) {
                    images.unshift(item);
                }
            });
            checkPreviousImageAvailable(images);
        });
    }

    function showInviteGroupDialog(groupId, userId) {
        const D = inviteGroupDialog.value;
        D.userIds = '';
        D.groups = [];
        D.groupId = groupId;
        D.groupName = groupId;
        D.userId = userId;
        D.userObject = {};
        D.visible = true;
    }

    function userDialogCommand(command) {
        let L;
        const D = props.userDialog;
        if (D.visible === false) {
            return;
        }
        if (command === 'Refresh') {
            showUserDialog(D.id);
        } else if (command === 'Share') {
            copyUserURL(D.id);
        } else if (command === 'Add Favorite') {
            showFavoriteDialog('friend', D.id);
        } else if (command === 'Edit Social Status') {
            showSocialStatusDialog();
        } else if (command === 'Edit Language') {
            showLanguageDialog();
        } else if (command === 'Edit Bio') {
            showBioDialog();
        } else if (command === 'Edit Pronouns') {
            showPronounsDialog();
        } else if (command === 'Logout') {
            logout();
        } else if (command === 'Request Invite') {
            notificationRequest
                .sendRequestInvite(
                    {
                        platform: 'standalonewindows'
                    },
                    D.id
                )
                .then((args) => {
                    $message('Request invite sent');
                    return args;
                });
        } else if (command === 'Invite Message') {
            L = parseLocation(props.lastLocation.location);
            worldRequest
                .getCachedWorld({
                    worldId: L.worldId
                })
                .then((args) => {
                    showSendInviteDialog(
                        {
                            instanceId: props.lastLocation.location,
                            worldId: props.lastLocation.location,
                            worldName: args.ref.name
                        },
                        D.id
                    );
                });
        } else if (command === 'Request Invite Message') {
            showSendInviteRequestDialog(
                {
                    platform: 'standalonewindows'
                },
                D.id
            );
        } else if (command === 'Invite') {
            let currentLocation = props.lastLocation.location;
            if (props.lastLocation.location === 'traveling') {
                currentLocation = props.lastLocationDestination;
            }
            L = parseLocation(currentLocation);
            worldRequest
                .getCachedWorld({
                    worldId: L.worldId
                })
                .then((args) => {
                    notificationRequest
                        .sendInvite(
                            {
                                instanceId: L.tag,
                                worldId: L.tag,
                                worldName: args.ref.name
                            },
                            D.id
                        )
                        .then((_args) => {
                            $message('Invite sent');
                            return _args;
                        });
                });
        } else if (command === 'Show Avatar Author') {
            const { currentAvatarImageUrl } = D.ref;
            showAvatarAuthorDialog(D.id, D.$avatarInfo.ownerId, currentAvatarImageUrl);
        } else if (command === 'Show Fallback Avatar Details') {
            const { fallbackAvatar } = D.ref;
            if (fallbackAvatar) {
                showAvatarDialog(fallbackAvatar);
            } else {
                $message({
                    message: 'No fallback avatar set',
                    type: 'error'
                });
            }
        } else if (command === 'Previous Images') {
            displayPreviousImages();
        } else if (command === 'Previous Instances') {
            showPreviousInstancesUserDialog(D.ref);
        } else if (command === 'Manage Gallery') {
            showGalleryDialog();
        } else if (command === 'Invite To Group') {
            showInviteGroupDialog('', D.id);
            // } else if (command === 'Send Boop') {
            //     this.showSendBoopDialog(D.id);
        } else if (command === 'Hide Avatar') {
            if (D.isHideAvatar) {
                setPlayerModeration(D.id, 0);
            } else {
                setPlayerModeration(D.id, 4);
            }
        } else if (command === 'Show Avatar') {
            if (D.isShowAvatar) {
                setPlayerModeration(D.id, 0);
            } else {
                setPlayerModeration(D.id, 5);
            }
        } else {
            const i18nPreFix = 'dialog.user.actions.';
            const formattedCommand = command.toLowerCase().replace(/ /g, '_');
            const displayCommandText = t(`${i18nPreFix}${formattedCommand}`).includes('i18nPreFix')
                ? command
                : t(`${i18nPreFix}${formattedCommand}`);

            $confirm(
                t('confirm.message', {
                    command: displayCommandText
                }),
                t('confirm.title'),
                {
                    confirmButtonText: t('confirm.confirm_button'),
                    cancelButtonText: t('confirm.cancel_button'),
                    type: 'info',
                    callback: (action) => {
                        if (action === 'confirm') {
                            performUserDialogCommand(command, D.id);
                        }
                    }
                }
            );
        }
    }

    function handleSendFriendRequest(args) {
        // API.$on('FRIEND:REQUEST')
        const ref = API.cachedUsers.get(args.params.userId);
        if (typeof ref === 'undefined') {
            return;
        }
        const friendLogHistory = {
            created_at: new Date().toJSON(),
            type: 'FriendRequest',
            userId: ref.id,
            displayName: ref.displayName
        };
        props.friendLogTable.data.push(friendLogHistory);
        database.addFriendLogHistory(friendLogHistory);

        // API.$on('FRIEND:REQUEST')
        const D = props.userDialog;
        if (D.visible === false || D.id !== args.params.userId) {
            return;
        }
        if (args.json.success) {
            D.isFriend = true;
        } else {
            D.outgoingRequest = true;
        }
    }

    function handleCancelFriendRequest(args) {
        // API.$on('FRIEND:REQUEST:CANCEL')
        const ref = API.cachedUsers.get(args.params.userId);
        if (typeof ref === 'undefined') {
            return;
        }
        const friendLogHistory = {
            created_at: new Date().toJSON(),
            type: 'CancelFriendRequest',
            userId: ref.id,
            displayName: ref.displayName
        };
        props.friendLogTable.data.push(friendLogHistory);
        database.addFriendLogHistory(friendLogHistory);

        // API.$on('FRIEND:REQUEST:CANCEL')
        const D = props.userDialog;
        if (D.visible === false || D.id !== args.params.userId) {
            return;
        }
        D.outgoingRequest = false;
    }

    function handleSendPlayerModeration(args) {
        // API.$on('PLAYER-MODERATION:SEND')
        const ref = {
            json: args.json,
            params: {
                playerModerationId: args.json.id
            }
        };
        API.$emit('PLAYER-MODERATION', ref);
        API.$emit('PLAYER-MODERATION:@SEND', ref);
    }

    async function performUserDialogCommand(command, userId) {
        let key;
        switch (command) {
            case 'Delete Favorite':
                favoriteRequest.deleteFavorite({
                    objectId: userId
                });
                break;
            case 'Accept Friend Request':
                key = API.getFriendRequest(userId);
                if (key === '') {
                    const args = await friendRequest.sendFriendRequest({
                        userId
                    });
                    handleSendFriendRequest(args);
                } else {
                    notificationRequest.acceptFriendRequestNotification({
                        notificationId: key
                    });
                }
                break;
            case 'Decline Friend Request':
                key = API.getFriendRequest(userId);
                if (key === '') {
                    const args = await friendRequest.cancelFriendRequest({
                        userId
                    });
                    handleCancelFriendRequest(args);
                } else {
                    notificationRequest.hideNotification({
                        notificationId: key
                    });
                }
                break;
            case 'Cancel Friend Request': {
                const args = await friendRequest.cancelFriendRequest({
                    userId
                });
                handleCancelFriendRequest(args);
                break;
            }
            case 'Send Friend Request': {
                const args = await friendRequest.sendFriendRequest({
                    userId
                });
                handleSendFriendRequest(args);
                break;
            }
            case 'Moderation Unblock':
                playerModerationRequest.deletePlayerModeration({
                    moderated: userId,
                    type: 'block'
                });
                break;
            case 'Moderation Block': {
                const args = await playerModerationRequest.sendPlayerModeration({
                    moderated: userId,
                    type: 'block'
                });
                handleSendPlayerModeration(args);
                break;
            }
            case 'Moderation Unmute':
                playerModerationRequest.deletePlayerModeration({
                    moderated: userId,
                    type: 'mute'
                });
                break;
            case 'Moderation Mute': {
                const args = await playerModerationRequest.sendPlayerModeration({
                    moderated: userId,
                    type: 'mute'
                });
                handleSendPlayerModeration(args);
                break;
            }
            case 'Moderation Enable Avatar Interaction':
                playerModerationRequest.deletePlayerModeration({
                    moderated: userId,
                    type: 'interactOff'
                });
                break;
            case 'Moderation Disable Avatar Interaction': {
                const args = await playerModerationRequest.sendPlayerModeration({
                    moderated: userId,
                    type: 'interactOff'
                });
                handleSendPlayerModeration(args);
                break;
            }
            case 'Moderation Enable Chatbox':
                playerModerationRequest.deletePlayerModeration({
                    moderated: userId,
                    type: 'muteChat'
                });
                break;
            case 'Moderation Disable Chatbox': {
                const args = await playerModerationRequest.sendPlayerModeration({
                    moderated: userId,
                    type: 'muteChat'
                });
                handleSendPlayerModeration(args);
                break;
            }
            case 'Report Hacking':
                reportUserForHacking(userId);
                break;
            case 'Unfriend':
                friendRequest.deleteFriend({
                    userId
                });
                break;
        }
    }

    function reportUserForHacking(userId) {
        miscRequest.reportUser({
            userId,
            contentType: 'user',
            reason: 'behavior-hacking',
            type: 'report'
        });
    }

    async function getUserGroups(userId) {
        props.userDialog.isGroupsLoading = true;
        userGroups.value = {
            groups: [],
            ownGroups: [],
            mutualGroups: [],
            remainingGroups: []
        };
        const args = await groupRequest.getGroups({ userId });
        if (userId !== props.userDialog.id) {
            props.userDialog.isGroupsLoading = false;
            return;
        }
        if (userId === API.currentUser.id) {
            // update current user groups
            API.currentUserGroups.clear();
            args.json.forEach((group) => {
                const ref = API.applyGroup(group);
                if (!API.currentUserGroups.has(group.id)) {
                    API.currentUserGroups.set(group.id, ref);
                }
            });

            saveCurrentUserGroups();
        }
        userGroups.value.groups = args.json;
        for (let i = 0; i < args.json.length; ++i) {
            const group = args.json[i];
            if (!group?.id) {
                console.error('getUserGroups, group ID is missing', group);
                continue;
            }
            if (group.ownerId === userId) {
                userGroups.value.ownGroups.unshift(group);
            }
            if (userId === API.currentUser.id) {
                // skip mutual groups for current user
                if (group.ownerId !== userId) {
                    userGroups.value.remainingGroups.unshift(group);
                }
                continue;
            }
            if (group.mutualGroup) {
                userGroups.value.mutualGroups.unshift(group);
            }
            if (!group.mutualGroup && group.ownerId !== userId) {
                userGroups.value.remainingGroups.unshift(group);
            }
        }
        if (userId === API.currentUser.id) {
            props.userDialog.groupSorting = userDialogGroupSortingOptions.inGame;
        } else if (props.userDialog.groupSorting === userDialogGroupSortingOptions.inGame) {
            props.userDialog.groupSorting = userDialogGroupSortingOptions.alphabetical;
        }
        await sortCurrentUserGroups();
        props.userDialog.isGroupsLoading = false;
    }

    function compareByMemberCount(a, b) {
        if (typeof a.memberCount !== 'number' || typeof b.memberCount !== 'number') {
            return 0;
        }
        return a.memberCount - b.memberCount;
    }

    function sortGroupsByInGame(a, b) {
        const aIndex = props.inGameGroupOrder.indexOf(a?.id);
        const bIndex = props.inGameGroupOrder.indexOf(b?.id);
        if (aIndex === -1 && bIndex === -1) {
            return 0;
        }
        if (aIndex === -1) {
            return 1;
        }
        if (bIndex === -1) {
            return -1;
        }
        return aIndex - bIndex;
    }

    async function sortCurrentUserGroups() {
        const D = props.userDialog;
        let sortMethod = function () {};

        switch (D.groupSorting.value) {
            case 'alphabetical':
                sortMethod = utils.compareByName;
                break;
            case 'members':
                sortMethod = compareByMemberCount;
                break;
            case 'inGame':
                sortMethod = sortGroupsByInGame;
                await props.updateInGameGroupOrder();
                break;
        }

        userGroups.value.ownGroups.sort(sortMethod);
        userGroups.value.mutualGroups.sort(sortMethod);
        userGroups.value.remainingGroups.sort(sortMethod);
    }

    function setUserDialogAvatars(userId) {
        const avatars = new Set();
        userDialogAvatars.value.forEach((avatar) => {
            avatars.add(avatar.id, avatar);
        });
        for (const ref of API.cachedAvatars.values()) {
            if (ref.authorId === userId && !avatars.has(ref.id)) {
                props.userDialog.avatars.push(ref);
            }
        }
        sortUserDialogAvatars(props.userDialog.avatars);
    }

    function setUserDialogWorlds(userId) {
        const worlds = [];
        for (const ref of API.cachedWorlds.values()) {
            if (ref.authorId === userId) {
                worlds.push(ref);
            }
        }
        props.userDialog.worlds = worlds;
    }

    function refreshUserDialogWorlds() {
        const D = props.userDialog;
        if (D.isWorldsLoading) {
            return;
        }
        D.isWorldsLoading = true;
        const params = {
            n: 50,
            offset: 0,
            sort: props.userDialog.worldSorting.value,
            order: props.userDialog.worldOrder.value,
            // user: 'friends',
            userId: D.id,
            releaseStatus: 'public'
        };
        if (params.userId === API.currentUser.id) {
            params.user = 'me';
            params.releaseStatus = 'all';
        }
        const map = new Map();
        for (const ref of API.cachedWorlds.values()) {
            if (ref.authorId === D.id && (ref.authorId === API.currentUser.id || ref.releaseStatus === 'public')) {
                API.cachedWorlds.delete(ref.id);
            }
        }
        API.bulk({
            fn: worldRequest.getWorlds,
            N: -1,
            params,
            handle: (args) => {
                for (const json of args.json) {
                    const $ref = API.cachedWorlds.get(json.id);
                    if (typeof $ref !== 'undefined') {
                        map.set($ref.id, $ref);
                    }
                }
            },
            done: () => {
                if (D.id === params.userId) {
                    setUserDialogWorlds(D.id);
                }
                D.isWorldsLoading = false;
            }
        });
    }

    async function getUserFavoriteWorlds(userId) {
        props.userDialog.isFavoriteWorldsLoading = true;
        if (favoriteWorldsRef.value) {
            favoriteWorldsRef.value.currentName = '0'; // select first tab
        }
        userFavoriteWorlds.value = [];
        const worldLists = [];
        let params = {
            ownerId: userId,
            n: 100
        };
        const json = await API.call('favorite/groups', {
            method: 'GET',
            params
        });
        for (let i = 0; i < json.length; ++i) {
            const list = json[i];
            if (list.type !== 'world') {
                continue;
            }
            params = {
                n: 100,
                offset: 0,
                userId,
                tag: list.name
            };
            try {
                const args = await favoriteRequest.getFavoriteWorlds(params);
                worldLists.push([list.displayName, list.visibility, args.json]);
            } catch (err) {
                console.error('getUserFavoriteWorlds', err);
            }
        }
        userFavoriteWorlds.value = worldLists;
        props.userDialog.isFavoriteWorldsLoading = false;
    }

    function userDialogTabClick(obj) {
        const userId = props.userDialog.id;
        if (userDialogLastActiveTab.value === obj.label) {
            return;
        }
        if (obj.label === t('dialog.user.groups.header')) {
            if (userDialogLastGroup.value !== userId) {
                userDialogLastGroup.value = userId;
                getUserGroups(userId);
            }
        } else if (obj.label === t('dialog.user.avatars.header')) {
            setUserDialogAvatars(userId);
            if (userDialogLastAvatar.value !== userId) {
                userDialogLastAvatar.value = userId;
                if (userId === API.currentUser.id) {
                    refreshUserDialogAvatars();
                } else {
                    setUserDialogAvatarsRemote(userId);
                }
            }
        } else if (obj.label === t('dialog.user.worlds.header')) {
            setUserDialogWorlds(userId);
            if (userDialogLastWorld.value !== userId) {
                userDialogLastWorld.value = userId;
                refreshUserDialogWorlds();
            }
        } else if (obj.label === t('dialog.user.favorite_worlds.header')) {
            if (userDialogLastFavoriteWorld.value !== userId) {
                userDialogLastFavoriteWorld.value = userId;
                getUserFavoriteWorlds(userId);
            }
        } else if (obj.label === t('dialog.user.json.header')) {
            refreshUserDialogTreeData();
        }
        userDialogLastActiveTab.value = obj.label;
    }

    function checkNote(ref, note) {
        if (ref.note !== note) {
            addNote(ref.id, note);
        }
    }

    async function addNote(userId, note) {
        if (props.userDialog.id === userId) {
            props.userDialog.noteSaving = true;
        }
        const args = await miscRequest.saveNote({
            targetUserId: userId,
            note
        });
        handleNoteChange(args);
    }



    function handleNoteChange(args) {
        // API.$on('NOTE')
        let _note = '';
        let targetUserId = '';
        if (typeof args.json !== 'undefined') {
            _note = utils.replaceBioSymbols(args.json.note);
        }
        if (typeof args.params !== 'undefined') {
            targetUserId = args.params.targetUserId;
        }
        if (targetUserId === props.userDialog.id) {
            if (_note === args.params.note) {
                props.userDialog.noteSaving = false;
                props.userDialog.note = _note;
            } else {
                // response is cached sadge :<
                userRequest.getUser({ userId: targetUserId });
            }
        }
        const ref = API.cachedUsers.get(targetUserId);
        if (typeof ref !== 'undefined') {
            ref.note = _note;
        }
    }

    async function deleteNote(userId) {
        if (props.userDialog.id === userId) {
            props.userDialog.noteSaving = true;
        }
        const args = await miscRequest.saveNote({
            targetUserId: userId,
            note: ''
        });
        handleNoteChange(args);
    }

    function onUserMemoChange() {
        const D = props.userDialog;
        saveUserMemo(D.id, D.memo);
    }

    function showBioDialog() {
        const D = bioDialog.value;
        D.bio = API.currentUser.bio;
        D.bioLinks = API.currentUser.bioLinks.slice();
        D.visible = true;
    }

    function showPreviousInstancesUserDialog(userRef) {
        const D = previousInstancesUserDialog.value;
        D.userRef = userRef;
        D.visible = true;
        // trigger watcher
        D.openFlg = true;
        nextTick(() => (D.openFlg = false));
    }

    function timeToText(args) {
        return utils.timeToText(args);
    }

    function toggleAvatarCopying() {
        userRequest.saveCurrentUser({
            allowAvatarCopying: !API.currentUser.allowAvatarCopying
        });
        //     .then((args) => {
        //     return args;
        // });
    }

    function resetHome() {
        $confirm('Continue? Reset Home', 'Confirm', {
            confirmButtonText: 'Confirm',
            cancelButtonText: 'Cancel',
            type: 'info',
            callback: (action) => {
                if (action === 'confirm') {
                    userRequest
                        .saveCurrentUser({
                            homeLocation: ''
                        })
                        .then((args) => {
                            $message({
                                message: 'Home world has been reset',
                                type: 'success'
                            });
                            return args;
                        });
                }
            }
        });
    }

    function copyUserId(userId) {
        copyToClipboard(userId, 'User ID copied to clipboard');
    }

    function copyUserURL(userId) {
        copyToClipboard(`https://vrchat.com/home/user/${userId}`, 'User URL copied to clipboard');
    }

    function copyUserDisplayName(displayName) {
        copyToClipboard(displayName, 'User DisplayName copied to clipboard');
    }

    async function setUserDialogGroupSorting(sortOrder) {
        const D = props.userDialog;
        if (D.groupSorting === sortOrder) {
            return;
        }
        D.groupSorting = sortOrder;
        await sortCurrentUserGroups();
    }

    async function exitEditModeCurrentUserGroups() {
        userDialogGroupEditMode.value = false;
        userDialogGroupEditGroups.value = [];
        await sortCurrentUserGroups();
    }

    async function editModeCurrentUserGroups() {
        await props.updateInGameGroupOrder();
        userDialogGroupEditGroups.value = Array.from(API.currentUserGroups.values());
        userDialogGroupEditGroups.value.sort(sortGroupsByInGame);
        userDialogGroupEditMode.value = true;
    }

    async function saveInGameGroupOrder() {
        userDialogGroupEditGroups.value.sort(sortGroupsByInGame);
        try {
            await AppApi.SetVRChatRegistryKey(
                `VRC_GROUP_ORDER_${API.currentUser.id}`,
                JSON.stringify(props.inGameGroupOrder),
                3
            );
        } catch (err) {
            console.error(err);
            $message({
                message: 'Failed to save in-game group order',
                type: 'error'
            });
        }
    }

    function moveGroupUp(groupId) {
        const index = props.inGameGroupOrder.indexOf(groupId);
        if (index > 0) {
            props.inGameGroupOrder.splice(index, 1);
            props.inGameGroupOrder.splice(index - 1, 0, groupId);
            saveInGameGroupOrder();
        }
    }

    function moveGroupDown(groupId) {
        const index = props.inGameGroupOrder.indexOf(groupId);
        if (index < props.inGameGroupOrder.length - 1) {
            props.inGameGroupOrder.splice(index, 1);
            props.inGameGroupOrder.splice(index + 1, 0, groupId);
            saveInGameGroupOrder();
        }
    }

    function moveGroupTop(groupId) {
        const index = props.inGameGroupOrder.indexOf(groupId);
        if (index > 0) {
            props.inGameGroupOrder.splice(index, 1);
            props.inGameGroupOrder.unshift(groupId);
            saveInGameGroupOrder();
        }
    }

    function moveGroupBottom(groupId) {
        const index = props.inGameGroupOrder.indexOf(groupId);
        if (index < props.inGameGroupOrder.length - 1) {
            props.inGameGroupOrder.splice(index, 1);
            props.inGameGroupOrder.push(groupId);
            saveInGameGroupOrder();
        }
    }

    async function setUserDialogWorldSorting(sortOrder) {
        const D = props.userDialog;
        if (D.worldSorting === sortOrder) {
            return;
        }
        D.worldSorting = sortOrder;
        refreshUserDialogWorlds();
    }

    async function setUserDialogWorldOrder(order) {
        const D = props.userDialog;
        if (D.worldOrder === order) {
            return;
        }
        D.worldOrder = order;
        refreshUserDialogWorlds();
    }

    function changeUserDialogAvatarSorting(sortOption) {
        const D = props.userDialog;
        D.avatarSorting = sortOption;
        sortUserDialogAvatars(D.avatars);
    }

    function refreshUserDialogTreeData() {
        emit('refreshUserDialogTreeData');
    }
    function setGroupVisibility(groupId, visibility) {
        emit('setGroupVisibility', groupId, visibility);
    }
    function refreshUserDialogAvatars() {
        emit('refreshUserDialogAvatars');
    }
    function leaveGroupPrompt(id) {
        emit('leaveGroupPrompt', id);
    }
    function sortUserDialogAvatars(avatars) {
        emit('sortUserDialogAvatars', avatars);
    }
    function logout() {
        emit('logout');
    }
    function showAvatarAuthorDialog(userId, authorId, currentAvatarImageUrl) {
        emit('showAvatarAuthorDialog', userId, authorId, currentAvatarImageUrl);
    }
    function showGalleryDialog() {
        emit('showGalleryDialog');
    }
    function saveCurrentUserGroups() {
        emit('saveCurrentUserGroups');
    }
    function saveUserMemo(userId, memo) {
        emit('saveUserMemo', userId, memo);
    }
    function clearInviteImageUpload() {
        emit('clearInviteImageUpload');
    }
    function inviteImageUpload(event) {
        emit('inviteImageUpload', event);
    }
    function refreshGalleryTable() {
        emit('refreshGalleryTable');
    }
    function refreshVRCPlusIconsTable() {
        emit('refreshVRCPlusIconsTable');
    }
    function refreshStickerTable() {
        emit('refreshStickerTable');
    }
    function refreshEmojiTable() {
        emit('refreshEmojiTable');
    }
    function refreshPrintTable() {
        emit('refreshPrintTable');
    }
</script>
