mixin userDialog el-dialog.x-dialog.x-user-dialog( :before-close='beforeDialogClose' @mousedown.native='dialogMouseDown' @mouseup.native='dialogMouseUp' ref='userDialog' :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.x-link( slot='reference' :src='userDialog.ref.profilePicOverrideThumbnail || userDialog.ref.profilePicOverride' style='flex: none; height: 120px; width: 213.33px; border-radius: 12px; object-fit: cover') img.x-link( v-lazy='userDialog.ref.profilePicOverride' style='height: 400px' @click='showFullscreenImageDialog(userDialog.ref.profilePicOverride)') el-popover(v-else placement='right' width='500px' trigger='click') img.x-link( slot='reference' :src='userDialog.ref.currentAvatarThumbnailImageUrl' style='flex: none; height: 120px; width: 160px; border-radius: 12px; object-fit: cover') img.x-link( v-lazy='userDialog.ref.currentAvatarImageUrl' style='height: 500px' @click='showFullscreenImageDialog(userDialog.ref.currentAvatarImageUrl)') 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(v-else-if='userDialog.ref.state === "offline"') {{ $t('dialog.user.status.offline') }} span(v-else-if='userDialog.ref.status === "active"') {{ $t('dialog.user.status.online') }} span(v-else-if='userDialog.ref.status === "join me"') {{ $t('dialog.user.status.join_me') }} span(v-else-if='userDialog.ref.status === "ask me"') {{ $t('dialog.user.status.ask_me') }} span(v-else-if='userDialog.ref.status === "busy"') {{ $t('dialog.user.status.busy') }} span(v-else) {{ $t('dialog.user.status.offline') }} i.x-user-status(:class='userStatusClass(userDialog.ref)') template(v-if='userDialog.previousDisplayNames.length > 0') el-tooltip(placement='bottom') template(#content) span {{ $t('dialog.user.previous_display_names') }} div( v-for='displayName in userDialog.previousDisplayNames' :key='displayName' placement='top') span(v-text='displayName') i.el-icon-caret-bottom el-popover(placement='top' trigger='click') span.dialog-title( slot='reference' v-text='userDialog.ref.displayName' style='margin-left: 5px; margin-right: 5px; cursor: pointer') span(style='display: block; text-align: center; font-family: monospace') {{ userDialog.ref.displayName | textToHex }} el-tooltip( v-if='userDialog.ref.pronouns' placement='top' :content='$t("dialog.user.pronouns")' :disabled='hideTooltips') span.x-grey( v-text='userDialog.ref.pronouns' style='margin-right: 5px; font-family: monospace; font-size: 12px') el-tooltip(v-for='item in userDialog.ref.$languages' :key='item.key' placement='top') template(#content) span {{ item.value }} ({{ item.key }}) span.flags( :class='languageClass(item.key)' style='display: inline-block; margin-right: 5px') template(v-if='userDialog.ref.id === API.currentUser.id') br el-popover(placement='top' trigger='click') span.x-grey( slot='reference' v-text='API.currentUser.username' style='margin-right: 10px; font-family: monospace; font-size: 12px; cursor: pointer') span(style='display: block; text-align: center; font-family: monospace') {{ API.currentUser.username | textToHex }} div(style='margin-top: 5px') el-tag.name( type='info' effect='plain' size='mini' :class='userDialog.ref.$trustClass' v-text='userDialog.ref.$trustLevel' style='margin-right: 5px; margin-top: 5px') el-tag.x-tag-friend( v-if='userDialog.isFriend && userDialog.friend' type='info' effect='plain' size='mini' style='margin-right: 5px; margin-top: 5px') {{ $t('dialog.user.tags.friend_no', { number: userDialog.ref.$friendNumber ? userDialog.ref.$friendNumber : "" }) }} el-tag.x-tag-troll( v-if='userDialog.ref.$isTroll' type='info' effect='plain' size='mini' style='margin-right: 5px; margin-top: 5px') Nuisance el-tag.x-tag-troll( v-if='userDialog.ref.$isProbableTroll' type='info' effect='plain' size='mini' style='margin-right: 5px; margin-top: 5px') Almost Nuisance el-tag.x-tag-vip( v-if='userDialog.ref.$isModerator' type='info' effect='plain' size='mini' style='margin-right: 5px; margin-top: 5px') {{ $t('dialog.user.tags.vrchat_team') }} el-tag.x-tag-platform-pc( v-if='userDialog.ref.last_platform === "standalonewindows"' type='info' effect='plain' size='mini' style='margin-right: 5px; margin-top: 5px') PC el-tag.x-tag-platform-quest( v-else-if='userDialog.ref.last_platform === "android"' type='info' effect='plain' size='mini' style='margin-right: 5px; margin-top: 5px') Android el-tag.x-tag-platform-ios( v-else-if='userDialog.ref.last_platform === "ios"' type='info' effect='plain' size='mini' style='margin-right: 5px; margin-top: 5px') iOS el-tag.x-tag-platform-other( v-else-if='userDialog.ref.last_platform' type='info' effect='plain' size='mini' style='margin-right: 5px; margin-top: 5px') {{ userDialog.ref.last_platform }} el-tag.x-tag-age-verification( v-if='userDialog.ref.ageVerificationStatus && userDialog.ref.ageVerificationStatus !== "hidden"' type='info' effect='plain' size='mini' style='margin-right: 5px; margin-top: 5px') {{ userDialog.ref.ageVerificationStatus }} el-tag.name( v-if='userDialog.ref.$customTag' type='info' effect='plain' size='mini' v-text='userDialog.ref.$customTag' :style='{ color: userDialog.ref.$customTagColour, "border-color": userDialog.ref.$customTagColour }' style='margin-right: 5px; margin-top: 5px') br template(v-for='badge in userDialog.ref.badges') el-tooltip(placement='top' :key='badge.badgeId') template(#content) span {{ badge.badgeName }} span(v-if='badge.hidden')  (Hidden) el-popover(placement='right' width='300px' trigger='click') img.x-link.x-user-badge( slot='reference' :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.x-link( v-lazy='badge.badgeImageUrl' style='width: 300px' @click='showFullscreenImageDialog(badge.badgeImageUrl)') br div(style='display: block; width: 300px; word-break: normal') span {{ badge.badgeName }} br span.x-grey(style='font-size: 12px') {{ badge.badgeDescription }} br span.x-grey( v-if='badge.assignedAt' style='font-family: monospace; font-size: 12px') {{ $t('dialog.user.badges.assigned') }}: {{ badge.assignedAt | formatDate('long') }} template(v-if='userDialog.id === API.currentUser.id') br el-checkbox( @change='toggleBadgeVisibility(badge)' v-model='badge.hidden' style='margin-top: 5px') {{ $t('dialog.user.badges.hidden') }} br el-checkbox( @change='toggleBadgeShowcased(badge)' v-model='badge.showcased' style='margin-top: 5px') {{ $t('dialog.user.badges.showcased') }} div(style='margin-top: 5px') span(v-text='userDialog.ref.statusDescription' style='font-size: 12px') div(v-if='userDialog.ref.userIcon' style='flex: none; margin-right: 10px') el-popover(placement='right' width='500px' trigger='click') img.x-link( slot='reference' :src='userImage(userDialog.ref, true, "256")' style='flex: none; width: 120px; height: 120px; border-radius: 12px; object-fit: cover') img.x-link( v-lazy='userDialog.ref.userIcon' style='height: 500px' @click='showFullscreenImageDialog(userDialog.ref.userIcon)') 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( @click='userDialogCommand("Add Favorite")' type='warning' icon='el-icon-star-on' circle) el-tooltip( v-else placement='top' :content='$t("dialog.user.actions.favorite_tooltip")' :disabled='hideTooltips') el-button( type='default' @click='userDialogCommand("Add Favorite")' icon='el-icon-star-off' circle) el-dropdown(trigger='click' @command='userDialogCommand' size='small') el-button( :type='userDialog.incomingRequest || userDialog.outgoingRequest ? "success" : userDialog.isBlock || userDialog.isMute ? "danger" : "default"' icon='el-icon-more' circle style='margin-left: 5px') el-dropdown-menu(#default='dropdown') el-dropdown-item(icon='el-icon-refresh' command='Refresh') {{ $t('dialog.user.actions.refresh') }} el-dropdown-item(icon='el-icon-share' command='Share') {{ $t('dialog.user.actions.share') }} 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(icon='el-icon-s-custom' command='Show Avatar Author') {{ $t('dialog.user.actions.show_avatar_author') }} el-dropdown-item(icon='el-icon-s-custom' command='Show Fallback Avatar Details') {{ $t('dialog.user.actions.show_fallback_avatar') }} el-dropdown-item(icon='el-icon-edit' command='Edit Social Status' divided) {{ $t('dialog.user.actions.edit_status') }} el-dropdown-item(icon='el-icon-edit' command='Edit Language') {{ $t('dialog.user.actions.edit_language') }} el-dropdown-item(icon='el-icon-edit' command='Edit Bio') {{ $t('dialog.user.actions.edit_bio') }} el-dropdown-item(icon='el-icon-edit' command='Edit Pronouns') {{ $t('dialog.user.actions.edit_pronouns') }} el-dropdown-item(icon='el-icon-switch-button' command='Logout' divided) {{ $t('dialog.user.actions.logout') }} 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(icon='el-icon-postcard' command='Request Invite Message') {{ $t('dialog.user.actions.request_invite_with_message') }} 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(icon='el-icon-message' command='Invite Message') {{ $t('dialog.user.actions.invite_with_message') }} 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(icon='el-icon-close' command='Decline Friend Request') {{ $t('dialog.user.actions.decline_friend_request') }} 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(v-else icon='el-icon-plus' command='Send Friend Request') {{ $t('dialog.user.actions.send_friend_request') }} el-dropdown-item(icon='el-icon-message' command='Invite To Group') {{ $t('dialog.user.actions.invite_to_group') }} //- 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(icon='el-icon-s-custom' command='Show Fallback Avatar Details') {{ $t('dialog.user.actions.show_fallback_avatar') }} el-dropdown-item(icon='el-icon-tickets' command='Previous Instances') {{ $t('dialog.user.actions.show_previous_instances') }} 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( 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( v-else icon='el-icon-circle-close' command='Moderation Block' divided :disabled='userDialog.ref.$isModerator') {{ $t('dialog.user.actions.moderation_block') }} 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( v-else icon='el-icon-turn-off-microphone' command='Moderation Mute' :disabled='userDialog.ref.$isModerator') {{ $t('dialog.user.actions.moderation_mute') }} 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( v-else icon='el-icon-chat-dot-round' command='Moderation Disable Chatbox') {{ $t('dialog.user.actions.moderation_disable_chatbox') }} el-dropdown-item(icon='el-icon-user-solid' command='Show Avatar') i.el-icon-check.el-icon--left(v-if='userDialog.isShowAvatar') span {{ $t('dialog.user.actions.moderation_show_avatar') }} el-dropdown-item(icon='el-icon-user' command='Hide Avatar') i.el-icon-check.el-icon--left(v-if='userDialog.isHideAvatar') span {{ $t('dialog.user.actions.moderation_hide_avatar') }} 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( v-else icon='el-icon-circle-close' command='Moderation Disable Avatar Interaction') {{ $t('dialog.user.actions.moderation_disable_avatar_interaction') }} el-dropdown-item( icon='el-icon-s-flag' command='Report Hacking' :disabled='userDialog.ref.$isModerator') {{ $t('dialog.user.actions.report_hacking') }} template(v-if='userDialog.isFriend') el-dropdown-item( icon='el-icon-delete' command='Unfriend' divided style='color: #f56c6c') {{ $t('dialog.user.actions.unfriend') }} el-tabs(ref='userDialogTabs' @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') 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') el-tooltip( placement='top' :content='$t("dialog.user.info.refresh_instance_info")' :disabled='hideTooltips') el-button( @click='refreshInstancePlayerCount(userDialog.$location.tag)' size='mini' icon='el-icon-refresh' style='margin-left: 5px' circle) last-join( :location='userDialog.$location.tag' :currentlocation='lastLocation.location') instance-info( :location='userDialog.$location.tag' :instance='userDialog.instance.ref' :friendcount='userDialog.instance.friendCount' :updateelement='updateInstanceInfo') location( :location='userDialog.ref.location' :traveling='userDialog.ref.travelingToLocation' style='display: block; margin-top: 5px') .x-friend-list(style='flex: 1; margin-top: 10px; max-height: 150px') .x-friend-item.x-friend-item-border( v-if='userDialog.$location.userId' @click='showUserDialog(userDialog.$location.userId)') template(v-if='userDialog.$location.user') .avatar(:class='userStatusClass(userDialog.$location.user)') img(:src='userImage(userDialog.$location.user, true)') .detail span.name( v-text='userDialog.$location.user.displayName' :style='{ color: userDialog.$location.user.$userColour }') span.extra {{ $t('dialog.user.info.instance_creator') }} span(v-else v-text='userDialog.$location.userId') .x-friend-item.x-friend-item-border( v-for='user in userDialog.users' :key='user.id' @click='showUserDialog(user.id)') .avatar(:class='userStatusClass(user)') img(:src='userImage(user, true)') .detail span.name(v-text='user.displayName' :style='{ color: user.$userColour }') span.extra(v-if='user.location === "traveling"') i.el-icon-loading(style='margin-right: 5px') timer(:epoch='user.$travelingToTime') span.extra(v-else) timer(:epoch='user.$location_at') .x-friend-list(style='max-height: none') .x-friend-item(v-if='!hideUserNotes' style='width: 100%; cursor: default') .detail span.name {{ $t('dialog.user.info.note') }} el-input( v-model='userDialog.note' type='textarea' maxlength='256' show-word-limit :rows='2' :autosize='{ minRows: 1, maxRows: 20 }' @change='checkNote(userDialog.ref, userDialog.note)' @input='cleanNote(userDialog.note)' :placeholder='$t("dialog.user.info.note_placeholder")' size='mini' resize='none') div(style='float: right') i.el-icon-loading(v-if='userDialog.noteSaving' style='margin-left: 5px') i.el-icon-more-outline( v-else-if='userDialog.note !== userDialog.ref.note' style='margin-left: 5px') el-button( v-if='userDialog.note' type='text' icon='el-icon-delete' size='mini' @click='deleteNote(userDialog.id)' style='margin-left: 5px') .x-friend-item(v-if='!hideUserMemos' style='width: 100%; cursor: default') .detail span.name {{ $t('dialog.user.info.memo') }} el-input.extra( v-model='userDialog.memo' @change='onUserMemoChange' type='textarea' :rows='2' :autosize='{ minRows: 1, maxRows: 20 }' :placeholder='$t("dialog.user.info.memo_placeholder")' size='mini' resize='none') .x-friend-item(style='width: 100%; cursor: default') .detail span.name( v-if='userDialog.id !== API.currentUser.id && userDialog.ref.profilePicOverride && userDialog.ref.currentAvatarImageUrl') {{ $t('dialog.user.info.avatar_info_last_seen') }} span.name(v-else) {{ $t('dialog.user.info.avatar_info') }} .extra avatar-info( :imageurl='userDialog.ref.currentAvatarImageUrl' :userid='userDialog.id' :avatartags='userDialog.ref.currentAvatarTags' style='display: inline-block') el-tooltip( v-if='userDialog.ref.profilePicOverride && !userDialog.ref.currentAvatarImageUrl && !hideTooltips' placement='top' :content='$t("dialog.user.info.vrcplus_hides_avatar")') i.el-icon-warning .x-friend-item(style='width: 100%; cursor: default') .detail span.name(style='margin-bottom: 5px') {{ $t('dialog.user.info.represented_group') }} .extra( v-if='userDialog.isRepresentedGroupLoading || (userDialog.representedGroup && userDialog.representedGroup.isRepresenting)') div(style='display: inline-block; flex: none; margin-right: 5px') el-popover(placement='right' width='500px' trigger='click') el-image.x-link( slot='reference' v-loading='userDialog.isRepresentedGroupLoading' :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') img.x-link( v-lazy='userDialog.representedGroup.iconUrl' style='height: 500px' @click='showFullscreenImageDialog(userDialog.representedGroup.iconUrl)') 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(v-text='userDialog.representedGroup.name' style='margin-right: 5px') span ({{ userDialog.representedGroup.memberCount }}) .extra(v-else) - .x-friend-item(style='width: 100%; cursor: default') .detail span.name {{ $t('dialog.user.info.bio') }} pre.extra( style='font-family: inherit; font-size: 12px; white-space: pre-wrap; margin: 0 0.5em 0 0') {{ userDialog.ref.bio || '-' }} div(v-if='userDialog.id === API.currentUser.id' style='float: right') el-button( type='text' icon='el-icon-edit' size='mini' @click='showBioDialog' style='margin-left: 5px') div(style='margin-top: 5px') el-tooltip(v-for='(link, index) in userDialog.ref.bioLinks' :key='index') template(#content) span(v-text='link') 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)') template(v-if='API.currentUser.id !== userDialog.id') .x-friend-item(style='cursor: default') .detail span.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.el-icon-warning span.extra {{ userDialog.lastSeen | formatDate('long') }} el-tooltip( :disabled='hideTooltips' placement='top' :content='$t("dialog.user.info.open_previouse_instance")') .x-friend-item(@click='showPreviousInstancesUserDialog(userDialog.ref)') .detail span.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.el-icon-warning span.extra(v-if='userDialog.joinCount === 0') - span.extra(v-else v-text='userDialog.joinCount') .x-friend-item(style='cursor: default') .detail span.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.el-icon-warning span.extra(v-if='userDialog.timeSpent === 0') - span.extra(v-else) {{ timeToText(userDialog.timeSpent) }} template(v-else) el-tooltip( :disabled='hideTooltips || API.currentUser.id !== userDialog.id' placement='top' :content='$t("dialog.user.info.open_previouse_instance")') .x-friend-item(@click='showPreviousInstancesUserDialog(userDialog.ref)') .detail span.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.el-icon-warning span.extra(v-if='userDialog.timeSpent === 0') - span.extra(v-else) {{ timeToText(userDialog.timeSpent) }} .x-friend-item(style='cursor: default') el-tooltip(:placement='API.currentUser.id !== userDialog.id ? "bottom" : "top"') template(#content) span {{ userOnlineForTimestamp(userDialog) | formatDate('short') }} .detail span.name(v-if='userDialog.ref.state === "online" && userDialog.ref.$online_for') {{ $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.el-icon-warning span.name(v-else) {{ $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.el-icon-warning span.extra {{ userOnlineFor(userDialog) }} .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') }} .detail span.name {{ $t('dialog.user.info.last_activity') }} span.extra {{ userDialog.ref.last_activity | formatDate('long') }} .x-friend-item(style='cursor: default') .detail span.name {{ $t('dialog.user.info.date_joined') }} span.extra(v-text='userDialog.ref.date_joined') .x-friend-item(v-if='API.currentUser.id !== userDialog.id' style='cursor: default') el-tooltip(placement='top' :disabled='!userDialog.dateFriendedInfo.length') template(#content v-if='userDialog.dateFriendedInfo.length') template(v-for='ref in userDialog.dateFriendedInfo') span {{ ref.type }}: {{ ref.created_at | formatDate('long') }} br .detail span.name(v-if='userDialog.unFriended') {{ $t('dialog.user.info.unfriended') }} el-tooltip( v-if='!hideTooltips' placement='top' style='margin-left: 5px' :content='$t("dialog.user.info.accuracy_notice")') i.el-icon-warning span.name(v-else) {{ $t('dialog.user.info.friended') }} el-tooltip( v-if='!hideTooltips' placement='top' style='margin-left: 5px' :content='$t("dialog.user.info.accuracy_notice")') i.el-icon-warning span.extra {{ userDialog.dateFriended | formatDate('long') }} template(v-if='API.currentUser.id === userDialog.id') .x-friend-item(@click='toggleAvatarCopying') .detail span.name {{ $t('dialog.user.info.avatar_cloning') }} span.extra(v-if='API.currentUser.allowAvatarCopying' style='color: #67c23a') {{ $t('dialog.user.info.avatar_cloning_allow') }} span.extra(v-else style='color: #f56c6c') {{ $t('dialog.user.info.avatar_cloning_deny') }} //- .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(v-else) .x-friend-item(style='cursor: default') .detail span.name {{ $t('dialog.user.info.avatar_cloning') }} span.extra(v-if='userDialog.ref.allowAvatarCopying' style='color: #67c23a') {{ $t('dialog.user.info.avatar_cloning_allow') }} span.extra(v-else style='color: #f56c6c') {{ $t('dialog.user.info.avatar_cloning_deny') }} .x-friend-item( v-if='userDialog.ref.id === API.currentUser.id && API.currentUser.homeLocation' @click='showWorldDialog(API.currentUser.homeLocation)' style='width: 100%') .detail span.name {{ $t('dialog.user.info.home_location') }} span.extra span(v-text='userDialog.$homeLocationName') el-button( @click.stop='resetHome()' size='mini' icon='el-icon-delete' circle style='margin-left: 5px') .x-friend-item(style='width: 100%; cursor: default') .detail span.name {{ $t('dialog.user.info.id') }} span.extra {{ userDialog.id }} el-tooltip( placement='top' :content='$t("dialog.user.info.id_tooltip")' :disabled='hideTooltips') el-dropdown( trigger='click' @click.native.stop size='mini' style='margin-left: 5px') el-button(type='default' icon='el-icon-s-order' size='mini' circle) el-dropdown-menu(#default='dropdown') el-dropdown-item(@click.native='copyUserId(userDialog.id)') {{ $t('dialog.user.info.copy_id') }} el-dropdown-item(@click.native='copyUserURL(userDialog.id)') {{ $t('dialog.user.info.copy_url') }} el-dropdown-item( @click.native='copyUserDisplayName(userDialog.ref.displayName)') {{ $t('dialog.user.info.copy_display_name') }} 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' @click='getUserGroups(userDialog.id)' size='mini' icon='el-icon-refresh' circle) span(style='margin-left: 5px') {{ $t('dialog.user.groups.total_count', { count: userGroups.groups.length }) }} template(v-if='userDialogGroupEditMode') span(style='margin-left: 10px; color: #909399; font-size: 10px') {{ $t('dialog.user.groups.hold_shift') }} div(style='display: flex; align-items: center') template(v-if='!userDialogGroupEditMode') span(style='margin-right: 5px') {{ $t('dialog.user.groups.sort_by') }} el-dropdown( @click.native.stop trigger='click' size='small' style='margin-right: 5px' :disabled='userDialog.isGroupsLoading') el-button(size='mini') span {{ userDialog.groupSorting.name }} #[i.el-icon-arrow-down.el-icon--right] el-dropdown-menu(#default='dropdown') el-dropdown-item( :disabled='item === userDialogGroupSortingOptions.inGame && userDialog.id !== API.currentUser.id' v-for='(item, key) in userDialogGroupSortingOptions' :key='key' v-text='item.name' @click.native='setUserDialogGroupSorting(item)') el-button( v-if='userDialogGroupEditMode' size='small' @click='exitEditModeCurrentUserGroups' icon='el-icon-edit' style='margin-right: 5px; height: 29px; padding: 7px 15px') {{ $t('dialog.user.groups.exit_edit_mode') }} el-button( v-else-if='API.currentUser.id === userDialog.id' size='small' @click='editModeCurrentUserGroups' icon='el-icon-edit' style='margin-right: 5px; height: 29px; padding: 7px 15px') {{ $t('dialog.user.groups.edit_mode') }} div(v-loading='userDialog.isGroupsLoading' style='margin-top: 10px') template(v-if='userDialogGroupEditMode') .x-friend-list(style='margin-top: 10px; margin-bottom: 15px; max-height: unset') .x-friend-item.x-friend-item-border( v-for='group in userDialogGroupEditGroups' :key='group.id' @click='showGroupDialog(group.id)' style='width: 100%') div(@click.stop style='margin-right: 3px; margin-left: 5px') el-button( @click='moveGroupUp(group.id)' size='mini' icon='el-icon-download' style='display: block; padding: 7px; font-size: 9px; margin-left: 0; rotate: 180deg') el-button( @click='moveGroupDown(group.id)' size='mini' icon='el-icon-download' style='display: block; padding: 7px; font-size: 9px; margin-left: 0') div(@click.stop style='margin-right: 10px') el-button( @click='moveGroupTop(group.id)' size='mini' icon='el-icon-top' style='display: block; padding: 7px; font-size: 9px; margin-left: 0') el-button( @click='moveGroupBottom(group.id)' size='mini' icon='el-icon-bottom' style='display: block; padding: 7px; font-size: 9px; margin-left: 0') .avatar img(v-lazy='group.iconUrl') .detail span.name(v-text='group.name') span.extra el-tooltip( v-if='group.isRepresenting' placement='top' :content='$t("dialog.group.members.representing")') i.el-icon-collection-tag(style='margin-right: 5px') el-tooltip(v-if='group.myMember.visibility !== "visible"' placement='top') template(#content) span {{ $t('dialog.group.members.visibility') }} {{ group.myMember.visibility }} i.el-icon-view(style='margin-right: 5px') span ({{ group.memberCount }}) el-dropdown( @click.native.stop :disabled='group.privacy !== "default"' trigger='click' size='small' style='margin-right: 5px') el-button(size='mini') span(v-if='group.myMember.visibility === "visible"') {{ $t('dialog.group.tags.visible') }} span(v-else-if='group.myMember.visibility === "friends"') {{ $t('dialog.group.tags.friends') }} span(v-else-if='group.myMember.visibility === "hidden"') {{ $t('dialog.group.tags.hidden') }} span(v-else) {{ group.myMember.visibility }} i.el-icon-arrow-down.el-icon--right(style='margin-left: 5px') el-dropdown-menu el-dropdown-item(@click.native='setGroupVisibility(group.id, "visible")') #[i.el-icon-check(v-if='group.myMember.visibility === "visible"')] {{ $t('dialog.group.actions.visibility_everyone') }} el-dropdown-item(@click.native='setGroupVisibility(group.id, "friends")') #[i.el-icon-check(v-if='group.myMember.visibility === "friends"')] {{ $t('dialog.group.actions.visibility_friends') }} el-dropdown-item(@click.native='setGroupVisibility(group.id, "hidden")') #[i.el-icon-check(v-if='group.myMember.visibility === "hidden"')] {{ $t('dialog.group.actions.visibility_hidden') }} //- 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' @click.stop='leaveGroupPrompt(group.id)' size='mini' icon='el-icon-close' circle style='color: #f56c6c; margin-left: 5px') el-button( v-else @click.stop='leaveGroupPrompt(group.id)' size='mini' icon='el-icon-delete' circle style='margin-left: 5px') 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(style='color: #909399; font-size: 12px; margin-left: 5px') {{ userGroups.ownGroups.length }}/{{ API.cachedConfig?.constants?.GROUPS?.MAX_OWNED }} .x-friend-list(style='margin-top: 10px; margin-bottom: 15px; min-height: 60px') .x-friend-item.x-friend-item-border( v-for='group in userGroups.ownGroups' :key='group.id' @click='showGroupDialog(group.id)') .avatar img(v-lazy='group.iconUrl') .detail span.name(v-text='group.name') span.extra el-tooltip( v-if='group.isRepresenting' placement='top' :content='$t("dialog.group.members.representing")') i.el-icon-collection-tag(style='margin-right: 5px') el-tooltip(v-if='group.memberVisibility !== "visible"' placement='top') template(#content) span {{ $t('dialog.group.members.visibility') }} {{ group.memberVisibility }} i.el-icon-view(style='margin-right: 5px') span ({{ group.memberCount }}) template(v-if='userGroups.mutualGroups.length > 0') span(style='font-weight: bold; font-size: 16px') {{ $t('dialog.user.groups.mutual_groups') }} span(style='color: #909399; font-size: 12px; margin-left: 5px') {{ userGroups.mutualGroups.length }} .x-friend-list(style='margin-top: 10px; margin-bottom: 15px; min-height: 60px') .x-friend-item.x-friend-item-border( v-for='group in userGroups.mutualGroups' :key='group.id' @click='showGroupDialog(group.id)') .avatar img(v-lazy='group.iconUrl') .detail span.name(v-text='group.name') span.extra el-tooltip( v-if='group.isRepresenting' placement='top' :content='$t("dialog.group.members.representing")') i.el-icon-collection-tag(style='margin-right: 5px') el-tooltip(v-if='group.memberVisibility !== "visible"' placement='top') template(#content) span {{ $t('dialog.group.members.visibility') }} {{ group.memberVisibility }} i.el-icon-view(style='margin-right: 5px') span ({{ group.memberCount }}) template(v-if='userGroups.remainingGroups.length > 0') span(style='font-weight: bold; font-size: 16px') {{ $t('dialog.user.groups.groups') }} 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(v-else) | {{ API.cachedConfig?.constants?.GROUPS?.MAX_JOINED }} .x-friend-list(style='margin-top: 10px; margin-bottom: 15px; min-height: 60px') .x-friend-item.x-friend-item-border( v-for='group in userGroups.remainingGroups' :key='group.id' @click='showGroupDialog(group.id)') .avatar img(v-lazy='group.iconUrl') .detail span.name(v-text='group.name') span.extra el-tooltip( v-if='group.isRepresenting' placement='top' :content='$t("dialog.group.members.representing")') i.el-icon-collection-tag(style='margin-right: 5px') el-tooltip(v-if='group.memberVisibility !== "visible"' placement='top') template(#content) span {{ $t('dialog.group.members.visibility') }} {{ group.memberVisibility }} i.el-icon-view(style='margin-right: 5px') span ({{ group.memberCount }}) 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' @click='refreshUserDialogWorlds()' size='mini' icon='el-icon-refresh' circle) span(style='margin-left: 5px') {{ $t('dialog.user.worlds.total_count', { count: userDialog.worlds.length }) }} div(style='display: flex; align-items: center') span(style='margin-right: 5px') {{ $t('dialog.user.worlds.sort_by') }} el-dropdown( @click.native.stop trigger='click' size='small' style='margin-right: 5px' :disabled='userDialog.isWorldsLoading') el-button(size='mini') span {{ userDialog.worldSorting.name }} #[i.el-icon-arrow-down.el-icon--right] el-dropdown-menu(#default='dropdown') el-dropdown-item( v-for='(item, key) in userDialogWorldSortingOptions' :key='key' v-text='item.name' @click.native='setUserDialogWorldSorting(item)') span(style='margin: 0 5px') {{ $t('dialog.user.worlds.order_by') }} el-dropdown( @click.native.stop trigger='click' size='small' style='margin-right: 5px' :disabled='userDialog.isWorldsLoading') el-button(size='mini') span {{ userDialog.worldOrder.name }} #[i.el-icon-arrow-down.el-icon--right] el-dropdown-menu(#default='dropdown') el-dropdown-item( v-for='(item, key) in userDialogWorldOrderOptions' :key='key' v-text='item.name' @click.native='setUserDialogWorldOrder(item)') .x-friend-list(v-loading='userDialog.isWorldsLoading' style='margin-top: 10px; min-height: 60px') .x-friend-item.x-friend-item-border( v-for='world in userDialog.worlds' :key='world.id' @click='showWorldDialog(world.id)') .avatar img(v-lazy='world.thumbnailImageUrl') .detail span.name(v-text='world.name') span.extra(v-if='world.occupants') ({{ world.occupants }}) el-tab-pane(:label='$t("dialog.user.favorite_worlds.header")' lazy) el-button( v-if='userFavoriteWorlds && userFavoriteWorlds.length > 0' type='default' :loading='userDialog.isFavoriteWorldsLoading' @click='getUserFavoriteWorlds(userDialog.id)' size='small' icon='el-icon-refresh' circle style='position: absolute; right: 15px; bottom: 15px; z-index: 99') el-tabs.zero-margin-tabs( type='card' stretch ref='favoriteWorlds' v-loading='userDialog.isFavoriteWorldsLoading' 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.x-status-icon( style='margin-right: 6px' :class='userFavoriteWorldsStatus(list[1])') span(v-text='list[0]' style='font-weight: bold; font-size: 14px') span(style='color: #909399; font-size: 10px; margin-left: 5px') {{ list[2].length }}/{{ API.favoriteLimits.maxFavoritesPerGroup.world }} .x-friend-list( style='margin-top: 10px; margin-bottom: 15px; min-height: 60px; max-height: none') .x-friend-item.x-friend-item-border( v-for='world in list[2]' :key='world.favoriteId' @click='showWorldDialog(world.id)') .avatar img(v-lazy='world.thumbnailImageUrl') .detail span.name(v-text='world.name') span.extra(v-if='world.occupants') ({{ world.occupants }}) 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. 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' @click='refreshUserDialogAvatars()' size='mini' icon='el-icon-refresh' circle) el-button( v-else type='default' :loading='userDialog.isAvatarsLoading' @click='setUserDialogAvatarsRemote(userDialog.id)' size='mini' icon='el-icon-refresh' circle) span(style='margin-left: 5px') {{ $t('dialog.user.avatars.total_count', { count: userDialogAvatars.length }) }} div template(v-if='userDialog.ref.id === API.currentUser.id') span(style='margin-right: 5px') {{ $t('dialog.user.avatars.sort_by') }} el-dropdown( @click.native.stop trigger='click' size='small' style='margin-right: 5px' :disabled='userDialog.isWorldsLoading') el-button(size='mini') span {{ $t(`dialog.user.avatars.sort_by_${userDialog.avatarSorting}`) }} #[i.el-icon-arrow-down.el-icon--right] el-dropdown-menu(#default='dropdown') el-dropdown-item( v-text='$t("dialog.user.avatars.sort_by_name")' @click.native='changeUserDialogAvatarSorting("name")') el-dropdown-item( v-text='$t("dialog.user.avatars.sort_by_update")' @click.native='changeUserDialogAvatarSorting("update")') span(style='margin-right: 5px; margin-left: 10px') {{ $t('dialog.user.avatars.group_by') }} el-dropdown( @click.native.stop trigger='click' size='small' style='margin-right: 5px' :disabled='userDialog.isWorldsLoading') el-button(size='mini') span {{ $t(`dialog.user.avatars.${userDialog.avatarReleaseStatus}`) }} #[i.el-icon-arrow-down.el-icon--right] el-dropdown-menu(#default='dropdown') el-dropdown-item( v-text='$t("dialog.user.avatars.all")' @click.native='userDialog.avatarReleaseStatus = "all"') el-dropdown-item( v-text='$t("dialog.user.avatars.public")' @click.native='userDialog.avatarReleaseStatus = "public"') el-dropdown-item( v-text='$t("dialog.user.avatars.private")' @click.native='userDialog.avatarReleaseStatus = "private"') .x-friend-list(style='margin-top: 10px; min-height: 60px; max-height: 50vh') .x-friend-item.x-friend-item-border( v-for='avatar in userDialogAvatars' :key='avatar.id' @click='showAvatarDialog(avatar.id)') .avatar img(v-if='avatar.thumbnailImageUrl' v-lazy='avatar.thumbnailImageUrl') .detail span.name(v-text='avatar.name') span.extra( v-text='avatar.releaseStatus' v-if='avatar.releaseStatus === "public"' style='color: #67c23a') span.extra( v-text='avatar.releaseStatus' v-else-if='avatar.releaseStatus === "private"' style='color: #f56c6c') span.extra(v-text='avatar.releaseStatus' v-else) el-tab-pane(:label='$t("dialog.user.json.header")' lazy style='height: 50vh') el-button( type='default' @click='refreshUserDialogTreeData()' size='mini' icon='el-icon-refresh' circle) el-button( type='default' @click='downloadAndSaveJson(userDialog.id, userDialog.ref)' size='mini' icon='el-icon-download' circle style='margin-left: 5px') el-tree(:data='userDialog.treeData' style='margin-top: 5px; font-size: 12px') template(#default='scope') span span(v-text='scope.data.key' style='font-weight: bold; margin-right: 5px') span(v-if='!scope.data.children' v-text='scope.data.value')