mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-12 11:23:52 +02:00
4081 lines
367 KiB
Plaintext
4081 lines
367 KiB
Plaintext
doctype html
|
||
html
|
||
head
|
||
meta(http-equiv="Content-Type" content="text/html;charset=utf-8")
|
||
meta(http-equiv="Cache-Control" content="no-cache")
|
||
meta(http-equiv="referrer" content="no-referrer")
|
||
meta(http-equiv="viewport" content="width=device-width,initial-scale=1,user-scalable=no")
|
||
title VRCX
|
||
link(rel="preconnect" href="https://api.vrchat.cloud")
|
||
link(rel="preconnect" href="https://d348imysud55la.cloudfront.net")
|
||
link(rel="stylesheet" href="app.css")
|
||
link(rel="stylesheet" href="flags.css")
|
||
body
|
||
.x-app#x-app(style="display:none")
|
||
//- login
|
||
.x-login-container(v-show="!API.isLoggedIn" v-loading="loginForm.loading")
|
||
div(style="position:absolute;margin:5px")
|
||
el-button(type="default" @click="showVRCXUpdateDialog" size="mini" icon="el-icon-download" circle)
|
||
div(style="width:300px;margin:auto")
|
||
div(style="margin:15px" v-if="Object.keys(loginForm.savedCredentials).length !== 0")
|
||
h2(style="font-weight:bold;text-align:center;margin:0") Saved Accounts
|
||
.x-friend-list(style="margin-top:10px")
|
||
.x-friend-item(v-for="user in loginForm.savedCredentials" :key="user.user.id")
|
||
.x-friend-item(@click="relogin(user)" style="width:202px;padding:0")
|
||
.avatar
|
||
img(v-lazy="userImage(user.user)")
|
||
.detail
|
||
span.name(v-text="user.user.displayName")
|
||
span.extra(v-text="user.user.username")
|
||
span.extra(v-text="user.loginParmas.endpoint")
|
||
el-button(type="default" @click="deleteSavedLogin(user.user.username)" size="mini" icon="el-icon-delete" circle)
|
||
div(style="margin:15px")
|
||
h2(style="font-weight:bold;text-align:center;margin:0") Login
|
||
el-form(ref="loginForm" :model="loginForm" :rules="loginForm.rules" @submit.native.prevent="login()")
|
||
el-form-item(label="Username or Email" prop="username" required)
|
||
el-input(v-model="loginForm.username" name="username" placeholder="Username or Email" clearable)
|
||
el-form-item(label="Password" prop="password" required style="margin-top:10px")
|
||
el-input(type="password" v-model="loginForm.password" name="password" placeholder="Password" clearable show-password)
|
||
el-checkbox(v-model="loginForm.saveCredentials" style="margin-top:15px") Save Credentials
|
||
el-checkbox(v-model="enableCustomEndpoint" @change="toggleCustomEndpoint" style="margin-top:10px") Dev Endpoint
|
||
el-form-item(v-if="enableCustomEndpoint" label="Endpont" prop="endpoint" style="margin-top:10px")
|
||
el-input(v-model="loginForm.endpoint" name="endpoint" :placeholder="API.endpointDomainVrchat" clearable)
|
||
el-form-item(v-if="enableCustomEndpoint" label="WebSocket" prop="endpoint" style="margin-top:10px")
|
||
el-input(v-model="loginForm.websocket" name="websocket" :placeholder="API.websocketDomainVrchat" clearable)
|
||
el-form-item(style="margin-top:15px")
|
||
el-button(native-type="submit" type="primary" :loading="loginForm.loading" style="width:100%") Login
|
||
el-button(type="primary" @click="openExternalLink('https://vrchat.com/register')" :loading="loginForm.loading" style="width:100%") Register
|
||
div(style="text-align:center;font-size:12px")
|
||
p #[a(@click="openExternalLink('https://vrchat.com/home/password')") Forgot password?]
|
||
p © 2019-2022 #[a(@click="openExternalLink('https://github.com/pypy-vrc')") pypy] (mina#5656) & #[a(@click="openExternalLink('https://github.com/Natsumi-sama')") Natsumi]
|
||
p VRCX is an assistant application for provide information about manage friendship. this application uses unofficial VRChat API (VRCSDK).
|
||
p VRCX isn't endorsed by VRChat and doesn't reflect the views or opinions of VRChat or anyone officially involved in producing or managing VRChat. VRChat is trademark of VRChat Inc. VRChat © VRChat Inc.
|
||
p pypy or Natsumi aren't responsible for any problems caused by VRCX. Use at your own risk!
|
||
|
||
//- menu
|
||
.x-menu-container
|
||
//- download progress
|
||
div(v-if="downloadInProgress" @click="showDownloadDialog" style="margin:7px;height:50px;cursor:pointer")
|
||
el-progress(type="circle" width="50" stroke-width="3" :percentage="downloadProgress" :format="downloadProgressText")
|
||
|
||
el-menu(ref="menu" collapse @select="selectMenu")
|
||
mixin menuitem(index, name, icon)
|
||
el-menu-item(index=index)
|
||
i(class=icon)
|
||
template(#title)
|
||
span= name
|
||
+menuitem('feed', 'Feed', 'el-icon-news')
|
||
+menuitem('gameLog', 'Game Log', 'el-icon-s-data')
|
||
+menuitem('playerList', 'Player List', 'el-icon-tickets')
|
||
+menuitem('search', 'Search', 'el-icon-search')
|
||
+menuitem('favorite', 'Favorites', 'el-icon-star-off')
|
||
+menuitem('friendLog', 'Friend Log', 'el-icon-notebook-2')
|
||
+menuitem('moderation', 'Moderation', 'el-icon-finished')
|
||
+menuitem('notification', 'Notification', 'el-icon-bell')
|
||
+menuitem('friendsList', 'Friends List', 'el-icon-s-management')
|
||
+menuitem('profile', 'Profile', 'el-icon-user')
|
||
+menuitem('settings', 'Settings', 'el-icon-s-tools')
|
||
|
||
//- playerList
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'playerList'")
|
||
div(style="display:flex;flex-direction:column;height:100%")
|
||
div(v-if="currentInstanceWorld.ref.id" style="display:flex")
|
||
el-popover(placement="right" width="500px" trigger="click" style="height:120px")
|
||
img.x-link(slot="reference" v-lazy="currentInstanceWorld.ref.thumbnailImageUrl" style="flex:none;width:160px;height:120px;border-radius:4px")
|
||
img.x-link(v-lazy="currentInstanceWorld.ref.imageUrl" style="width:500px;height:375px" @click="downloadAndSaveImage(currentInstanceWorld.ref.imageUrl)")
|
||
div(style="margin-left:10px;display:flex;flex-direction:column;min-width:320px;width:100%")
|
||
div
|
||
span.x-link(@click="showWorldDialog(currentInstanceWorld.ref.id)" style="font-weight:bold;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1")
|
||
| #[i.el-icon-s-home(v-show="API.currentUser.$homeLocation && API.currentUser.$homeLocation.worldId === currentInstanceWorld.ref.id" style="margin-right:5px")] {{ currentInstanceWorld.ref.name }}
|
||
div
|
||
span.x-link(v-text="currentInstanceWorld.ref.authorName" @click="showUserDialog(currentInstanceWorld.ref.authorId)" style="color:#909399;font-family:monospace")
|
||
div(style="margin-top:5px")
|
||
el-tag(v-if="currentInstanceWorld.ref.$isLabs" type="primary" effect="plain" size="mini" style="margin-right:5px") Labs
|
||
el-tag(v-else-if="currentInstanceWorld.ref.releaseStatus === 'public'" type="success" effect="plain" size="mini" style="margin-right:5px") Public
|
||
el-tag(v-else-if="currentInstanceWorld.ref.releaseStatus === 'private'" type="danger" effect="plain" size="mini" style="margin-right:5px") Private
|
||
el-tag.x-tag-platform-pc(v-if="currentInstanceWorld.isPC" type="info" effect="plain" size="mini" style="margin-right:5px") PC
|
||
el-tag.x-tag-platform-quest(v-if="currentInstanceWorld.isQuest" type="info" effect="plain" size="mini" style="margin-right:5px") Quest
|
||
el-tag(type="info" effect="plain" size="mini" v-text="currentInstanceWorld.fileSize" style="margin-right:5px")
|
||
el-tag(v-if="currentInstanceWorld.inCache" type="info" effect="plain" size="mini" style="margin-right:5px")
|
||
span(v-text="currentInstanceWorld.cacheSize")
|
||
| Cache
|
||
br
|
||
location-world(:locationobject="currentInstanceLocation" :currentuserid="API.currentUser.id")
|
||
span(v-if="lastLocation.playerList.size > 0" style="margin-left:5px")
|
||
| {{ lastLocation.playerList.size }}
|
||
| #[template(v-if="lastLocation.friendList.size > 0") ({{ lastLocation.friendList.size }})]
|
||
| #[timer(v-if="lastLocation.date" :epoch="lastLocation.date")]
|
||
div(style="margin-top:5px")
|
||
span(v-show="currentInstanceWorld.ref.name !== currentInstanceWorld.ref.description" v-text="currentInstanceWorld.ref.description" style="font-size:12px;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2")
|
||
div(style="display:flex;flex-direction:column;margin-left:20px")
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Capacity
|
||
span.extra {{ currentInstanceWorld.ref.capacity | commaNumber }} ({{ currentInstanceWorld.ref.capacity * 2 | commaNumber }})
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Last Updated
|
||
span.extra {{ currentInstanceWorld.fileCreatedAt | formatDate('long') }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Created
|
||
span.extra {{ currentInstanceWorld.ref.created_at | formatDate('long') }}
|
||
div.photon-event-table(v-if="photonLoggingEnabled")
|
||
div(style="position:absolute;width:600px;margin-left:195px;z-index:1")
|
||
el-select(v-model="photonEventTableTypeFilter" @change="photonEventTableFilterChange" multiple clearable collapse-tags style="flex:1;width:220px" placeholder="Filter")
|
||
el-option(v-once v-for="type in photonEventTableTypeFilterList" :key="type" :label="type" :value="type")
|
||
el-input(v-model="photonEventTableFilter" @input="photonEventTableFilterChange" placeholder="Search" clearable style="width:150px;margin-left:10px")
|
||
el-button(@click="showChatboxBlacklistDialog" style="margin-left:10px") Chatbox Blacklist
|
||
el-tooltip(placement="bottom" content="VRCX Companion Status" :disabled="hideTooltips")
|
||
div(style="display:inline-block;margin-left:15px;font-size:14px;vertical-align:text-top;margin-top:1px")
|
||
span(v-if="ipcEnabled && !photonEventIcon") 🟢
|
||
span(v-else-if="ipcEnabled") ⚪
|
||
span(v-else) 🔴
|
||
el-tabs(type="card")
|
||
el-tab-pane(label="Current")
|
||
data-tables(v-bind="photonEventTable" style="margin-bottom:10px")
|
||
el-table-column(label="Date" prop="created_at" width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="right")
|
||
template(#content)
|
||
span {{ scope.row.created_at | formatDate('long') }}
|
||
span {{ scope.row.created_at | formatDate('short') }}
|
||
el-table-column(label="User" prop="photonId" width="160")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.displayName" @click="showUserFromPhotonId(scope.row.photonId)" style="padding-right:10px")
|
||
el-table-column(label="Type" prop="type" width="140")
|
||
el-table-column(label="Details" prop="text")
|
||
template(v-once #default="scope")
|
||
template(v-if="scope.row.type === 'ChangeAvatar'")
|
||
span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)")
|
||
|
|
||
span(v-if="!scope.row.inCache" style="color:#aaa") #[i.el-icon-download]
|
||
span.avatar-info-public(v-if="scope.row.avatar.releaseStatus === 'public'") (Public)
|
||
span.avatar-info-own(v-else-if="scope.row.avatar.releaseStatus === 'private'") (Private)
|
||
template(v-if="scope.row.avatar.description && scope.row.avatar.name !== scope.row.avatar.description")
|
||
| - {{ scope.row.avatar.description }}
|
||
template(v-else-if="scope.row.type === 'ChangeStatus'")
|
||
template(v-if="scope.row.status !== scope.row.previousStatus")
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span(v-if="scope.row.previousStatus === 'active'") Active
|
||
span(v-else-if="scope.row.previousStatus === 'join me'") Join Me
|
||
span(v-else-if="scope.row.previousStatus === 'ask me'") Ask Me
|
||
span(v-else-if="scope.row.previousStatus === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="statusClass(scope.row.previousStatus)")
|
||
span
|
||
i.el-icon-right
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span(v-if="scope.row.status === 'active'") Active
|
||
span(v-else-if="scope.row.status === 'join me'") Join Me
|
||
span(v-else-if="scope.row.status === 'ask me'") Ask Me
|
||
span(v-else-if="scope.row.status === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="statusClass(scope.row.status)" style="margin-right:5px")
|
||
span(v-if="scope.row.statusDescription !== scope.row.previousStatusDescription" v-text="scope.row.statusDescription")
|
||
span.x-link(v-else-if="scope.row.type === 'PortalSpawn'" @click="showWorldDialog(scope.row.location, scope.row.shortName)")
|
||
location(:location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName" :link="false")
|
||
span(v-else-if="scope.row.type === 'ChatBoxMessage'" v-text="scope.row.text")
|
||
span(v-else-if="scope.row.type === 'OnPlayerJoined'")
|
||
span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)")
|
||
|
|
||
span(v-if="!scope.row.inCache" style="color:#aaa") #[i.el-icon-download]
|
||
span.avatar-info-public(v-if="scope.row.avatar.releaseStatus === 'public'") (Public)
|
||
span.avatar-info-own(v-else-if="scope.row.avatar.releaseStatus === 'private'") (Private)
|
||
span(v-else-if="scope.row.color === 'yellow'" v-text="scope.row.text" style="color:yellow")
|
||
span(v-else v-text="scope.row.text")
|
||
el-tab-pane(label="Previous")
|
||
data-tables(v-bind="photonEventTablePrevious" style="margin-bottom:10px")
|
||
el-table-column(label="Date" prop="created_at" width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="right")
|
||
template(#content)
|
||
span {{ scope.row.created_at | formatDate('long') }}
|
||
span {{ scope.row.created_at | formatDate('short') }}
|
||
el-table-column(label="User" prop="photonId" width="160")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.displayName" @click="lookupUser(scope.row)" style="padding-right:10px")
|
||
el-table-column(label="Type" prop="type" width="140")
|
||
el-table-column(label="Details" prop="text")
|
||
template(v-once #default="scope")
|
||
template(v-if="scope.row.type === 'ChangeAvatar'")
|
||
span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)")
|
||
|
|
||
span(v-if="!scope.row.inCache" style="color:#aaa") #[i.el-icon-download]
|
||
span.avatar-info-public(v-if="scope.row.avatar.releaseStatus === 'public'") (Public)
|
||
span.avatar-info-own(v-else-if="scope.row.avatar.releaseStatus === 'private'") (Private)
|
||
template(v-if="scope.row.avatar.description && scope.row.avatar.name !== scope.row.avatar.description")
|
||
| - {{ scope.row.avatar.description }}
|
||
template(v-else-if="scope.row.type === 'ChangeStatus'")
|
||
template(v-if="scope.row.status !== scope.row.previousStatus")
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span(v-if="scope.row.previousStatus === 'active'") Active
|
||
span(v-else-if="scope.row.previousStatus === 'join me'") Join Me
|
||
span(v-else-if="scope.row.previousStatus === 'ask me'") Ask Me
|
||
span(v-else-if="scope.row.previousStatus === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="statusClass(scope.row.previousStatus)")
|
||
span
|
||
i.el-icon-right
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span(v-if="scope.row.status === 'active'") Active
|
||
span(v-else-if="scope.row.status === 'join me'") Join Me
|
||
span(v-else-if="scope.row.status === 'ask me'") Ask Me
|
||
span(v-else-if="scope.row.status === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="statusClass(scope.row.status)")
|
||
span(v-if="scope.row.statusDescription !== scope.row.previousStatusDescription" v-text="scope.row.statusDescription" style="margin-left:5px")
|
||
span.x-link(v-else-if="scope.row.type === 'PortalSpawn'" @click="showWorldDialog(scope.row.location, scope.row.shortName)")
|
||
location(:location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName" :link="false")
|
||
span(v-else-if="scope.row.type === 'ChatBoxMessage'" v-text="scope.row.text")
|
||
span(v-else-if="scope.row.type === 'OnPlayerJoined'")
|
||
span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)")
|
||
|
|
||
span(v-if="!scope.row.inCache" style="color:#aaa") #[i.el-icon-download]
|
||
span.avatar-info-public(v-if="scope.row.avatar.releaseStatus === 'public'") (Public)
|
||
span.avatar-info-own(v-else-if="scope.row.avatar.releaseStatus === 'private'") (Private)
|
||
span(v-else-if="scope.row.color === 'yellow'" v-text="scope.row.text" style="color:yellow")
|
||
span(v-else v-text="scope.row.text")
|
||
div.current-instance-table
|
||
data-tables(v-bind="currentInstanceUserList" @row-click="selectCurrentInstanceRow" style="margin-top:10px;cursor:pointer")
|
||
el-table-column(label="Avatar" width="70" prop="photo")
|
||
template(v-once #default="scope")
|
||
template(v-if="userImage(scope.row.ref)")
|
||
el-popover(placement="right" height="500px" trigger="hover")
|
||
img.friends-list-avatar(slot="reference" v-lazy="userImage(scope.row.ref)")
|
||
img.friends-list-avatar(v-lazy="userImageFull(scope.row.ref)" style="height:500px;cursor:pointer" @click="downloadAndSaveImage(userImageFull(scope.row.ref))")
|
||
el-table-column(label="Timer" width="90" prop="timer" sortable)
|
||
template(v-once #default="scope")
|
||
timer(:epoch="scope.row.timer")
|
||
el-table-column(v-if="photonLoggingEnabled" label="Photon Id" width="110" prop="photonId" sortable)
|
||
template(v-once #default="scope")
|
||
template(v-if="chatboxUserBlacklist.has(scope.row.ref.id)")
|
||
el-tooltip(placement="left" content="Unblock chatbox messages")
|
||
el-button(type="text" icon="el-icon-turn-off-microphone" size="mini" style="color:red;margin-right:5px" @click.stop="deleteChatboxUserBlacklist(scope.row.ref.id)")
|
||
template(v-else)
|
||
el-tooltip(placement="left" content="Block chatbox messages")
|
||
el-button(type="text" icon="el-icon-microphone" size="mini" style="margin-right:5px" @click.stop="addChatboxUserBlacklist(scope.row.ref)")
|
||
span(v-text="scope.row.photonId")
|
||
el-table-column(label="Icons" prop="isMaster" width="100")
|
||
template(v-once #default="scope")
|
||
el-tooltip(v-if="scope.row.isMaster" placement="left" content="Instance Master")
|
||
span 👑
|
||
el-tooltip(v-if="scope.row.isFriend" placement="left" content="Friend")
|
||
span 💚
|
||
el-tooltip(v-if="scope.row.timeoutTime" placement="left" content="Timeout")
|
||
span(style="color:red") 🔴{{ scope.row.timeoutTime }}s
|
||
el-table-column(label="Platform" prop="inVRMode" width="80")
|
||
template(v-once #default="scope")
|
||
template(v-if="scope.row.ref.last_platform")
|
||
span(v-if="scope.row.ref.last_platform === 'standalonewindows'" style="color:#409eff") PC
|
||
span(v-else-if="scope.row.ref.last_platform === 'android'" style="color:#67c23a") Q
|
||
span(v-else) {{ scope.row.ref.last_platform }}
|
||
template(v-if="scope.row.inVRMode !== null")
|
||
span(v-if="scope.row.inVRMode") VR
|
||
span(v-else) D
|
||
el-table-column(label="Display Name" min-width="140" prop="ref.displayName")
|
||
template(v-once #default="scope")
|
||
span(v-if="randomUserColours" v-text="scope.row.ref.displayName" :style="{'color':scope.row.ref.$userColour}")
|
||
span(v-else v-text="scope.row.ref.displayName")
|
||
el-table-column(label="Status" min-width="180" prop="ref.status")
|
||
template(v-once #default="scope")
|
||
template(v-if="scope.row.ref.status")
|
||
i.x-user-status(:class="statusClass(scope.row.ref.status)")
|
||
span
|
||
span(v-text="scope.row.ref.statusDescription")
|
||
//- el-table-column(label="Group" min-width="180" prop="groupOnNameplate" sortable)
|
||
//- template(v-once #default="scope")
|
||
//- span(v-text="scope.row.groupOnNameplate")
|
||
el-table-column(label="Rank" width="110" prop="$trustSortNum" sortable="custom")
|
||
template(v-once #default="scope")
|
||
span.name(v-text="scope.row.ref.$trustLevel" :class="scope.row.ref.$trustClass")
|
||
el-table-column(label="Language" width="100" prop="ref.$languages")
|
||
template(v-once #default="scope")
|
||
el-tooltip(v-for="item in scope.row.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-left:5px")
|
||
el-table-column(label="Bio Links" width="100" prop="ref.bioLinks")
|
||
template(v-once #default="scope")
|
||
el-tooltip(v-if="link" v-for="(link, index) in scope.row.ref.bioLinks" :key="index")
|
||
template(#content)
|
||
span(v-text="link")
|
||
img(:src="getFaviconUrl(link)" style="width:16px;height:16px;vertical-align:middle;margin-right:5px;cursor:pointer" @click.stop="openExternalLink(link)")
|
||
|
||
//- feed
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'feed'")
|
||
data-tables(v-bind="feedTable" v-loading="feedTable.loading")
|
||
template(#tool)
|
||
div(style="margin:0 0 10px;display:flex;align-items:center")
|
||
div(style="flex:none;margin-right:10px")
|
||
el-tooltip(placement="bottom" content="Filter VIP only" :disabled="hideTooltips")
|
||
el-switch(v-model="feedTable.vip" @change="feedTableLookup" active-color="#13ce66")
|
||
el-select(v-model="feedTable.filter" @change="feedTableLookup" multiple clearable collapse-tags style="flex:1" placeholder="Filter")
|
||
el-option(v-once v-for="type in ['GPS', 'Online', 'Offline', 'Status', 'Avatar', 'Bio']" :key="type" :label="type" :value="type")
|
||
el-input(v-model="feedTable.search" placeholder="Search" @keyup.native.13="feedTableLookup" @change="feedTableLookup" clearable style="flex:none;width:150px;margin:0 10px")
|
||
//- el-tooltip(placement="bottom" content="Clear feed" :disabled="hideTooltips")
|
||
//- el-button(type="default" @click="clearFeed()" icon="el-icon-delete" circle style="flex:none")
|
||
el-table-column(type="expand" width="20")
|
||
template(v-once #default="scope")
|
||
div(style="position:relative;font-size:14px")
|
||
template(v-if="scope.row.type === 'GPS'")
|
||
location(v-if="scope.row.previousLocation" :location="scope.row.previousLocation")
|
||
el-tag(type="info" effect="plain" size="mini" style="margin-left:5px") {{ scope.row.time | timeToText }}
|
||
br
|
||
span
|
||
i.el-icon-right
|
||
location(v-if="scope.row.location" :location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName")
|
||
template(v-else-if="scope.row.type === 'Offline'")
|
||
template(v-if="scope.row.location")
|
||
location(:location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName")
|
||
el-tag(type="info" effect="plain" size="mini" style="margin-left:5px") {{ scope.row.time | timeToText }}
|
||
template(v-else-if="scope.row.type === 'Online'")
|
||
location(v-if="scope.row.location" :location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName")
|
||
template(v-else-if="scope.row.type === 'Avatar'")
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="scope.row.previousCurrentAvatarThumbnailImageUrl" style="flex:none;width:160px;height:120px;border-radius:4px")
|
||
img.x-link(v-lazy="scope.row.previousCurrentAvatarImageUrl" style="width:500px;height:375px" @click="showAvatarAuthorDialog(scope.row.userId, '', scope.row.previousCurrentAvatarImageUrl)")
|
||
span(style="position:relative;top:-50px;margin:0 5px")
|
||
i.el-icon-right
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="scope.row.currentAvatarThumbnailImageUrl" style="flex:none;width:160px;height:120px;border-radius:4px")
|
||
img.x-link(v-lazy="scope.row.currentAvatarImageUrl" style="width:500px;height:375px" @click="showAvatarAuthorDialog(scope.row.userId, '', scope.row.currentAvatarImageUrl)")
|
||
template(v-else-if="scope.row.type === 'Status'")
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span(v-if="scope.row.previousStatus === 'active'") Active
|
||
span(v-else-if="scope.row.previousStatus === 'join me'") Join Me
|
||
span(v-else-if="scope.row.previousStatus === 'ask me'") Ask Me
|
||
span(v-else-if="scope.row.previousStatus === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="statusClass(scope.row.previousStatus)")
|
||
span(v-text="scope.row.previousStatusDescription")
|
||
br
|
||
span
|
||
i.el-icon-right
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span(v-if="scope.row.status === 'active'") Active
|
||
span(v-else-if="scope.row.status === 'join me'") Join Me
|
||
span(v-else-if="scope.row.status === 'ask me'") Ask Me
|
||
span(v-else-if="scope.row.status === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="statusClass(scope.row.status)")
|
||
span(v-text="scope.row.statusDescription")
|
||
template(v-else-if="scope.row.type === 'Bio'")
|
||
pre(v-text="scope.row.previousBio" style="font-family:inherit;font-size:12px;white-space:pre-wrap;margin:0 0.5em 0 0")
|
||
span
|
||
i.el-icon-right
|
||
pre(v-text="scope.row.bio" style="font-family:inherit;font-size:12px;white-space:pre-wrap;margin:0 0.5em 0 0")
|
||
el-table-column(label="Date" prop="created_at" sortable="custom" width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="right")
|
||
template(#content)
|
||
span {{ scope.row.created_at | formatDate('long') }}
|
||
span {{ scope.row.created_at | formatDate('short') }}
|
||
el-table-column(label="Type" prop="type" width="70")
|
||
el-table-column(label="User" prop="displayName" width="180")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.displayName" @click="showUserDialog(scope.row.userId)")
|
||
el-table-column(label="Detail")
|
||
template(v-once #default="scope")
|
||
template(v-if="scope.row.type === 'GPS'")
|
||
location(v-if="scope.row.location" :location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName")
|
||
template(v-else-if="scope.row.type === 'Offline' || scope.row.type === 'Online'")
|
||
location(v-if="scope.row.location" :location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName")
|
||
template(v-else-if="scope.row.type === 'Status'")
|
||
template(v-if="scope.row.statusDescription === scope.row.previousStatusDescription")
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span(v-if="scope.row.previousStatus === 'active'") Active
|
||
span(v-else-if="scope.row.previousStatus === 'join me'") Join Me
|
||
span(v-else-if="scope.row.previousStatus === 'ask me'") Ask Me
|
||
span(v-else-if="scope.row.previousStatus === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="statusClass(scope.row.previousStatus)")
|
||
span
|
||
i.el-icon-right
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span(v-if="scope.row.status === 'active'") Active
|
||
span(v-else-if="scope.row.status === 'join me'") Join Me
|
||
span(v-else-if="scope.row.status === 'ask me'") Ask Me
|
||
span(v-else-if="scope.row.status === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="statusClass(scope.row.status)")
|
||
template(v-else)
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span(v-if="scope.row.status === 'active'") Online
|
||
span(v-else-if="scope.row.status === 'join me'") Join Me
|
||
span(v-else-if="scope.row.status === 'ask me'") Ask Me
|
||
span(v-else-if="scope.row.status === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="statusClass(scope.row.status)")
|
||
span
|
||
span(v-text="scope.row.statusDescription")
|
||
template(v-else-if="scope.row.type === 'Avatar'")
|
||
avatar-info(:imageurl="scope.row.currentAvatarImageUrl" :userid="scope.row.userId" :hintownerid="scope.row.ownerId" :hintavatarname="scope.row.avatarName")
|
||
template(v-else-if="scope.row.type === 'Bio'")
|
||
span(v-text="scope.row.bio")
|
||
|
||
//- gameLog
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'gameLog'")
|
||
data-tables(v-bind="gameLogTable" v-loading="gameLogTable.loading")
|
||
template(#tool)
|
||
div(style="margin:0 0 10px;display:flex;align-items:center")
|
||
el-select(v-model="gameLogTable.filter" @change="gameLogTableLookup" multiple clearable collapse-tags style="flex:1" placeholder="Filter")
|
||
el-option(v-once v-for="type in ['Location', 'OnPlayerJoined', 'OnPlayerLeft', 'PortalSpawn', 'Event', 'VideoPlay']" :key="type" :label="type" :value="type")
|
||
el-input(v-model="gameLogTable.search" placeholder="Search" @keyup.native.13="gameLogTableLookup" @change="gameLogTableLookup" clearable style="flex:none;width:150px;margin:0 10px")
|
||
//- el-tooltip(placement="bottom" content="Reload game log" :disabled="hideTooltips")
|
||
//- el-button(type="default" @click="resetGameLog" icon="el-icon-refresh" circle style="flex:none")
|
||
el-table-column(label="Date" prop="created_at" sortable="custom" width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="right")
|
||
template(#content)
|
||
span {{ scope.row.created_at | formatDate('long') }}
|
||
span {{ scope.row.created_at | formatDate('short') }}
|
||
el-table-column(label="Type" prop="type" width="120")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-if="scope.row.location && scope.row.type !== 'Location'" v-text="scope.row.type" @click="showWorldDialog(scope.row.location)")
|
||
span(v-else v-text="scope.row.type")
|
||
el-table-column(label="User" prop="displayName" width="180")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-if="scope.row.displayName" v-text="scope.row.displayName" @click="lookupUser(scope.row)" style="padding-right:10px")
|
||
el-table-column(label="Detail" prop="data")
|
||
template(v-once #default="scope")
|
||
location(v-if="scope.row.type === 'Location'" :location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName")
|
||
location(v-else-if="scope.row.type === 'PortalSpawn'" :location="scope.row.instanceId" :hint="scope.row.worldName" :grouphint="scope.row.groupName")
|
||
template(v-else-if="scope.row.type === 'Event'")
|
||
span(v-text="scope.row.data")
|
||
template(v-else-if="scope.row.type === 'VideoPlay'")
|
||
span(v-if="scope.row.videoId") {{ scope.row.videoId }}:
|
||
span(v-if="scope.row.videoId === 'LSMedia'" v-text="scope.row.videoName")
|
||
span.x-link(v-else-if="scope.row.videoName" @click="openExternalLink(scope.row.videoUrl)" v-text="scope.row.videoName")
|
||
span.x-link(v-else @click="openExternalLink(scope.row.videoUrl)" v-text="scope.row.videoUrl")
|
||
template(v-else-if="scope.row.type === 'Notification' || scope.row.type === 'OnPlayerJoined' || scope.row.type === 'OnPlayerLeft'")
|
||
span.x-link(v-else v-text="scope.row.data")
|
||
|
||
//- search
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'search'")
|
||
div(style="margin:0 0 10px;display:flex;align-items:center")
|
||
el-input(v-model="searchText" placeholder="Search" @keyup.native.13="search()" style="flex:1")
|
||
el-tooltip(placement="bottom" content="Clear search results" :disabled="hideTooltips")
|
||
el-button(type="default" @click="clearSearch()" icon="el-icon-delete" circle style="flex:none;margin-left:10px")
|
||
el-tabs(ref="searchTab" type="card" style="margin-top:15px")
|
||
el-tab-pane(label="User" v-loading="isSearchUserLoading" style="min-height:60px")
|
||
.x-friend-list
|
||
.x-friend-item(v-for="user in searchUserResults" :key="user.id" @click="showUserDialog(user.id)")
|
||
template(v-once)
|
||
.avatar
|
||
img(v-lazy="userImage(user)")
|
||
.detail
|
||
span.name(v-text="user.displayName")
|
||
span.extra(v-if="randomUserColours" v-text="user.$trustLevel" :class="user.$trustClass")
|
||
span.extra(v-else v-text="user.$trustLevel" :style="{'color':user.$userColour}")
|
||
el-button-group(style="margin-top:15px")
|
||
el-button(v-if="searchUserParams.offset" @click="moreSearchUser(-1)" icon="el-icon-back" size="small") Prev
|
||
el-button(v-if="searchUserResults.length" @click="moreSearchUser(1)" icon="el-icon-right" size="small") Next
|
||
el-tab-pane(label="World" v-loading="isSearchWorldLoading" style="min-height:60px")
|
||
el-dropdown(@command="(row) => searchWorld(row)" size="small" trigger="click" style="margin-bottom:15px")
|
||
el-button(size="small") Search by Category #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(v-for="row in API.cachedConfig.dynamicWorldRows" :key="row.index" v-text="row.name" :command="row")
|
||
el-checkbox(v-model="searchWorldLabs" style="margin-left:10px") Include community labs
|
||
.x-friend-list
|
||
.x-friend-item(v-for="world in searchWorldResults" :key="world.id" @click="showWorldDialog(world.id)")
|
||
template(v-once)
|
||
.avatar
|
||
img(v-lazy="world.thumbnailImageUrl")
|
||
.detail
|
||
span.name(v-text="world.name")
|
||
span.extra(v-if="world.occupants") {{ world.authorName }} ({{ world.occupants }})
|
||
span.extra(v-else v-text="world.authorName")
|
||
el-button-group(style="margin-top:15px")
|
||
el-button(v-if="searchWorldParams.offset" @click="moreSearchWorld(-1)" icon="el-icon-back" size="small") Prev
|
||
el-button(v-if="searchWorldResults.length >= 10" @click="moreSearchWorld(1)" icon="el-icon-right" size="small") Next
|
||
el-tab-pane(label="Avatar" v-loading="isSearchAvatarLoading" style="min-height:60px")
|
||
el-dropdown(v-if="avatarRemoteDatabaseProviderList.length > 1" trigger="click" @click.native.stop size="mini" style="margin-right:5px")
|
||
el-button(size="small") Search Provider #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(v-for="provider in avatarRemoteDatabaseProviderList" :key="provider" @click.native="setAvatarProvider(provider)") #[i.el-icon-check.el-icon--left(v-if="provider === avatarRemoteDatabaseProvider")] {{ provider }}
|
||
el-tooltip(placement="bottom" content="Refresh own avatars" :disabled="hideTooltips")
|
||
el-button(type="default" :loading="userDialog.isAvatarsLoading" @click="refreshUserDialogAvatars()" size="mini" icon="el-icon-refresh" circle)
|
||
span(style="font-size:14px;margin-left:5px;margin-right:5px") Results {{ searchAvatarResults.length }}
|
||
el-radio-group(v-model="searchAvatarFilter" size="mini" style="margin:5px;display:block" @change="searchAvatar")
|
||
el-radio(label="all") all
|
||
el-radio(label="public") public
|
||
el-radio(label="private") private
|
||
el-radio-group(v-model="searchAvatarFilterRemote" size="mini" style="margin:5px;display:block" @change="searchAvatar")
|
||
el-radio(label="all") all
|
||
el-radio(label="local") local
|
||
el-radio(label="remote" :disabled="!avatarRemoteDatabase") remote
|
||
el-radio-group(:disabled="searchAvatarFilterRemote !== 'local'" v-model="searchAvatarSort" size="mini" style="margin:5px;display:block" @change="searchAvatar")
|
||
el-radio(label="name") by name
|
||
el-radio(label="update") by update
|
||
el-radio(label="created") by created
|
||
.x-friend-list(style="margin-top:20px")
|
||
.x-friend-item(v-for="avatar in searchAvatarPage" :key="avatar.id" @click="showAvatarDialog(avatar.id)")
|
||
template(v-once)
|
||
.avatar
|
||
img(v-if="avatar.thumbnailImageUrl" v-lazy="avatar.thumbnailImageUrl")
|
||
img(v-else-if="avatar.imageUrl" v-lazy="avatar.imageUrl")
|
||
.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)
|
||
span.extra(v-text="avatar.authorName")
|
||
el-button-group(style="margin-top:15px")
|
||
el-button(v-if="searchAvatarPageNum" @click="moreSearchAvatar(-1)" icon="el-icon-back" size="small") Prev
|
||
el-button(v-if="searchAvatarResults.length > 10 && (searchAvatarPageNum + 1) * 10 < searchAvatarResults.length" @click="moreSearchAvatar(1)" icon="el-icon-right" size="small") Next
|
||
|
||
//- favorite
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'favorite'")
|
||
el-tooltip(placement="bottom" content="Refresh all favorites" :disabled="hideTooltips")
|
||
el-button(type="default" :loading="API.isFavoriteLoading" @click="API.refreshFavorites(); getLocalWorldFavorites()" size="small" icon="el-icon-refresh" circle style="position:relative;float:right;z-index:1")
|
||
el-tabs(ref="favoriteTabRef" type="card" v-loading="API.isFavoriteLoading")
|
||
el-tab-pane(label="Friends")
|
||
el-collapse(v-if="$refs.menu && $refs.menu.activeIndex === 'favorite' && $refs.favoriteTabRef && $refs.favoriteTabRef.currentName === '0'" style="border:0")
|
||
el-button(size="small" @click="showFriendExportDialog") Export
|
||
el-button(size="small" @click="showFriendImportDialog") Import
|
||
el-collapse-item(v-for="group in API.favoriteFriendGroups" :key="group.name")
|
||
template(slot="title")
|
||
span(v-text="group.displayName" style="font-weight:bold;font-size:14px;margin-left:10px")
|
||
span(style="color:#909399;font-size:12px;margin-left:10px") {{ group.count }}/{{ group.capacity }}
|
||
el-tooltip(placement="top" content="Rename" :disabled="hideTooltips")
|
||
el-button(@click.stop="changeFavoriteGroupName(group)" size="mini" icon="el-icon-edit" circle style="margin-left:10px")
|
||
el-tooltip(placement="right" content="Clear" :disabled="hideTooltips")
|
||
el-button(@click.stop="clearFavoriteGroup(group)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
.x-friend-list(v-if="group.count" style="margin-top:10px")
|
||
div(style="display:inline-block;width:300px;margin-right:15px" v-for="favorite in favoriteFriends" v-if="favorite.groupKey === group.key" :key="favorite.id" @click="showUserDialog(favorite.id)")
|
||
.x-friend-item
|
||
template(v-if="favorite.ref")
|
||
.avatar(:class="userStatusClass(favorite.ref)")
|
||
img(v-lazy="userImage(favorite.ref)")
|
||
.detail
|
||
span.name(v-text="favorite.ref.displayName" :style="{'color':favorite.ref.$userColour}")
|
||
location.extra(v-if="favorite.ref.location !== 'offline'" :location="favorite.ref.location" :traveling="favorite.ref.travelingToLocation" :link="false")
|
||
span(v-else v-text="favorite.ref.statusDescription")
|
||
el-tooltip(placement="left" content="Move" :disabled="hideTooltips")
|
||
el-dropdown(trigger="click" @click.native.stop size="mini" style="margin-left:5px")
|
||
el-button(type="default" icon="el-icon-back" size="mini" circle)
|
||
el-dropdown-menu(#default="dropdown")
|
||
template(v-if="groupAPI.name !== group.name" v-for="groupAPI in API.favoriteFriendGroups" :key="groupAPI.name")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="moveFavorite(favorite.ref, groupAPI, 'friend')" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
|
||
el-tooltip(placement="right" content="Unfavorite" :disabled="hideTooltips")
|
||
el-button(@click.stop="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
template(v-else)
|
||
span(v-text="favorite.name || favorite.id")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="deleteFavorite(favorite.id)" style="margin-left:5px")
|
||
el-tab-pane(label="Worlds")
|
||
el-collapse(v-if="$refs.menu && $refs.menu.activeIndex === 'favorite' && $refs.favoriteTabRef && $refs.favoriteTabRef.currentName === '1'" style="border:0")
|
||
el-button(size="small" @click="showWorldExportDialog") Export
|
||
el-button(size="small" @click="showWorldImportDialog") Import
|
||
span(style="display:block;margin-top:20px") VRChat Favorites
|
||
el-collapse-item(v-for="group in API.favoriteWorldGroups" :key="group.name")
|
||
template(slot="title")
|
||
span(v-text="group.displayName" style="font-weight:bold;font-size:14px;margin-left:10px")
|
||
i.x-user-status(style="margin-left:5px" :class="userFavoriteWorldsStatus(group.visibility)")
|
||
span(style="color:#909399;font-size:12px;margin-left:10px") {{ group.count }}/{{ group.capacity }}
|
||
el-tooltip(placement="top" content="Change visibility" :disabled="hideTooltips")
|
||
el-dropdown(trigger="click" @click.native.stop size="mini" style="margin-left:10px")
|
||
el-button(type="default" icon="el-icon-view" size="mini" circle)
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(v-if="group.visibility !== visibility" v-for="visibility in worldGroupVisibilityOptions" :key="visibility" style="display:block;margin:10px 0" v-text="visibility" @click.native="changeWorldGroupVisibility(group.name, visibility)")
|
||
el-tooltip(placement="top" content="Rename" :disabled="hideTooltips")
|
||
el-button(@click.stop="changeFavoriteGroupName(group)" size="mini" icon="el-icon-edit" circle style="margin-left:5px")
|
||
el-tooltip(placement="right" content="Clear" :disabled="hideTooltips")
|
||
el-button(@click.stop="clearFavoriteGroup(group)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
.x-friend-list(v-if="group.count" style="margin-top:10px")
|
||
div(style="display:inline-block;width:300px;margin-right:15px" v-for="favorite in favoriteWorlds" v-if="favorite.groupKey === group.key" :key="favorite.id" @click="showWorldDialog(favorite.id)")
|
||
.x-friend-item
|
||
template(v-if="favorite.ref")
|
||
.avatar
|
||
img(v-lazy="favorite.ref.thumbnailImageUrl")
|
||
.detail
|
||
span.name(v-text="favorite.ref.name")
|
||
span.extra(v-if="favorite.ref.occupants") {{ favorite.ref.authorName }} ({{ favorite.ref.occupants }})
|
||
span.extra(v-else v-text="favorite.ref.authorName")
|
||
el-tooltip(placement="left" content="Move" :disabled="hideTooltips")
|
||
el-dropdown(trigger="click" @click.native.stop size="mini" style="margin-left:5px")
|
||
el-button(type="default" icon="el-icon-back" size="mini" circle)
|
||
el-dropdown-menu(#default="dropdown")
|
||
template(v-if="groupAPI.name !== group.name" v-for="groupAPI in API.favoriteWorldGroups" :key="groupAPI.name")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="moveFavorite(favorite.ref, groupAPI, 'world')" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
|
||
el-tooltip(placement="right" content="Unfavorite" :disabled="hideTooltips")
|
||
el-button(@click.stop="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
template(v-else)
|
||
span(v-text="favorite.name || favorite.id")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="deleteFavorite(favorite.id)" style="margin-left:5px")
|
||
span(style="display:block;margin-top:20px") Local Favorites
|
||
el-button(size="small" @click="promptNewLocalWorldFavoriteGroup" style="display:block;margin-top:10px") New Group
|
||
el-collapse-item(v-for="group in localWorldFavoriteGroups" v-if="localWorldFavorites[group]" :key="group")
|
||
template(slot="title")
|
||
span(v-text="group" style="font-weight:bold;font-size:14px;margin-left:10px")
|
||
span(style="color:#909399;font-size:12px;margin-left:10px") {{ getLocalWorldFavoriteGroupLength(group) }}
|
||
el-tooltip(placement="top" content="Rename" :disabled="hideTooltips")
|
||
el-button(@click.stop="promptLocalWorldFavoriteGroupRename(group)" size="mini" icon="el-icon-edit" circle style="margin-left:10px")
|
||
el-tooltip(placement="right" content="Delete" :disabled="hideTooltips")
|
||
el-button(@click.stop="promptLocalWorldFavoriteGroupDelete(group)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
.x-friend-list(style="margin-top:10px")
|
||
div(style="display:inline-block;width:300px;margin-right:15px" v-for="favorite in localWorldFavorites[group]" :key="favorite.id" @click="showWorldDialog(favorite.id)")
|
||
.x-friend-item
|
||
template(v-if="favorite.name")
|
||
.avatar
|
||
img(v-lazy="favorite.thumbnailImageUrl")
|
||
.detail
|
||
span.name(v-text="favorite.name")
|
||
span.extra(v-if="favorite.occupants") {{ favorite.authorName }} ({{ favorite.occupants }})
|
||
span.extra(v-else v-text="favorite.authorName")
|
||
el-tooltip(placement="right" content="Unfavorite" :disabled="hideTooltips")
|
||
el-button(@click.stop="removeLocalWorldFavorite(favorite.id, group)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
template(v-else)
|
||
span(v-text="favorite.id")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="removeLocalWorldFavorite(favorite.id, group)" style="margin-left:5px")
|
||
el-tab-pane(label="Avatars")
|
||
el-collapse(v-if="$refs.menu && $refs.menu.activeIndex === 'favorite' && $refs.favoriteTabRef && $refs.favoriteTabRef.currentName === '2'" style="border:0")
|
||
el-button(size="small" @click="showAvatarExportDialog") Export
|
||
el-button(size="small" @click="showAvatarImportDialog") Import
|
||
el-collapse-item(v-for="group in API.favoriteAvatarGroups" :key="group.name")
|
||
template(slot="title")
|
||
span(v-text="group.displayName" style="font-weight:bold;font-size:14px;margin-left:10px")
|
||
span(style="color:#909399;font-size:12px;margin-left:10px") {{ group.count }}/{{ group.capacity }}
|
||
el-tooltip(placement="top" content="Rename" :disabled="hideTooltips")
|
||
el-button(@click.stop="changeFavoriteGroupName(group)" size="mini" icon="el-icon-edit" circle style="margin-left:10px")
|
||
el-tooltip(placement="right" content="Clear" :disabled="hideTooltips")
|
||
el-button(@click.stop="clearFavoriteGroup(group)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
.x-friend-list(v-if="group.count" style="margin-top:10px")
|
||
div(style="display:inline-block;width:300px;margin-right:15px" v-for="favorite in favoriteAvatars" v-if="favorite.groupKey === group.key" :key="favorite.id" @click="showAvatarDialog(favorite.id)")
|
||
.x-friend-item
|
||
template(v-if="favorite.ref")
|
||
.avatar
|
||
img(v-lazy="favorite.ref.thumbnailImageUrl")
|
||
.detail
|
||
span.name(v-text="favorite.ref.name")
|
||
span.extra(v-text="favorite.ref.authorName")
|
||
el-tooltip(placement="left" content="Move" :disabled="hideTooltips")
|
||
el-dropdown(trigger="click" @click.native.stop size="mini" style="margin-left:5px")
|
||
el-button(type="default" icon="el-icon-back" size="mini" circle)
|
||
el-dropdown-menu(#default="dropdown")
|
||
template(v-if="groupAPI.name !== group.name" v-for="groupAPI in API.favoriteAvatarGroups" :key="groupAPI.name")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="moveFavorite(favorite.ref, groupAPI, 'avatar')" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }})
|
||
el-tooltip(placement="right" content="Unfavorite" :disabled="hideTooltips")
|
||
el-button(@click.stop="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
template(v-else)
|
||
.detail
|
||
span.name(v-text="favorite.name || favorite.id")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="deleteFavorite(favorite.id)" style="margin-left:5px")
|
||
el-collapse-item
|
||
template(slot="title")
|
||
span(style="font-weight:bold;font-size:14px;margin-left:10px") Local History
|
||
span(style="color:#909399;font-size:12px;margin-left:10px") {{ avatarHistoryArray.length }}/100
|
||
el-tooltip(placement="right" content="Clear" :disabled="hideTooltips")
|
||
el-button(@click.stop="promptClearAvatarHistory" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
.x-friend-list(v-if="avatarHistoryArray.length" style="margin-top:10px")
|
||
div(style="display:inline-block;width:300px;margin-right:15px" v-for="favorite in avatarHistoryArray" :key="favorite.id" @click="showAvatarDialog(favorite.id)")
|
||
.x-friend-item
|
||
.avatar
|
||
img(v-lazy="favorite.thumbnailImageUrl")
|
||
.detail
|
||
span.name(v-text="favorite.name")
|
||
span.extra(v-text="favorite.authorName")
|
||
template(v-if="API.cachedFavoritesByObjectId.has(favorite.id)")
|
||
el-tooltip(placement="left" content="Unfavorite" :disabled="hideTooltips")
|
||
el-button(@click.stop="deleteFavorite(favorite.id)" type="default" icon="el-icon-star-on" size="mini" circle)
|
||
template(v-else)
|
||
el-tooltip(placement="left" content="Favorite" :disabled="hideTooltips")
|
||
el-button(@click.stop="showFavoriteDialog('avatar', favorite.id)" type="default" icon="el-icon-star-off" size="mini" circle)
|
||
|
||
//- friendLog
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'friendLog'" v-if="$refs.menu && $refs.menu.activeIndex === 'friendLog'")
|
||
data-tables(v-bind="friendLogTable")
|
||
template(#tool)
|
||
div(style="margin:0 0 10px;display:flex;align-items:center")
|
||
el-select(v-model="friendLogTable.filters[0].value" @change="saveTableFilters" multiple clearable collapse-tags style="flex:1" placeholder="Filter")
|
||
el-option(v-once v-for="type in ['Friend', 'Unfriend', 'FriendRequest', 'CancelFriendRequest', 'DisplayName', 'TrustLevel']" :key="type" :label="type" :value="type")
|
||
el-input(v-model="friendLogTable.filters[1].value" placeholder="Search" style="flex:none;width:150px;margin-left:10px")
|
||
el-table-column(label="Date" prop="created_at" sortable="custom" width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="right")
|
||
template(#content)
|
||
span {{ scope.row.created_at | formatDate('long') }}
|
||
span {{ scope.row.created_at | formatDate('short') }}
|
||
el-table-column(label="Type" prop="type" width="150")
|
||
el-table-column(label="User" prop="displayName")
|
||
template(v-once #default="scope")
|
||
span(v-if="scope.row.type === 'DisplayName'") {{ scope.row.previousDisplayName }} #[i.el-icon-right]
|
||
span.x-link(v-text="scope.row.displayName || scope.row.userId" @click="showUserDialog(scope.row.userId)")
|
||
template(v-if="scope.row.type === 'TrustLevel'")
|
||
span ({{ scope.row.previousTrustLevel }} #[i.el-icon-right] {{ scope.row.trustLevel }})
|
||
el-table-column(label="Action" width="80" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click="deleteFriendLog(scope.row)")
|
||
|
||
//- moderation
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'moderation'" v-if="$refs.menu && $refs.menu.activeIndex === 'moderation'")
|
||
data-tables(v-bind="playerModerationTable" v-loading="API.isPlayerModerationsLoading")
|
||
template(#tool)
|
||
div(style="margin:0 0 10px;display:flex;align-items:center")
|
||
el-select(v-model="playerModerationTable.filters[0].value" @change="saveTableFilters" multiple clearable collapse-tags style="flex:1" placeholder="Filter")
|
||
el-option(v-once v-for="type in ['block', 'unblock', 'mute', 'unmute', 'interactOn', 'interactOff']" :key="type" :label="type" :value="type")
|
||
el-input(v-model="playerModerationTable.filters[1].value" placeholder="Search" style="flex:none;width:150px;margin:0 10px")
|
||
el-tooltip(placement="bottom" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" :loading="API.isPlayerModerationsLoading" @click="API.refreshPlayerModerations()" icon="el-icon-refresh" circle style="flex:none")
|
||
el-table-column(label="Date" prop="created" sortable="custom" width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="right")
|
||
template(#content)
|
||
span {{ scope.row.created | formatDate('long') }}
|
||
span {{ scope.row.created | formatDate('short') }}
|
||
el-table-column(label="Type" prop="type" width="100")
|
||
el-table-column(label="Source" prop="sourceDisplayName")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.sourceDisplayName" @click="showUserDialog(scope.row.sourceUserId)")
|
||
el-table-column(label="Target" prop="targetDisplayName")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.targetDisplayName" @click="showUserDialog(scope.row.targetUserId)")
|
||
el-table-column(label="Action" width="80" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(v-if="scope.row.sourceUserId === API.currentUser.id" type="text" icon="el-icon-close" size="mini" @click="deletePlayerModeration(scope.row)")
|
||
|
||
//- notification
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'notification'" v-if="$refs.menu && $refs.menu.activeIndex === 'notification'" v-loading="API.isNotificationsLoading")
|
||
data-tables(v-bind="notificationTable")
|
||
template(#tool)
|
||
div(style="margin:0 0 10px;display:flex;align-items:center")
|
||
el-select(v-model="notificationTable.filters[0].value" @change="saveTableFilters" multiple clearable collapse-tags style="flex:1" placeholder="Filter")
|
||
el-option(v-once v-for="type in ['requestInvite', 'invite', 'requestInviteResponse', 'inviteResponse', 'friendRequest', 'hiddenFriendRequest', 'message', 'group.announcement', 'group.informative', 'group.invite', 'group.joinRequest', 'moderation.warning.group']" :key="type" :label="type" :value="type")
|
||
el-input(v-model="notificationTable.filters[1].value" placeholder="Search" style="flex:none;width:150px;margin:0 10px")
|
||
el-tooltip(placement="bottom" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" :loading="API.isNotificationsLoading" @click="API.refreshNotifications()" icon="el-icon-refresh" circle style="flex:none")
|
||
el-table-column(label="Date" prop="created_at" sortable="custom" width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="right")
|
||
template(#content)
|
||
span {{ scope.row.created_at | formatDate('long') }}
|
||
span {{ scope.row.created_at | formatDate('short') }}
|
||
el-table-column(label="Type" prop="type" width="160")
|
||
template(v-once #default="scope")
|
||
el-tooltip(v-if="scope.row.type === 'invite'" placement="top")
|
||
template(#content)
|
||
location(v-if="scope.row.details" :location="scope.row.details.worldId" :hint="scope.row.details.worldName" :grouphint="scope.row.details.groupName" :link="false")
|
||
span.x-link(v-text="scope.row.type" @click="showWorldDialog(scope.row.details.worldId)")
|
||
template(v-else-if="scope.row.link")
|
||
el-tooltip(placement="top" :content="scope.row.linkText" :disabled="hideTooltips")
|
||
span.x-link(v-text="scope.row.type" @click="openNotificationLink(scope.row.link)")
|
||
span(v-else v-text="scope.row.type")
|
||
el-table-column(label="User" prop="senderUsername" width="150")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.senderUsername" @click="showUserDialog(scope.row.senderUserId)")
|
||
el-table-column(label="Photo" width="100" prop="photo")
|
||
template(v-once #default="scope")
|
||
template(v-if="scope.row.details && scope.row.details.imageUrl")
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="scope.row.details.imageUrl" style="flex:none;width:90px;border-radius:4px")
|
||
img.x-link(v-lazy="scope.row.details.imageUrl" style="width:500px" @click="downloadAndSaveImage(scope.row.details.imageUrl)")
|
||
template(v-else-if="scope.row.imageUrl")
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="scope.row.imageUrl" style="flex:none;width:90px;border-radius:4px")
|
||
img.x-link(v-lazy="scope.row.imageUrl" style="width:500px" @click="downloadAndSaveImage(scope.row.imageUrl)")
|
||
el-table-column(label="Message" prop="message")
|
||
template(v-once #default="scope")
|
||
span(v-if="scope.row.title") {{ scope.row.title }}, {{ scope.row.message }}
|
||
span(v-else-if="scope.row.message" v-text="scope.row.message")
|
||
span(v-else-if='scope.row.details && scope.row.details.inviteMessage' v-text="scope.row.details.inviteMessage")
|
||
span(v-else-if='scope.row.details && scope.row.details.requestMessage' v-text="scope.row.details.requestMessage")
|
||
span(v-else-if='scope.row.details && scope.row.details.responseMessage' v-text="scope.row.details.responseMessage")
|
||
el-table-column(label="Action" width="100" align="right")
|
||
template(v-once #default="scope")
|
||
template(v-if="scope.row.senderUserId !== API.currentUser.id && !scope.row.$isExpired")
|
||
template(v-if="scope.row.type === 'friendRequest'")
|
||
el-tooltip(placement="top" content="Accept" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-check" size="mini" @click="acceptNotification(scope.row)")
|
||
template(v-else-if="scope.row.type === 'invite'")
|
||
el-tooltip(placement="top" content="Decline with message" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-chat-line-square" size="mini" @click="showSendInviteResponseDialog(scope.row)")
|
||
template(v-else-if="scope.row.type === 'requestInvite'")
|
||
template(v-if="lastLocation.location && isGameRunning && checkCanInvite(lastLocation.location)")
|
||
el-tooltip(placement="top" content="Invite" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-check" size="mini" @click="acceptRequestInvite(scope.row)")
|
||
el-tooltip(placement="top" content="Decline with message" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-chat-line-square" size="mini" style="margin-left:5px" @click="showSendInviteRequestResponseDialog(scope.row)")
|
||
template(v-else-if="scope.row.type === 'group.invite'")
|
||
el-tooltip(placement="top" content="Accept" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-check" size="mini" style="margin-left:5px" @click="sendNotificationResponse(scope.row.id, scope.row.responses, 'accept')")
|
||
el-tooltip(placement="top" content="Decline" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-close" size="mini" style="margin-left:5px" @click="sendNotificationResponse(scope.row.id, scope.row.responses, 'decline')")
|
||
el-tooltip(placement="top" content="Block invites from group" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-circle-close" size="mini" style="margin-left:5px" @click="sendNotificationResponse(scope.row.id, scope.row.responses, 'block')")
|
||
template(v-else-if="scope.row.type === 'group.joinRequest'")
|
||
el-tooltip(placement="top" content="Accept" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-check" size="mini" style="margin-left:5px" @click="sendNotificationResponse(scope.row.id, scope.row.responses, 'accept')")
|
||
el-tooltip(placement="top" content="Decline" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-close" size="mini" style="margin-left:5px" @click="sendNotificationResponse(scope.row.id, scope.row.responses, 'reject')")
|
||
el-tooltip(placement="top" content="Block user from requesting" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-circle-close" size="mini" style="margin-left:5px" @click="sendNotificationResponse(scope.row.id, scope.row.responses, 'block')")
|
||
template(v-else-if="scope.row.type === 'group.announcement'")
|
||
el-tooltip(placement="top" content="Dismiss" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-check" size="mini" style="margin-left:5px" @click="sendNotificationResponse(scope.row.id, scope.row.responses, 'delete')")
|
||
el-tooltip(placement="top" content="Unsubscribe" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-close" size="mini" style="margin-left:5px" @click="sendNotificationResponse(scope.row.id, scope.row.responses, 'unsubscribe')")
|
||
template(v-else-if="scope.row.type === 'group.informative'")
|
||
el-tooltip(placement="top" content="Dismiss" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-check" size="mini" style="margin-left:5px" @click="sendNotificationResponse(scope.row.id, scope.row.responses, 'delete')")
|
||
template(v-if="scope.row.type !== 'requestInviteResponse' && scope.row.type !== 'inviteResponse' && scope.row.type !== 'message' && !scope.row.type.includes('group.') && !scope.row.type.includes('moderation.')")
|
||
el-tooltip(placement="top" content="Decline" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-close" size="mini" style="margin-left:5px" @click="hideNotification(scope.row)")
|
||
template(v-if="scope.row.type !== 'friendRequest' && scope.row.type !== 'hiddenFriendRequest' && !scope.row.type.includes('group.') && !scope.row.type.includes('moderation.')")
|
||
el-tooltip(placement="top" content="Delete log" :disabled="hideTooltips")
|
||
el-button(type="text" icon="el-icon-delete" size="mini" style="margin-left:5px" @click="deleteNotificationLog(scope.row)")
|
||
|
||
//- profile
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'profile'")
|
||
div.options-container(style="margin-top:0")
|
||
span.header Profile
|
||
.x-friend-list(style="margin-top:10px")
|
||
.x-friend-item(@click="showUserDialog(API.currentUser.id)")
|
||
.avatar
|
||
img(v-lazy="userImage(API.currentUser)")
|
||
.detail
|
||
span.name(v-text="API.currentUser.displayName")
|
||
span.extra(v-text="API.currentUser.username")
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Last Activity
|
||
span.extra {{ API.currentUser.last_activity | formatDate('long') }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Two-Factor Auth (2FA)
|
||
span.extra {{ API.currentUser.twoFactorAuthEnabled ? 'Enabled' : 'Disabled' }}
|
||
div
|
||
el-button(size="small" icon="el-icon-switch-button" @click="logout()" style="margin-left:0;margin-right:5px;margin-top:10px") Logout
|
||
el-button(size="small" icon="el-icon-printer" @click="showExportFriendsListDialog()" style="margin-left:0;margin-right:5px;margin-top:10px") Export Friends List
|
||
el-button(size="small" icon="el-icon-user" @click="showExportAvatarsListDialog()" style="margin-left:0;margin-right:5px;margin-top:10px") Export Own Avatars
|
||
el-button(size="small" icon="el-icon-chat-dot-round" @click="showDiscordNamesDialog()" style="margin-left:0;margin-right:5px;margin-top:10px") Discord Names
|
||
el-button(size="small" icon="el-icon-document-copy" @click="showNoteExportDialog()" style="margin-left:0;margin-right:5px;margin-top:10px") Export Notes
|
||
div.options-container
|
||
span.header Game Info
|
||
.x-friend-list(style="margin-top:10px")
|
||
.x-friend-item
|
||
.detail(@click="API.getVisits()")
|
||
span.name Online Users
|
||
span.extra(v-if="visits") {{visits}} users online.
|
||
span.extra(v-else) Click to refresh
|
||
div.options-container
|
||
span.header VRC SDK Downloads
|
||
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" @click="API.getConfig()" size="mini" icon="el-icon-refresh" circle style="margin-left:5px")
|
||
.x-friend-list(style="margin-top:10px")
|
||
.x-friend-item(v-for="(link, item) in API.cachedConfig.downloadUrls" :key="item" placement="top")
|
||
.detail(@click="openExternalLink(link)")
|
||
span.name(v-text="item")
|
||
span.extra(v-text="link")
|
||
div.options-container
|
||
span.header Direct Access
|
||
div(style="margin-top:10px")
|
||
el-button-group
|
||
el-button(size="small" @click="promptUsernameDialog()") Username
|
||
el-button(size="small" @click="promptUserIdDialog()") User ID
|
||
el-button(size="small" @click="promptWorldDialog()") World/Instance
|
||
el-button(size="small" @click="promptAvatarDialog()") Avatar
|
||
div.options-container
|
||
span.header Invite Messages
|
||
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" @click="inviteMessageTable.visible = true; refreshInviteMessageTable('message')" size="mini" icon="el-icon-refresh" circle style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Clear results" :disabled="hideTooltips")
|
||
el-button(type="default" @click="inviteMessageTable.visible = false" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
data-tables(v-if="inviteMessageTable.visible" v-bind="inviteMessageTable" style="margin-top:10px")
|
||
el-table-column(label="Slot" prop="slot" sortable="custom" width="70")
|
||
el-table-column(label="Message" prop="message")
|
||
el-table-column(label="Cool Down" prop="updatedAt" sortable="custom" width="110" align="right")
|
||
template(v-once #default="scope")
|
||
countdown-timer(:datetime="scope.row.updatedAt" :hours="1")
|
||
el-table-column(label="Action" width="60" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-edit" size="mini" @click="showEditInviteMessageDialog('message', scope.row)")
|
||
div.options-container
|
||
span.header Invite Response Messages
|
||
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" @click="inviteResponseMessageTable.visible = true; refreshInviteMessageTable('response')" size="mini" icon="el-icon-refresh" circle style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Clear results" :disabled="hideTooltips")
|
||
el-button(type="default" @click="inviteResponseMessageTable.visible = false" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
data-tables(v-if="inviteResponseMessageTable.visible" v-bind="inviteResponseMessageTable" style="margin-top:10px")
|
||
el-table-column(label="Slot" prop="slot" sortable="custom" width="70")
|
||
el-table-column(label="Message" prop="message")
|
||
el-table-column(label="Cool Down" prop="updatedAt" sortable="custom" width="110" align="right")
|
||
template(v-once #default="scope")
|
||
countdown-timer(:datetime="scope.row.updatedAt" :hours="1")
|
||
el-table-column(label="Action" width="60" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-edit" size="mini" @click="showEditInviteMessageDialog('response', scope.row)")
|
||
div.options-container
|
||
span.header Invite Request Messages
|
||
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" @click="inviteRequestMessageTable.visible = true; refreshInviteMessageTable('request')" size="mini" icon="el-icon-refresh" circle style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Clear results" :disabled="hideTooltips")
|
||
el-button(type="default" @click="inviteRequestMessageTable.visible = false" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
data-tables(v-if="inviteRequestMessageTable.visible" v-bind="inviteRequestMessageTable" style="margin-top:10px")
|
||
el-table-column(label="Slot" prop="slot" sortable="custom" width="70")
|
||
el-table-column(label="Message" prop="message")
|
||
el-table-column(label="Cool Down" prop="updatedAt" sortable="custom" width="110" align="right")
|
||
template(v-once #default="scope")
|
||
countdown-timer(:datetime="scope.row.updatedAt" :hours="1")
|
||
el-table-column(label="Action" width="60" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-edit" size="mini" @click="showEditInviteMessageDialog('request', scope.row)")
|
||
div.options-container
|
||
span.header Invite Request Response Messages
|
||
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" @click="inviteRequestResponseMessageTable.visible = true; refreshInviteMessageTable('requestResponse')" size="mini" icon="el-icon-refresh" circle style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Clear results" :disabled="hideTooltips")
|
||
el-button(type="default" @click="inviteRequestResponseMessageTable.visible = false" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
data-tables(v-if="inviteRequestResponseMessageTable.visible" v-bind="inviteRequestResponseMessageTable" style="margin-top:10px")
|
||
el-table-column(label="Slot" prop="slot" sortable="custom" width="70")
|
||
el-table-column(label="Message" prop="message")
|
||
el-table-column(label="Cool Down" prop="updatedAt" sortable="custom" width="110" align="right")
|
||
template(v-once #default="scope")
|
||
countdown-timer(:datetime="scope.row.updatedAt" :hours="1")
|
||
el-table-column(label="Action" width="60" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-edit" size="mini" @click="showEditInviteMessageDialog('requestResponse', scope.row)")
|
||
div.options-container
|
||
span.header Past Display Names
|
||
data-tables(v-bind="pastDisplayNameTable" style="margin-top:10px")
|
||
el-table-column(label="Date" prop="updated_at" sortable="custom")
|
||
template(v-once #default="scope")
|
||
span {{ scope.row.updated_at | formatDate('long') }}
|
||
el-table-column(label="Name" prop="displayName")
|
||
div.options-container
|
||
span.header Config JSON
|
||
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" @click="refreshConfigTreeData()" size="mini" icon="el-icon-refresh" circle style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Clear results" :disabled="hideTooltips")
|
||
el-button(type="default" @click="configTreeData = []" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
el-tree(v-if="configTreeData.length > 0" :data="configTreeData" style="margin-top:10px;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")
|
||
div.options-container
|
||
span.header Current User JSON
|
||
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" @click="refreshCurrentUserTreeData()" size="mini" icon="el-icon-refresh" circle style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Clear results" :disabled="hideTooltips")
|
||
el-button(type="default" @click="currentUserTreeData = []" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
el-tree(v-if="currentUserTreeData.length > 0" :data="currentUserTreeData" style="margin-top:10px;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")
|
||
|
||
//- friends list
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'friendsList'" v-if="$refs.menu && $refs.menu.activeIndex === 'friendsList'")
|
||
div.options-container(style="margin-top:0")
|
||
span.header Friends List
|
||
div(style="float:right;font-size:13px")
|
||
div(v-if="friendsListBulkUnfriendMode" style="display:inline-block;margin-right:10px")
|
||
el-button(size="small" @click="showBulkUnfriendSelectionConfirm") Bulk Unfriend Selection
|
||
//- el-button(size="small" @click="showBulkUnfriendAllConfirm" style="margin-right:5px") Bulk Unfriend All
|
||
div(style="display:inline-block;margin-right:10px")
|
||
span.name Bulk Unfriend Mode
|
||
el-switch(v-model="friendsListBulkUnfriendMode" style="margin-left:5px")
|
||
span Load missing entries
|
||
el-tooltip(placement="top" style="margin-left:5px" content="This takes a lot of API requests so use it sparingly")
|
||
i.el-icon-warning
|
||
template(v-if="friendsListLoading")
|
||
span(v-text="friendsListLoadingProgress" style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Cancel" :disabled="hideTooltips")
|
||
el-button(@click="friendsListLoading = false" size="mini" icon="el-icon-loading" circle style="margin-left:5px")
|
||
template(v-else)
|
||
el-tooltip(placement="top" content="Load" :disabled="hideTooltips")
|
||
el-button(@click="friendsListLoadUsers" size="mini" icon="el-icon-refresh-left" circle style="margin-left:5px")
|
||
div(style="margin:10px 0 0 10px;display:flex;align-items:center")
|
||
div(style="flex:none;margin-right:10px")
|
||
el-tooltip(placement="bottom" content="Filter VIP only" :disabled="hideTooltips")
|
||
el-switch(v-model="friendsListSearchFilterVIP" @change="friendsListSearchChange" active-color="#13ce66")
|
||
el-input(v-model="friendsListSearch" placeholder="Search" @change="friendsListSearchChange" clearable style="flex:1")
|
||
el-select(v-model="friendsListSearchFilters" multiple clearable collapse-tags style="flex:none;width:200px;margin:0 10px" @change="friendsListSearchChange" placeholder="Filter")
|
||
el-option(v-once v-for="type in ['Display Name', 'User Name', 'Rank', 'Status', 'Bio', 'Memo']" :key="type" :label="type" :value="type")
|
||
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" @click="friendsListSearchChange" icon="el-icon-refresh" circle style="flex:none")
|
||
el-tooltip(placement="top" content="Clear results" :disabled="hideTooltips")
|
||
el-button(type="default" @click="friendsListTable.data = []" icon="el-icon-delete" circle style="flex:none;margin-left:5px")
|
||
data-tables(v-bind="friendsListTable" @row-click="selectFriendsListRow" style="margin-top:10px;cursor:pointer")
|
||
el-table-column(v-if="friendsListBulkUnfriendMode" width="55" prop="$selected")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" size="mini" @click.stop)
|
||
el-checkbox(v-model="scope.row.$selected")
|
||
el-table-column(label="No." width="70" prop="$friendNum" sortable="custom")
|
||
el-table-column(label="Avatar" width="70" prop="photo")
|
||
template(v-once #default="scope")
|
||
el-popover(placement="right" height="500px" trigger="hover")
|
||
img.friends-list-avatar(slot="reference" v-lazy="userImage(scope.row)")
|
||
img.friends-list-avatar(v-lazy="userImageFull(scope.row)" style="height:500px;cursor:pointer" @click="downloadAndSaveImage(userImageFull(scope.row))")
|
||
el-table-column(label="Display Name" min-width="140" prop="displayName" sortable :sort-method="(a, b) => sortAlphabetically(a, b, 'displayName')")
|
||
template(v-once #default="scope")
|
||
span.name(v-if="randomUserColours" v-text="scope.row.displayName" :style="{'color':scope.row.$userColour}")
|
||
span.name(v-else v-text="scope.row.displayName")
|
||
el-table-column(label="Rank" width="110" prop="$trustSortNum" sortable="custom")
|
||
template(v-once #default="scope")
|
||
span.name(v-if="randomUserColours" v-text="scope.row.$trustLevel" :class="scope.row.$trustClass")
|
||
span.name(v-else v-text="scope.row.$trustLevel" :style="{'color':scope.row.$userColour}")
|
||
el-table-column(label="Status" min-width="180" prop="status" sortable :sort-method="(a, b) => sortStatus(a.status, b.status)")
|
||
template(v-once #default="scope")
|
||
i.x-user-status(v-if="scope.row.status !== 'offline'" :class="statusClass(scope.row.status)")
|
||
span
|
||
span(v-text="scope.row.statusDescription")
|
||
el-table-column(label="Language" width="110" prop="$languages" sortable :sort-method="(a, b) => sortLanguages(a, b)")
|
||
template(v-once #default="scope")
|
||
el-tooltip(v-for="item in scope.row.$languages" :key="item.key" placement="top")
|
||
template(#content)
|
||
span {{ item.value }} ({{ item.key }})
|
||
span.flags(:class="languageClass(item.key)" style="display:inline-block;margin-left:5px")
|
||
el-table-column(label="Bio Links" width="100" prop="bioLinks")
|
||
template(v-once #default="scope")
|
||
el-tooltip(v-if="link" v-for="(link, index) in scope.row.bioLinks" :key="index")
|
||
template(#content)
|
||
span(v-text="link")
|
||
img(:src="getFaviconUrl(link)" style="width:16px;height:16px;vertical-align:middle;margin-right:5px;cursor:pointer" @click.stop="openExternalLink(link)")
|
||
el-table-column(label="Join Count" width="120" prop="$joinCount" sortable)
|
||
el-table-column(label="Time Together" width="140" prop="$timeSpent" sortable)
|
||
template(v-once #default="scope")
|
||
span(v-if="scope.row.$timeSpent") {{ scope.row.$timeSpent | timeToText }}
|
||
el-table-column(label="Last Seen" width="170" prop="$lastSeen" sortable :sort-method="(a, b) => sortAlphabetically(a, b, '$lastSeen')")
|
||
template(v-once #default="scope")
|
||
span {{ scope.row.$lastSeen | formatDate('long') }}
|
||
el-table-column(label="Last Activity" width="170" prop="last_activity" sortable :sort-method="(a, b) => sortAlphabetically(a, b, 'last_activity')")
|
||
template(v-once #default="scope")
|
||
span {{ scope.row.last_activity | formatDate('long') }}
|
||
el-table-column(label="Last Login" width="170" prop="last_login" sortable :sort-method="(a, b) => sortAlphabetically(a, b, 'last_login')")
|
||
template(v-once #default="scope")
|
||
span {{ scope.row.last_login | formatDate('long') }}
|
||
el-table-column(label="Date Joined" width="120" prop="date_joined" sortable :sort-method="(a, b) => sortAlphabetically(a, b, 'date_joined')")
|
||
el-table-column(label="Unfriend" width="80")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="confirmDeleteFriend(scope.row.id)")
|
||
|
||
//- settings
|
||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'settings'")
|
||
div.options-container(style="margin-top:0")
|
||
span.header Settings
|
||
el-tabs(type="card" style="margin-top:10px")
|
||
el-tab-pane(label="General")
|
||
div.options-container(style="margin-top:0")
|
||
span.header General
|
||
.x-friend-list(style="margin-top:10px")
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Version
|
||
span.extra(v-text="appVersion")
|
||
.x-friend-item(@click="checkForVRCXUpdate")
|
||
.detail
|
||
span.name Latest Version
|
||
span.extra(v-if="latestAppVersion" v-text="latestAppVersion")
|
||
span.extra(v-else) Click to refresh
|
||
.x-friend-item(@click="openExternalLink('https://github.com/pypy-vrc/VRCX')")
|
||
.detail
|
||
span.name Repository URL
|
||
span.extra https://github.com/pypy-vrc/VRCX
|
||
.x-friend-item(@click="openExternalLink('https://vrcx.pypy.moe/discord')")
|
||
.detail
|
||
span.name Support
|
||
span.extra https://vrcx.pypy.moe/discord
|
||
div.options-container
|
||
span.header VRCX Updater
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-upload" @click="showVRCXUpdateDialog()") Change build
|
||
div.options-container-item
|
||
span.name Auto update:
|
||
br
|
||
el-radio-group(v-model="autoUpdateVRCX" @change="saveAutoUpdateVRCX" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="Notify")
|
||
el-radio-button(label="Auto Download")
|
||
el-radio-button(label="Auto Install")
|
||
div.options-container
|
||
span.header Application
|
||
div.options-container-item
|
||
span.name Start at Windows startup
|
||
el-switch(v-model="isStartAtWindowsStartup")
|
||
div.options-container-item
|
||
span.name Start as minimized state
|
||
el-switch(v-model="isStartAsMinimizedState")
|
||
div.options-container-item
|
||
span.name Close to tray
|
||
el-switch(v-model="isCloseToTray")
|
||
div.options-container
|
||
div.options-container(style="margin-top:45px;border-top:1px solid #eee;padding-top:30px")
|
||
span.header Legal Notice
|
||
div.options-container-item
|
||
p © 2019-2022 #[a(@click="openExternalLink('https://github.com/pypy-vrc')") pypy] (mina#5656) & #[a(@click="openExternalLink('https://github.com/Natsumi-sama')") Natsumi]
|
||
p VRCX is an assistant application for provide information about manage friendship. this application uses unofficial VRChat API (VRCSDK).
|
||
p VRCX isn't endorsed by VRChat and doesn't reflect the views or opinions of VRChat or anyone officially involved in producing or managing VRChat. VRChat is trademark of VRChat Inc. VRChat © VRChat Inc.
|
||
p pypy or Natsumi aren't responsible for any problems caused by VRCX. Use at your own risk!
|
||
div.options-container-item
|
||
el-button(@click="ossDialog = true" size="small") Open Source Software Notice
|
||
el-tab-pane(label="Appearance")
|
||
div.options-container(style="margin-top:0")
|
||
span.header Appearance
|
||
div.options-container-item
|
||
span.name Theme mode
|
||
el-radio-group(v-model="themeMode" size="mini")
|
||
el-radio-button(label="system") System
|
||
el-radio-button(label="light") Light
|
||
el-radio-button(label="dark") Dark
|
||
div.options-container-item
|
||
span.name VRCPlus Profile Icons
|
||
el-switch(v-model="displayVRCPlusIconsAsAvatar" @change="saveOpenVROption")
|
||
div.options-container-item
|
||
span.name Disable Tooltips
|
||
el-switch(v-model="hideTooltips" @change="saveOpenVROption")
|
||
div.options-container-item
|
||
span.name Sort Favorites By
|
||
el-switch(v-model="sortFavorites" inactive-text="name" active-text="date" @change="saveSortFavoritesOption")
|
||
div.options-container-item
|
||
span.name Sort Instance Users By
|
||
el-switch(v-model="instanceUsersSortAlphabetical" inactive-text="time" active-text="alphabetical" @change="saveOpenVROption")
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-notebook-1" @click="promptMaxTableSizeDialog") Table Max Size
|
||
div.options-container-item
|
||
el-dropdown(@click.native.stop trigger="click" size="small")
|
||
el-button(size="mini")
|
||
span Page Size: {{ tablePageSize }} #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(v-for="(number) in [10, 15, 25, 50, 100]" v-text="number" @click.native="setTablePageSize(number)")
|
||
div.options-container
|
||
span.header Timedate
|
||
div.options-container-item
|
||
span.name Time Format
|
||
el-switch(v-model="dtHour12" @change="setDatetimeFormat" inactive-text="24 Hour" active-text="12 Hour")
|
||
div.options-container-item
|
||
span.name Force ISO date format
|
||
el-switch(v-model="dtIsoFormat" @change="setDatetimeFormat")
|
||
div.options-container
|
||
span.header Side Panel
|
||
br
|
||
span.sub-header Sorting
|
||
div.options-container-item
|
||
span.name Sort Private to bottom
|
||
el-switch(v-model="orderFriendsGroupPrivate" @change="saveOrderFriendGroup")
|
||
div.options-container-item
|
||
span.name Sort by status
|
||
el-switch(v-model="orderFriendsGroupStatus" @change="saveOrderFriendGroup")
|
||
div.options-container-item
|
||
span.name Sort GPS to top
|
||
el-switch(v-model="orderFriendsGroupGPS" @change="saveOrderFriendGroup")
|
||
span.name(style="margin-left:5px") (online for only)
|
||
div.options-container-item
|
||
span.name VIP
|
||
el-switch(v-model="orderFriendsGroup0" inactive-text="alphabetical" active-text="online for" @change="saveOrderFriendGroup")
|
||
div.options-container-item
|
||
span.name Online
|
||
el-switch(v-model="orderFriendsGroup1" inactive-text="alphabetical" active-text="online for" @change="saveOrderFriendGroup")
|
||
div.options-container-item
|
||
span.name Active
|
||
el-switch(v-model="orderFriendsGroup2" inactive-text="alphabetical" active-text="online for" @change="saveOrderFriendGroup")
|
||
div.options-container-item
|
||
span.name Offline
|
||
el-switch(v-model="orderFriendsGroup3" inactive-text="alphabetical" active-text="online for" @change="saveOrderFriendGroup")
|
||
span.sub-header Width
|
||
div.options-container-item
|
||
el-slider(v-model="asideWidth" @input="setAsideWidth" :show-tooltip="false" :marks="{236: ''}" :min="141" :max="500" style="width:300px")
|
||
div.options-container
|
||
span.header User Dialog
|
||
div.options-container-item
|
||
span.name Hide VRChat Notes
|
||
el-switch(v-model="hideUserNotes" @change="saveUserDialogOption")
|
||
div.options-container-item
|
||
span.name Hide VRCX Memos
|
||
el-switch(v-model="hideUserMemos" @change="saveUserDialogOption")
|
||
div.options-container-item
|
||
span.name Export VRCX memos into VRChat notes
|
||
br
|
||
el-button(size="small" icon="el-icon-document-copy" @click="showNoteExportDialog") Export Notes
|
||
div.options-container
|
||
span.header User Colours
|
||
div.options-container-item
|
||
span.name Random colours from user ID
|
||
el-switch(v-model="randomUserColours" @change="updatetrustColor")
|
||
div.options-container-item
|
||
div
|
||
el-color-picker(v-model="trustColor.untrusted" @change="updatetrustColor" size="mini" :predefine="['#CCCCCC']")
|
||
span.color-picker(slot="trigger" class="x-tag-untrusted") Visitor
|
||
div
|
||
el-color-picker(v-model="trustColor.basic" @change="updatetrustColor" size="mini" :predefine="['#1778ff']")
|
||
span.color-picker(slot="trigger" class="x-tag-basic") New User
|
||
div
|
||
el-color-picker(v-model="trustColor.known" @change="updatetrustColor" size="mini" :predefine="['#2bcf5c']")
|
||
span.color-picker(slot="trigger" class="x-tag-known") User
|
||
div
|
||
el-color-picker(v-model="trustColor.trusted" @change="updatetrustColor" size="mini" :predefine="['#ff7b42']")
|
||
span.color-picker(slot="trigger" class="x-tag-trusted") Known User
|
||
div
|
||
el-color-picker(v-model="trustColor.veteran" @change="updatetrustColor" size="mini" :predefine="['#b18fff', '#8143e6', '#ff69b4', '#b52626', '#ffd000', '#abcdef']")
|
||
span.color-picker(slot="trigger" class="x-tag-veteran") Trusted User
|
||
div
|
||
el-color-picker(v-model="trustColor.vip" @change="updatetrustColor" size="mini" :predefine="['#ff2626']")
|
||
span.color-picker(slot="trigger" class="x-tag-vip") VRChat Team
|
||
div
|
||
el-color-picker(v-model="trustColor.troll" @change="updatetrustColor" size="mini" :predefine="['#782f2f']")
|
||
span.color-picker(slot="trigger" class="x-tag-troll") Nuisance
|
||
el-tab-pane(label="Notifications")
|
||
div.options-container(style="margin-top:0")
|
||
span.header Notifications
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-chat-square" @click="showNotyFeedFiltersDialog") Notification Filters
|
||
span.sub-header SteamVR Notifications
|
||
div.options-container-item
|
||
span.name SteamVR Overlay
|
||
el-switch(v-model="openVR" @change="saveOpenVROption")
|
||
div.options-container-item
|
||
span.name Overlay Notifications
|
||
el-switch(v-model="overlayNotifications" @change="saveOpenVROption" :disabled="!openVR")
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-rank" @click="showNotificationPositionDialog" :disabled="!overlayNotifications || !openVR") Notification Position
|
||
div.options-container-item
|
||
span.name XSOverlay Notifications
|
||
el-switch(v-model="xsNotifications" @change="saveOpenVROption")
|
||
div.options-container-item
|
||
span.name User images (slower)
|
||
el-switch(v-model="imageNotifications" @change="saveOpenVROption")
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-time" @click="promptNotificationTimeout" :disabled="(!overlayNotifications || !openVR) && !xsNotifications") Notification Timeout
|
||
span.sub-header Desktop Notifications
|
||
div.options-container-item
|
||
span.name When to display:
|
||
br
|
||
el-radio-group(v-model="desktopToast" @change="saveOpenVROption" size="mini")
|
||
el-radio-button(label="Never")
|
||
el-radio-button(label="Desktop Mode")
|
||
el-radio-button(label="Inside VR")
|
||
el-radio-button(label="Outside VR")
|
||
el-radio-button(label="Game Closed")
|
||
el-radio-button(label="Game Running")
|
||
el-radio-button(label="Always")
|
||
br
|
||
span.sub-header Text-To-Speech Options
|
||
div.options-container-item
|
||
span.name Notification TTS, When to play:
|
||
br
|
||
el-radio-group(v-model="notificationTTS" @change="saveNotificationTTS" size="mini")
|
||
el-radio-button(label="Never")
|
||
el-radio-button(label="Inside VR")
|
||
el-radio-button(label="Game Closed")
|
||
el-radio-button(label="Game Running")
|
||
el-radio-button(label="Always")
|
||
div.options-container-item
|
||
span.name TTS Voice
|
||
el-dropdown(@command="(voice) => changeTTSVoice(voice)" trigger="click" size="small")
|
||
el-button(size="mini" :disabled="notificationTTS === 'Never'")
|
||
span {{ getTTSVoiceName() }} #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(v-if="voice" v-for="(voice, index) in TTSvoices" :key="index" v-text="voice.name" :command="index")
|
||
el-tab-pane(label="Wrist Overlay")
|
||
div.options-container(style="margin-top:0")
|
||
span.header SteamVR Wrist Overlay
|
||
div.options-container-item
|
||
span * It runs automatically when VRChat is running.
|
||
br
|
||
br
|
||
span Grip: Vive or Other Controllers Grab, Oculus X/A Buttons
|
||
br
|
||
span Menu: Vive Menu, Index B, Oculus Y/B Buttons
|
||
br
|
||
div.options-container-item
|
||
span.name SteamVR Overlay
|
||
el-switch(v-model="openVR" @change="saveOpenVROption")
|
||
div.options-container-item
|
||
span.name Wrist Feed Overlay
|
||
el-switch(v-model="overlayWrist" @change="saveOpenVROption" :disabled="!openVR")
|
||
div.options-container-item
|
||
span.name Hide Private Worlds
|
||
el-switch(v-model="hidePrivateFromFeed" @change="saveOpenVROption")
|
||
div.options-container-item(style="min-width:118px")
|
||
span.name Start Overlay With
|
||
el-switch(v-model="openVRAlways" @change="saveOpenVROption" inactive-text="VRChat" active-text="SteamVR" :disabled="!openVR")
|
||
div.options-container-item
|
||
span.name Overlay Button
|
||
el-switch(v-model="overlaybutton" @change="saveOpenVROption" inactive-text="Grip" active-text="Menu" :disabled="!openVR || !overlayWrist")
|
||
div.options-container-item
|
||
span.name Display Overlay On
|
||
el-radio-group(v-model="overlayHand" @change="saveOpenVROption" size="mini")
|
||
el-radio-button(label="1") Left Hand
|
||
el-radio-button(label="2") Right Hand
|
||
el-radio-button(label="0") Both Hands
|
||
div.options-container-item
|
||
span.name Background Colour
|
||
el-switch(v-model="vrBackgroundEnabled" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
|
||
div.options-container-item
|
||
span.name Minimal Feed Icons
|
||
el-switch(v-model="minimalFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
|
||
div.options-container-item
|
||
span.name Hide VR Devices
|
||
el-switch(v-model="hideDevicesFromFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
|
||
div.options-container-item
|
||
span.name Hide CPU Usage
|
||
el-switch(v-model="hideCpuUsageFromFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
|
||
div.options-container-item
|
||
span.name Hide Game Uptime
|
||
el-switch(v-model="hideUptimeFromFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
|
||
div.options-container-item
|
||
span.name Show PC Uptime
|
||
el-switch(v-model="pcUptimeOnFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-notebook-2" @click="showWristFeedFiltersDialog" :disabled="!openVR || !overlayWrist") Wrist Feed Filters
|
||
el-tab-pane(label="Discord Presence")
|
||
div.options-container(style="margin-top:0")
|
||
span.header Discord Presence
|
||
div.options-container-item
|
||
span * Only works when VRChat is running.
|
||
div.options-container-item
|
||
span.name Enable
|
||
el-tooltip(placement="top" style="margin-left:5px" content="Recommended to disable Rich Presence in VRChat config.json to stop it from conflicting")
|
||
i.el-icon-warning(style="cursor:pointer" @click="showVRChatConfig")
|
||
el-switch(v-model="discordActive" @change="saveDiscordOption")
|
||
div.options-container-item
|
||
span.name Instance type/player count
|
||
el-switch(v-model="discordInstance" @change="saveDiscordOption" :disabled="!discordActive")
|
||
div.options-container-item
|
||
span.name Join button (public only)
|
||
el-switch(v-model="discordJoinButton" @change="saveDiscordOption" :disabled="!discordActive")
|
||
div.options-container-item
|
||
span.name Hide world details in private
|
||
el-switch(v-model="discordHideInvite" @change="saveDiscordOption" :disabled="!discordActive")
|
||
div.options-container-item
|
||
span.name Hide world images
|
||
el-switch(v-model="discordHideImage" @change="saveDiscordOption" :disabled="!discordActive")
|
||
el-tab-pane(label="Advanced")
|
||
div.options-container(style="margin-top:0")
|
||
span.header Advanced
|
||
div.options-container-item
|
||
el-button-group
|
||
el-button(size="small" icon="el-icon-s-operation" @click="showVRChatConfig()") VRChat config.json
|
||
el-button(size="small" icon="el-icon-s-operation" @click="showLaunchOptions()") Launch Options
|
||
div.options-container
|
||
span.sub-header Pending Offline
|
||
div.options-container-item
|
||
span.name Delay before marking user as offline (fixes false positives)
|
||
el-button-group(style="display:block")
|
||
el-button(size="small" icon="el-icon-s-operation" @click="promptSetPendingOffline") Set Delay
|
||
span.sub-header Primary password
|
||
div.options-container-item
|
||
span.name(style="min-width:300px") Encrypt password (disables auto login)
|
||
el-switch(v-model="enablePrimaryPassword" @change="enablePrimaryPasswordChange" :disabled="!loginForm.savedCredentials[API.currentUser.username]")
|
||
span.sub-header VRChat Quit Fix
|
||
div.options-container-item
|
||
span.name(style="min-width:300px") Kill VRChat after exiting game
|
||
el-switch(v-model="vrcQuitFix" @change="saveOpenVROption")
|
||
span.sub-header Automatically Manage Cache When Closing VRChat
|
||
div.options-container-item
|
||
span.name(style="min-width:300px") Auto delete old versions from cache
|
||
el-switch(v-model="autoSweepVRChatCache" @change="saveOpenVROption")
|
||
div.options-container
|
||
span.header Remote Avatar Database
|
||
div.options-container-item
|
||
span.name Enable
|
||
el-switch(v-model="avatarRemoteDatabase" @change="saveOpenVROption")
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-user-solid" @click="showAvatarProviderDialog") Avatar Database Provider
|
||
div.options-container
|
||
span.header YouTube API
|
||
div.options-container-item
|
||
span.name Enabled
|
||
el-switch(v-model="youTubeApi" @change="changeYouTubeApi")
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-caret-right" @click="showYouTubeApiDialog") YouTube API Key
|
||
span.header Progress pie overlay for videos
|
||
div.options-container-item
|
||
span.name Enable
|
||
el-tooltip(placement="top" style="margin-left:5px" content="Requires SteamVR overlay to be enabled")
|
||
i.el-icon-warning
|
||
el-switch(v-model="progressPie" @change="changeYouTubeApi" :disabled="!openVR")
|
||
div.options-container-item
|
||
span.name Dance worlds only
|
||
el-switch(v-model="progressPieFilter" @change="changeYouTubeApi" :disabled="!openVR")
|
||
div.options-container(v-if="photonLoggingEnabled")
|
||
span.header Photon Logging Overlay
|
||
div.options-container-item
|
||
span.sub-header Photon Event HUD
|
||
div.options-container-item
|
||
span.name Enable
|
||
el-tooltip(placement="top" style="margin-left:5px" content="Requires SteamVR overlay to be enabled")
|
||
i.el-icon-warning
|
||
el-switch(v-model="photonEventOverlay" @change="saveEventOverlay" :disabled="!openVR")
|
||
div.options-container-item
|
||
span.name Filter
|
||
el-radio-group(v-model="photonEventOverlayFilter" @change="saveEventOverlay" size="mini" :disabled="!openVR || !photonEventOverlay")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-time" @click="promptPhotonOverlayMessageTimeout" :disabled="!openVR") Message Timeout
|
||
div.options-container-item
|
||
el-select(v-model="photonEventTableTypeOverlayFilter" @change="photonEventTableFilterChange" multiple clearable collapse-tags style="flex:1" placeholder="Filter")
|
||
el-option(v-once v-for="type in photonEventTableTypeFilterList" :key="type" :label="type" :value="type")
|
||
br
|
||
span.sub-header User timeout HUD
|
||
div.options-container-item
|
||
span.name Enable
|
||
el-tooltip(placement="top" style="margin-left:5px" content="Requires SteamVR overlay to be enabled")
|
||
i.el-icon-warning
|
||
el-switch(v-model="timeoutHudOverlay" @change="saveEventOverlay" :disabled="!openVR")
|
||
div.options-container-item
|
||
span.name Filter
|
||
el-radio-group(v-model="timeoutHudOverlayFilter" @change="saveEventOverlay" size="mini" :disabled="!openVR || !timeoutHudOverlay")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-time" @click="promptPhotonLobbyTimeoutThreshold" :disabled="!openVR") Timeout Threshold
|
||
div.options-container
|
||
span.header VRCX Instance Cache/Debug
|
||
div.options-container-item
|
||
span.name Disable GameLog
|
||
el-switch(v-model="gameLogDisabled" @change="disableGameLogDialog")
|
||
span.name(style="margin-left:15px") (will likely break things)
|
||
div.options-container-item
|
||
span.name User cache: #[span(v-text="API.cachedUsers.size")]
|
||
div.options-container-item
|
||
span.name World cache: #[span(v-text="API.cachedWorlds.size")]
|
||
div.options-container-item
|
||
span.name Avatar cache: #[span(v-text="API.cachedAvatars.size")]
|
||
div.options-container-item
|
||
span.name Avatar Name cache: #[span(v-text="API.cachedAvatarNames.size")]
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-delete-solid" @click="clearVRCXCache") Clear Cache
|
||
el-button(size="small" icon="el-icon-time" @click="promptAutoClearVRCXCacheFrequency") Auto Clear Cache
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-download" @click="showDownloadDialog") Download History
|
||
el-button(size="small" icon="el-icon-tickets" @click="showConsole") Show Console
|
||
div.options-container
|
||
span.sub-header SQLite Table Size
|
||
div.options-container-item
|
||
el-button(size="small" icon="el-icon-refresh" @click="getSqliteTableSizes") Refresh
|
||
div.options-container-item
|
||
span.name GPS: #[span(v-text="sqliteTableSizes.gps")]
|
||
div.options-container-item
|
||
span.name Status: #[span(v-text="sqliteTableSizes.status")]
|
||
div.options-container-item
|
||
span.name Bio: #[span(v-text="sqliteTableSizes.bio")]
|
||
div.options-container-item
|
||
span.name Avatar: #[span(v-text="sqliteTableSizes.avatar")]
|
||
div.options-container-item
|
||
span.name Online/Offline: #[span(v-text="sqliteTableSizes.onlineOffline")]
|
||
div.options-container-item
|
||
span.name Friend Log History: #[span(v-text="sqliteTableSizes.friendLogHistory")]
|
||
div.options-container-item
|
||
span.name Notifications: #[span(v-text="sqliteTableSizes.notification")]
|
||
div.options-container-item
|
||
span.name Location: #[span(v-text="sqliteTableSizes.location")]
|
||
div.options-container-item
|
||
span.name Join/Leave: #[span(v-text="sqliteTableSizes.joinLeave")]
|
||
div.options-container-item
|
||
span.name Portal Spawn: #[span(v-text="sqliteTableSizes.portalSpawn")]
|
||
div.options-container-item
|
||
span.name Video Play: #[span(v-text="sqliteTableSizes.videoPlay")]
|
||
div.options-container-item
|
||
span.name Event: #[span(v-text="sqliteTableSizes.event")]
|
||
|
||
//- friends
|
||
.x-aside-container(v-show="$refs.menu && $refs.menu.activeIndex !== 'friendsList'" id="aside")
|
||
div(style="display:flex;align-items:baseline")
|
||
el-select(v-model="quickSearch" clearable placeholder="Search" filterable remote :remote-method="quickSearchRemoteMethod" popper-class="x-quick-search" @change="quickSearchChange" @visible-change="quickSearchVisibleChange" style="flex:1;padding:10px")
|
||
el-option(v-for="item in quickSearchItems" :key="item.value" :value="item.value" :label="item.label")
|
||
.x-friend-item
|
||
template(v-if="item.ref")
|
||
.detail
|
||
span.name(v-text="item.ref.displayName" :style="{'color':item.ref.$userColour}")
|
||
span.extra(v-if="item.ref.state === 'offline'") Offline
|
||
span.extra(v-else-if="item.ref.state === 'active'") Active
|
||
location.extra(v-else :location="item.ref.location" :traveling="item.ref.travelingToLocation" :link="false")
|
||
img.avatar(v-lazy="userImage(item.ref)")
|
||
span(v-else) Search More: #[span(v-text="item.label" style="font-weight:bold")]
|
||
el-tooltip(placement="bottom" content="Direct access ID/URL from clipboard" :disabled="hideTooltips")
|
||
el-button(type="default" @click="directAccessPaste" size="mini" icon="el-icon-discover" circle)
|
||
el-tooltip(placement="bottom" content="Refresh friends" :disabled="hideTooltips")
|
||
el-button(type="default" @click="API.closeWebSocket(); API.getCurrentUser(); API.refreshFriends()" :loading="API.isRefreshFriendsLoading" size="mini" icon="el-icon-refresh" circle style="margin-right:10px")
|
||
.x-friend-list(style="padding-bottom:10px")
|
||
.x-friend-group(style="padding:5px 0 0")
|
||
span FRIENDS―{{ onlineFriendCount }}/{{ friends.size }}
|
||
.x-friend-group(style="padding:10px 0 5px")
|
||
i.el-icon-arrow-right(:class="{ rotate: isFriendsGroupMe }")
|
||
span.x-link(@click="isFriendsGroupMe = !isFriendsGroupMe" style="margin-left:5px") ME
|
||
div(v-show="isFriendsGroupMe")
|
||
.x-friend-item(:key="API.currentUser.id" @click="showUserDialog(API.currentUser.id)")
|
||
.avatar(:class="userStatusClass(API.currentUser)")
|
||
img(v-lazy="userImage(API.currentUser)")
|
||
.detail
|
||
span.name(v-text="API.currentUser.displayName" :style="{'color':API.currentUser.$userColour}")
|
||
location.extra(v-if="isGameRunning === true" :location="lastLocation.location" :traveling="lastLocationDestination" :link="false")
|
||
span.extra(v-else v-text="API.currentUser.statusDescription" :link="false")
|
||
.x-friend-group(v-show="friendsGroup0.length")
|
||
i.el-icon-arrow-right(:class="{ rotate: isFriendsGroup0 }")
|
||
span.x-link(@click="isFriendsGroup0 = !isFriendsGroup0" style="margin-left:5px") VIP―{{ friendsGroup0.length }}
|
||
div(v-show="isFriendsGroup0")
|
||
.x-friend-item(v-for="friend in friendsGroup0" :key="friend.id" @click="showUserDialog(friend.id)")
|
||
template(v-if="friend.ref")
|
||
.avatar(:class="userStatusClass(friend.ref, friend.pendingOffline)")
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-if="!hideUserMemos && friend.$nickName" :style="{'color':friend.ref.$userColour}") {{ friend.ref.displayName }} ({{ friend.$nickName }})
|
||
span.name(v-else v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span.extra(v-if="friend.pendingOffline") #[i.el-icon-warning-outline] Pending Offline
|
||
location.extra(v-else :location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false")
|
||
template(v-else)
|
||
span(v-text="friend.name || friend.id")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="confirmDeleteFriend(friend.id)" style="margin-left:5px")
|
||
.x-friend-group(v-show="friendsGroup1.length")
|
||
i.el-icon-arrow-right(:class="{ rotate: isFriendsGroup1 }")
|
||
span.x-link(@click="isFriendsGroup1 = !isFriendsGroup1" style="margin-left:5px") ONLINE―{{ friendsGroup1.length }}
|
||
div(v-show="isFriendsGroup1")
|
||
.x-friend-item(v-for="friend in friendsGroup1" :key="friend.id" @click="showUserDialog(friend.id)")
|
||
template(v-if="friend.ref")
|
||
.avatar(:class="userStatusClass(friend.ref, friend.pendingOffline)")
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-if="!hideUserMemos && friend.$nickName" :style="{'color':friend.ref.$userColour}") {{ friend.ref.displayName }} ({{ friend.$nickName }})
|
||
span.name(v-else v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span.extra(v-if="friend.pendingOffline") #[i.el-icon-warning-outline] Pending Offline
|
||
location.extra(v-else :location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false")
|
||
template(v-else)
|
||
span(v-text="friend.name || friend.id")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="confirmDeleteFriend(friend.id)" style="margin-left:5px")
|
||
.x-friend-group(v-show="friendsGroup2.length")
|
||
i.el-icon-arrow-right(:class="{ rotate: isFriendsGroup2 }")
|
||
span.x-link(@click="isFriendsGroup2 = !isFriendsGroup2" style="margin-left:5px") ACTIVE―{{ friendsGroup2.length }}
|
||
div(v-show="isFriendsGroup2")
|
||
.x-friend-item(v-for="friend in friendsGroup2" :key="friend.id" @click="showUserDialog(friend.id)")
|
||
template(v-if="friend.ref")
|
||
.avatar
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-if="!hideUserMemos && friend.$nickName" :style="{'color':friend.ref.$userColour}") {{ friend.ref.displayName }} ({{ friend.$nickName }})
|
||
span.name(v-else v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span.extra(v-text="friend.ref.statusDescription" :link="false")
|
||
template(v-else)
|
||
span(v-text="friend.name || friend.id")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="confirmDeleteFriend(friend.id)" style="margin-left:5px")
|
||
.x-friend-group(v-show="friendsGroup3.length")
|
||
i.el-icon-arrow-right(:class="{ rotate: isFriendsGroup3 }")
|
||
span.x-link(@click="isFriendsGroup3 = !isFriendsGroup3" style="margin-left:5px") OFFLINE―{{ friendsGroup3.length }}
|
||
div(v-show="isFriendsGroup3")
|
||
.x-friend-item(v-for="friend in friendsGroup3" :key="friend.id" @click="showUserDialog(friend.id)")
|
||
template(v-if="friend.ref")
|
||
.avatar
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-if="!hideUserMemos && friend.$nickName" :style="{'color':friend.ref.$userColour}") {{ friend.ref.displayName }} ({{ friend.$nickName }})
|
||
span.name(v-else v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span.extra(v-text="friend.ref.statusDescription")
|
||
template(v-else)
|
||
span(v-text="friend.name || friend.id")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="confirmDeleteFriend(friend.id)" style="margin-left:5px")
|
||
|
||
//- dialog: user
|
||
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")
|
||
div(v-loading="userDialog.loading")
|
||
div(style="display:flex")
|
||
el-popover(v-if="userDialog.ref.profilePicOverride" placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="userDialog.ref.profilePicOverride" style="flex:none;height:120px;width:213.33px;border-radius:4px;object-fit:cover")
|
||
img.x-link(v-lazy="userDialog.ref.profilePicOverride" style="height:400px" @click="downloadAndSaveImage(userDialog.ref.profilePicOverride)")
|
||
el-popover(v-else placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="userDialog.ref.currentAvatarThumbnailImageUrl" style="flex:none;height:120px;width:160px;border-radius:4px;object-fit:cover")
|
||
img.x-link(v-lazy="userDialog.ref.currentAvatarImageUrl" style="height:500px" @click="downloadAndSaveImage(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'") Active
|
||
span(v-else-if="userDialog.ref.location === 'offline'") Offline
|
||
span(v-else-if="userDialog.ref.status === 'active'") Online
|
||
span(v-else-if="userDialog.ref.status === 'join me'") Join Me
|
||
span(v-else-if="userDialog.ref.status === 'ask me'") Ask Me
|
||
span(v-else-if="userDialog.ref.status === 'busy'") Do Not Disturb
|
||
span(v-else) Offline
|
||
i.x-user-status(:class="userStatusClass(userDialog.ref)")
|
||
template(v-if="userDialog.previousDisplayNames.length > 0")
|
||
el-tooltip(placement="bottom")
|
||
template(#content)
|
||
span Previous Display Names:
|
||
div(v-for="displayName in userDialog.previousDisplayNames" placement="top")
|
||
span(v-text="displayName")
|
||
i.el-icon-caret-bottom
|
||
span.dialog-title(v-text="userDialog.ref.displayName" style="margin-left:5px;margin-right:5px")
|
||
template(v-if="userDialog.ref.id === API.currentUser.id")
|
||
el-popover(placement="top" trigger="click")
|
||
span(slot="reference" v-text="API.currentUser.username" style="margin-right:5px;color:#909399;font-family:monospace;font-size:12px;cursor:pointer")
|
||
span(style="display:block;text-align:center;font-family:monospace") {{ API.currentUser.username | textToHex }}
|
||
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")
|
||
div
|
||
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") Friend No.{{userDialog.friend.no}}
|
||
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-vip(v-if="userDialog.ref.$isModerator" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") VRChat Team
|
||
el-tag.x-tag-vrcplus(v-if="userDialog.ref.$isVRCPlus" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") VRC+
|
||
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") Quest
|
||
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" v-lazy="userDialog.ref.userIcon" style="flex:none;width:120px;height:120px;border-radius:4px;object-fit:cover")
|
||
img.x-link(v-lazy="userDialog.ref.userIcon" style="height:500px" @click="downloadAndSaveImage(userDialog.ref.userIcon)")
|
||
div(style="flex:none")
|
||
template(v-if="API.currentUser.id !== userDialog.ref.id")
|
||
el-tooltip(v-if="userDialog.isFavorite" placement="top" content="Remove from favorites" :disabled="hideTooltips")
|
||
el-button(@click="userDialogCommand('Delete Favorite')" type="warning" icon="el-icon-star-on" circle)
|
||
el-tooltip(v-else placement="top" content="Add to favorites" :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 || userDialog.isShowAvatar) ? 'success' : (userDialog.isBlock || userDialog.isMute || userDialog.isHideAvatar) ? '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") Refresh
|
||
el-dropdown-item(icon="el-icon-s-order" command="Copy User") Copy User URL
|
||
template(v-if="userDialog.ref.id === API.currentUser.id")
|
||
el-dropdown-item(icon="el-icon-picture-outline" command="Manage Gallery" divided) Manage Gallery/Icons
|
||
el-dropdown-item(icon="el-icon-s-custom" command="Show Avatar Author") Show Avatar Author
|
||
el-dropdown-item(icon="el-icon-s-custom" command="Show Fallback Avatar Details") Show Fallback Avatar Details
|
||
el-dropdown-item(icon="el-icon-edit" command="Edit Social Status" divided) Social Status
|
||
el-dropdown-item(icon="el-icon-edit" command="Edit Language") Language
|
||
el-dropdown-item(icon="el-icon-edit" command="Edit Bio") Bio
|
||
el-dropdown-item(icon="el-icon-switch-button" command="Logout" divided) Logout
|
||
template(v-else)
|
||
template(v-if="userDialog.isFriend")
|
||
el-dropdown-item(icon="el-icon-postcard" command="Request Invite" divided) Request Invite
|
||
el-dropdown-item(icon="el-icon-postcard" command="Request Invite Message") Request Invite With Message
|
||
template(v-if="lastLocation.location && isGameRunning && checkCanInvite(lastLocation.location)")
|
||
el-dropdown-item(icon="el-icon-message" command="Invite") Invite
|
||
el-dropdown-item(icon="el-icon-message" command="Invite Message") Invite With Message
|
||
template(v-else-if="userDialog.incomingRequest")
|
||
el-dropdown-item(icon="el-icon-check" command="Accept Friend Request") Accept Friend Request
|
||
el-dropdown-item(icon="el-icon-close" command="Decline Friend Request") Decline Friend Request
|
||
el-dropdown-item(v-else-if="userDialog.outgoingRequest" icon="el-icon-close" command="Cancel Friend Request") Cancel Friend Request
|
||
el-dropdown-item(v-else icon="el-icon-plus" command="Send Friend Request") Send Friend Request
|
||
el-dropdown-item(icon="el-icon-message" command="Invite To Group") Invite To Group
|
||
el-dropdown-item(icon="el-icon-s-custom" command="Show Avatar Author" divided) Show Avatar Author
|
||
el-dropdown-item(icon="el-icon-s-custom" command="Show Fallback Avatar Details") Show Fallback Avatar Details
|
||
el-dropdown-item(icon="el-icon-tickets" command="Previous Instances") Show Previous Instances
|
||
el-dropdown-item(v-if="userDialog.ref.currentAvatarImageUrl" icon="el-icon-picture-outline" command="Previous Images") Show Avatar Previous Images
|
||
el-dropdown-item(v-if="userDialog.isBlock" icon="el-icon-circle-check" command="Unblock" divided style="color:#F56C6C") Unblock
|
||
el-dropdown-item(v-else icon="el-icon-circle-close" command="Block" divided :disabled="userDialog.ref.$isModerator") Block
|
||
el-dropdown-item(v-if="userDialog.isMute" icon="el-icon-microphone" command="Unmute" style="color:#F56C6C") Unmute
|
||
el-dropdown-item(v-else icon="el-icon-turn-off-microphone" command="Mute" :disabled="userDialog.ref.$isModerator") Mute
|
||
el-dropdown-item(icon="el-icon-user-solid" command="Show Avatar") #[i.el-icon-check.el-icon--left(v-if="userDialog.isShowAvatar")]Show Avatar
|
||
el-dropdown-item(icon="el-icon-user" command="Hide Avatar") #[i.el-icon-check.el-icon--left(v-if="userDialog.isHideAvatar")]Hide Avatar
|
||
el-dropdown-item(v-if="userDialog.isInteractOff" icon="el-icon-thumb" command="Enable Avatar Interaction" style="color:#F56C6C") Enable Avatar Interaction
|
||
el-dropdown-item(v-else icon="el-icon-circle-close" command="Disable Avatar Interaction") Disable Avatar Interaction
|
||
template(v-if="userDialog.isFriend")
|
||
el-dropdown-item(icon="el-icon-delete" command="Unfriend" divided style="color:#F56C6C") Unfriend
|
||
el-tabs(ref="userDialogTabs" @tab-click="userDialogTabClick")
|
||
el-tab-pane(label="Info")
|
||
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")
|
||
location(:location="userDialog.ref.location" :traveling="userDialog.ref.travelingToLocation")
|
||
template(v-if="isRealInstance(userDialog.$location.tag)")
|
||
el-tooltip(placement="top" content="Launch/Invite" :disabled="hideTooltips")
|
||
launch(:location="userDialog.$location.tag" style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Invite yourself" :disabled="hideTooltips")
|
||
invite-yourself(:location="userDialog.$location.tag" :shortname="userDialog.$location.shortName" style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Refresh player count" :disabled="hideTooltips")
|
||
el-button(v-if="userDialog.$location.tag !== lastLocation.location" @click="refreshInstancePlayerCount(userDialog.$location.tag)" size="mini" icon="el-icon-refresh" style="margin-left:5px" circle)
|
||
span(v-if="userDialog.instance.occupants" style="margin-left:5px") {{ userDialog.instance.occupants }} #[template(v-if="userDialog.instance.friendCount > 0") ({{ userDialog.instance.friendCount }})]
|
||
.x-friend-list(style="flex:1;margin-top:10px;max-height:150px")
|
||
.x-friend-item(v-if="userDialog.$location.userId" @click="showUserDialog(userDialog.$location.userId)" class="x-friend-item-border")
|
||
template(v-if="userDialog.$location.user")
|
||
.avatar(:class="userStatusClass(userDialog.$location.user)")
|
||
img(v-lazy="userImage(userDialog.$location.user)")
|
||
.detail
|
||
span.name(v-text="userDialog.$location.user.displayName" :style="{'color':userDialog.$location.user.$userColour}")
|
||
span.extra Instance Creator
|
||
span(v-else v-text="userDialog.$location.userId")
|
||
.x-friend-item(v-for="user in userDialog.users" :key="user.id" @click="showUserDialog(user.id)" class="x-friend-item-border")
|
||
.avatar(:class="userStatusClass(user)")
|
||
img(v-lazy="userImage(user)")
|
||
.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 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="Click to add a note" 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 Memo
|
||
el-input.extra(v-model="userDialog.memo" type="textarea" :rows="2" :autosize="{ minRows: 1, maxRows: 20 }" placeholder="Click to add a memo" 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") Avatar Info Last Seen
|
||
span.name(v-else) Avatar Info
|
||
.extra
|
||
avatar-info(:imageurl="userDialog.ref.currentAvatarImageUrl" :userid="userDialog.id")
|
||
.x-friend-item(style="width:100%;cursor:default")
|
||
.detail
|
||
span.name Represented Group
|
||
.extra(v-if="userDialog.representedGroup.isRepresenting")
|
||
div(style="display:inline-block;flex:none;margin-right:5px")
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="userDialog.representedGroup.iconUrl" style="flex:none;width:60px;height:60px;border-radius:4px;object-fit:cover")
|
||
img.x-link(v-lazy="userDialog.representedGroup.iconUrl" style="height:500px" @click="downloadAndSaveImage(userDialog.representedGroup.iconUrl)")
|
||
span(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 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-if="link" v-for="(link, index) in userDialog.ref.bioLinks" :key="index")
|
||
template(#content)
|
||
span(v-text="link")
|
||
img(:src="getFaviconUrl(link)" 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 Last Seen
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
i.el-icon-warning
|
||
span.extra {{ userDialog.lastSeen | formatDate('long') }}
|
||
.x-friend-item(@click="showPreviousInstancesUserDialog(userDialog.ref)")
|
||
.detail
|
||
span.name Join Count
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
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 Time Together
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
i.el-icon-warning
|
||
span.extra(v-if="userDialog.timeSpent === 0") -
|
||
span.extra(v-else) {{ userDialog.timeSpent | timeToText }}
|
||
.x-friend-item(style="cursor:default")
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span {{ userOnlineForTimestamp(userDialog) | formatDate('short') }}
|
||
.detail
|
||
span.name(v-if="userDialog.ref.state === 'online' && userDialog.ref.$online_for") Online For
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
i.el-icon-warning
|
||
span.name(v-else) Offline For
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
i.el-icon-warning
|
||
span.extra {{ userOnlineFor(userDialog) | timeToText }}
|
||
.x-friend-item(style="cursor:default")
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span Last Login {{ userDialog.ref.last_login | formatDate('short') }}
|
||
.detail
|
||
span.name Last Activity
|
||
span.extra {{ userDialog.ref.last_activity | formatDate('long') }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Date Joined
|
||
span.extra(v-text="userDialog.ref.date_joined")
|
||
.x-friend-item(v-if="API.currentUser.id !== userDialog.id" style="cursor:default")
|
||
.detail
|
||
span.name(v-if="userDialog.unFriended") Unfriended
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
i.el-icon-warning
|
||
span.name(v-else) Friended
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
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 Avatar Cloning
|
||
span.extra(v-if="userDialog.ref.allowAvatarCopying" style="color:#67C23A") Allow
|
||
span.extra(v-else style="color:#F56C6C") Deny
|
||
template(v-else)
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Avatar Cloning
|
||
span.extra(v-if="userDialog.ref.allowAvatarCopying" style="color:#67C23A") Allow
|
||
span.extra(v-else style="color:#F56C6C") 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 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")
|
||
el-tab-pane(label="Groups")
|
||
el-button(type="default" :loading="userDialog.isGroupsLoading" @click="getUserGroups(userDialog.id)" size="mini" icon="el-icon-refresh" circle)
|
||
span(style="margin-left:5px") Total {{ userGroups.groups.length }}
|
||
div(v-loading="userDialog.isGroupsLoading" style="margin-top:10px")
|
||
template(v-if="userGroups.ownGroups.length > 0")
|
||
span(style="font-weight:bold;font-size:16px") Own Groups
|
||
span(style="color:#909399;font-size:12px;margin-left:5px") {{ userGroups.ownGroups.length }}
|
||
.x-friend-list(style="margin-top:10px;margin-bottom:15px;min-height:60px")
|
||
.x-friend-item(v-for="group in userGroups.ownGroups" :key="group.id" @click="showGroupDialog(group.id)" class="x-friend-item-border")
|
||
.avatar
|
||
img(v-lazy="group.iconUrl")
|
||
.detail
|
||
span.name(v-text="group.name")
|
||
span.extra ({{ group.memberCount }})
|
||
template(v-if="userGroups.mutualGroups.length > 0")
|
||
span(style="font-weight:bold;font-size:16px") 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(v-for="group in userGroups.mutualGroups" :key="group.id" @click="showGroupDialog(group.id)" class="x-friend-item-border")
|
||
.avatar
|
||
img(v-lazy="group.iconUrl")
|
||
.detail
|
||
span.name(v-text="group.name")
|
||
span.extra ({{ group.memberCount }})
|
||
template(v-if="userGroups.remainingGroups.length > 0")
|
||
span(style="font-weight:bold;font-size:16px") Groups
|
||
span(style="color:#909399;font-size:12px;margin-left:5px") {{ userGroups.remainingGroups.length }}
|
||
.x-friend-list(style="margin-top:10px;margin-bottom:15px;min-height:60px")
|
||
.x-friend-item(v-for="group in userGroups.remainingGroups" :key="group.id" @click="showGroupDialog(group.id)" class="x-friend-item-border")
|
||
.avatar
|
||
img(v-lazy="group.iconUrl")
|
||
.detail
|
||
span.name(v-text="group.name")
|
||
span.extra ({{ group.memberCount }})
|
||
el-tab-pane(label="Worlds")
|
||
el-button(type="default" :loading="userDialog.isWorldsLoading" @click="refreshUserDialogWorlds()" size="mini" icon="el-icon-refresh" circle)
|
||
span(style="margin-left:5px") Total {{ userDialog.worlds.length }}
|
||
el-radio-group(v-model="userDialog.worldSorting" size="mini" style="margin-left:30px" @change="changeUserDialogWorldSorting")
|
||
el-radio(label="name") by name
|
||
el-radio(label="update") by update
|
||
.x-friend-list(v-loading="userDialog.isWorldsLoading" style="margin-top:10px;min-height:60px")
|
||
.x-friend-item(v-for="world in userDialog.worlds" :key="world.id" @click="showWorldDialog(world.id)" class="x-friend-item-border")
|
||
.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="Favorite Worlds")
|
||
el-button(type="default" :loading="userDialog.isFavoriteWorldsLoading" @click="getUserFavoriteWorlds(userDialog.id)" size="mini" icon="el-icon-refresh" circle)
|
||
el-tabs(type="card" v-loading="userDialog.isFavoriteWorldsLoading" style="margin-top:10px")
|
||
template(v-for="(list, index) in userFavoriteWorlds" v-if="list")
|
||
el-tab-pane
|
||
span(slot="label")
|
||
span(v-text="list[0]" style="font-weight:bold;font-size:16px")
|
||
i.x-user-status(style="margin-left:5px" :class="userFavoriteWorldsStatus(list[1])")
|
||
span(style="color:#909399;font-size:12px;margin-left:5px") {{ list[2].length }}/{{ API.favoriteLimits.maxFavoritesPerGroup.world }}
|
||
.x-friend-list(style="margin-top:10px;margin-bottom:15px;min-height:60px")
|
||
.x-friend-item(v-for="world in list[2]" :key="world.id" @click="showWorldDialog(world.id)" class="x-friend-item-border")
|
||
.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="Avatars")
|
||
template(v-if="userDialog.ref.id === API.currentUser.id")
|
||
el-button(type="default" :loading="userDialog.isAvatarsLoading" @click="refreshUserDialogAvatars()" size="mini" icon="el-icon-refresh" circle)
|
||
span(style="margin-left:5px") Total {{ userDialogAvatars.length }}
|
||
el-radio-group(v-if="userDialog.ref.id === API.currentUser.id" v-model="userDialog.avatarSorting" size="mini" style="margin-left:30px;margin-right:30px" @change="changeUserDialogAvatarSorting")
|
||
el-radio(label="name") by name
|
||
el-radio(label="update") by update
|
||
el-radio-group(v-if="userDialog.ref.id === API.currentUser.id" v-model="userDialog.avatarReleaseStatus" size="mini" style="margin-left:30px")
|
||
el-radio(label="all") all
|
||
el-radio(label="public") public
|
||
el-radio(label="private") private
|
||
.x-friend-list(style="margin-top:10px;min-height:60px")
|
||
.x-friend-item(v-for="avatar in userDialogAvatars" @click="showAvatarDialog(avatar.id)" class="x-friend-item-border")
|
||
.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="JSON")
|
||
el-button(type="default" @click="refreshUserDialogTreeData()" size="mini" icon="el-icon-refresh" circle)
|
||
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")
|
||
|
||
//- dialog: world
|
||
el-dialog.x-dialog.x-world-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="worldDialog" :visible.sync="worldDialog.visible" :show-close="false" width="770px")
|
||
div(v-loading="worldDialog.loading")
|
||
div(style="display:flex")
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="worldDialog.ref.thumbnailImageUrl" style="flex:none;width:160px;height:120px;border-radius:4px")
|
||
img.x-link(v-lazy="worldDialog.ref.imageUrl" style="width:500px;height:375px" @click="downloadAndSaveImage(worldDialog.ref.imageUrl)")
|
||
div(style="flex:1;display:flex;align-items:center;margin-left:15px")
|
||
div(style="flex:1")
|
||
div
|
||
i.el-icon-s-home(v-show="API.currentUser.$homeLocation && API.currentUser.$homeLocation.worldId === worldDialog.id" style="margin-right:5px")
|
||
span.dialog-title(v-text="worldDialog.ref.name")
|
||
div(style="margin-top:5px")
|
||
span.x-link(v-text="worldDialog.ref.authorName" @click="showUserDialog(worldDialog.ref.authorId)" style="color:#909399;font-family:monospace")
|
||
div
|
||
el-tag(v-if="worldDialog.ref.$isLabs" type="primary" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Labs
|
||
el-tag(v-else-if="worldDialog.ref.releaseStatus === 'public'" type="success" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Public
|
||
el-tag(v-else type="danger" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Private
|
||
el-tag.x-tag-platform-pc(v-if="worldDialog.isPC" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") PC
|
||
el-tag.x-tag-platform-quest(v-if="worldDialog.isQuest" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Quest
|
||
el-tag(type="info" effect="plain" size="mini" v-text="worldDialog.fileSize" style="margin-right:5px;margin-top:5px")
|
||
el-tag(v-if="worldDialog.inCache" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px")
|
||
span(v-text="worldDialog.cacheSize")
|
||
| Cache
|
||
div(style="margin-top:5px")
|
||
span(v-show="worldDialog.ref.name !== worldDialog.ref.description" v-text="worldDialog.ref.description" style="font-size:12px")
|
||
div(style="flex:none;margin-left:10px")
|
||
el-tooltip(v-if="worldDialog.inCache" placement="top" content="Delete world from cache" :disabled="hideTooltips")
|
||
el-button(icon="el-icon-delete" circle @click="deleteVRChatCache(worldDialog.ref)" :disabled="isGameRunning && worldDialog.cacheLocked")
|
||
el-tooltip(v-if="worldDialog.isFavorite" placement="top" content="Favorite/Unfavorite" :disabled="hideTooltips")
|
||
el-button(type="default" icon="el-icon-star-on" circle @click="worldDialogCommand('Add Favorite')" style="margin-left:5px")
|
||
el-tooltip(v-else placement="top" content="Favorite/Unfavorite" :disabled="hideTooltips")
|
||
el-button(type="default" icon="el-icon-star-off" circle @click="worldDialogCommand('Add Favorite')" style="margin-left:5px")
|
||
el-dropdown(trigger="click" @command="worldDialogCommand" size="small" style="margin-left:5px")
|
||
el-button(type="default" icon="el-icon-more" circle)
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(icon="el-icon-refresh" command="Refresh") Refresh
|
||
el-dropdown-item(icon="el-icon-s-flag" command="New Instance" divided) New Instance
|
||
el-dropdown-item(v-if="API.currentUser.$homeLocation && API.currentUser.$homeLocation.worldId === worldDialog.id" icon="el-icon-magic-stick" command="Reset Home" divided) Reset Home
|
||
el-dropdown-item(v-else icon="el-icon-s-home" command="Make Home" divided) Make Home
|
||
el-dropdown-item(icon="el-icon-tickets" command="Previous Instances") Show Previous Instances
|
||
template(v-if="API.currentUser.id !== worldDialog.ref.authorId")
|
||
el-dropdown-item(icon="el-icon-picture-outline" command="Previous Images") Show Previous Images
|
||
template(v-else)
|
||
el-dropdown-item(icon="el-icon-edit" command="Rename") Rename
|
||
el-dropdown-item(icon="el-icon-edit" command="Change Description") Change Description
|
||
el-dropdown-item(icon="el-icon-edit" command="Change Capacity") Change Capacity
|
||
el-dropdown-item(icon="el-icon-edit" command="Change YouTube Preview") Change YouTube Preview
|
||
el-dropdown-item(icon="el-icon-edit" command="Change Tags") Change Tags
|
||
el-dropdown-item(icon="el-icon-picture-outline" command="Change Image") Change Image
|
||
el-dropdown-item(v-if="worldDialog.ref.unityPackageUrl" icon="el-icon-download" command="Download Unity Package") Download Unity Package
|
||
el-dropdown-item(v-if="worldDialog.ref.tags.includes('system_approved') || worldDialog.ref.tags.includes('system_labs')" icon="el-icon-view" command="Unpublish" divided) Unpublish
|
||
el-dropdown-item(v-else icon="el-icon-view" command="Publish" divided) Publish To Labs
|
||
el-dropdown-item(icon="el-icon-delete" command="Delete" style="color:#F56C6C") Delete
|
||
el-tabs
|
||
el-tab-pane(label="Instances")
|
||
div.
|
||
#[i.el-icon-user] Public {{ worldDialog.ref.publicOccupants | commaNumber }}
|
||
#[i.el-icon-user-solid(style="margin-left:10px")] Private {{ worldDialog.ref.privateOccupants | commaNumber }}
|
||
#[i.el-icon-check(style="margin-left:10px")] Capacity {{ worldDialog.ref.capacity | commaNumber }} ({{ worldDialog.ref.capacity * 2 | commaNumber }})
|
||
div(v-for="room in worldDialog.rooms" :key="room.id")
|
||
div(style="margin:5px 0")
|
||
location-world(:locationobject="room.$location" :currentuserid="API.currentUser.id" :worlddialogshortname="worldDialog.$location.shortName")
|
||
el-tooltip(placement="top" content="Invite yourself" :disabled="hideTooltips")
|
||
invite-yourself(:location="room.$location.tag" :shortname="room.$location.shortName" style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Refresh player count" :disabled="hideTooltips")
|
||
el-button(v-if="room.$location.tag !== lastLocation.location" @click="refreshInstancePlayerCount(room.$location.tag)" size="mini" icon="el-icon-refresh" style="margin-left:5px" circle)
|
||
span(v-if="room.occupants" style="margin-left:5px") {{ room.occupants }} #[template(v-if="room.friendCount > 0") ({{ room.friendCount }})]
|
||
.x-friend-list(style="margin:10px 0;max-height:unset" v-if="room.$location.userId || room.users.length")
|
||
.x-friend-item(v-if="room.$location.userId" @click="showUserDialog(room.$location.userId)" class="x-friend-item-border")
|
||
template(v-if="room.$location.user")
|
||
.avatar(:class="userStatusClass(room.$location.user)")
|
||
img(v-lazy="userImage(room.$location.user)")
|
||
.detail
|
||
span.name(v-text="room.$location.user.displayName" :style="{'color':room.$location.user.$userColour}")
|
||
span.extra Instance Creator
|
||
span(v-else v-text="room.$location.userId")
|
||
.x-friend-item(v-for="user in room.users" :key="user.id" @click="showUserDialog(user.id)" class="x-friend-item-border")
|
||
.avatar(:class="userStatusClass(user)")
|
||
img(v-lazy="userImage(user)")
|
||
.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")
|
||
el-tab-pane(label="Info")
|
||
.x-friend-list(style="max-height:none")
|
||
div(style="width:100%;display:flex")
|
||
.x-friend-item(style="width:350px;cursor:default")
|
||
.detail
|
||
span.name World ID
|
||
span.extra {{ worldDialog.id }}
|
||
el-tooltip(placement="top" content="Copy to clipboard" :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="copyWorldId(worldDialog.id)") Copy ID
|
||
el-dropdown-item(@click.native="copyWorldUrl(worldDialog.id)") Copy URL
|
||
.x-friend-item(v-if="worldDialog.ref.previewYoutubeId" style="width:350px" @click="openExternalLink(`https://www.youtube.com/watch?v=${worldDialog.ref.previewYoutubeId}`)")
|
||
.detail
|
||
span.name YouTube Preview
|
||
span.extra https://www.youtube.com/watch?v={{ worldDialog.ref.previewYoutubeId }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Players
|
||
span.extra {{ worldDialog.ref.occupants | commaNumber }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Favorites
|
||
span.extra {{ worldDialog.ref.favorites | commaNumber }}
|
||
| #[template(v-if="worldDialog.ref.favorites > 0 && worldDialog.ref.visits > 0") ({{ Math.round(((worldDialog.ref.favorites - worldDialog.ref.visits) / worldDialog.ref.visits * 100 + 100) * 100) / 100 }}%)]
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Visits
|
||
span.extra {{ worldDialog.ref.visits | commaNumber }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Capacity
|
||
span.extra {{ worldDialog.ref.capacity | commaNumber }} ({{ worldDialog.ref.capacity * 2 | commaNumber }})
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Heat
|
||
span.extra {{ worldDialog.ref.heat | commaNumber }} {{ '🔥'.repeat(worldDialog.ref.heat) }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Popularity
|
||
span.extra {{ worldDialog.ref.popularity | commaNumber }} {{ '💖'.repeat(worldDialog.ref.popularity) }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Created
|
||
span.extra {{ worldDialog.ref.created_at | formatDate('long') }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Last Updated
|
||
span.extra {{ worldDialog.fileCreatedAt | formatDate('long') }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Version
|
||
span.extra(v-text="worldDialog.ref.version")
|
||
.x-friend-item(style="width:525px;cursor:default")
|
||
.detail
|
||
span.name Platform
|
||
span.extra(v-text="worldDialogPlatform")
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Last Visit
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
i.el-icon-warning
|
||
span.extra {{ worldDialog.lastVisit | formatDate('long') }}
|
||
.x-friend-item(@click="showPreviousInstancesWorldDialog(worldDialog.ref)")
|
||
.detail
|
||
span.name Visit Count
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
i.el-icon-warning
|
||
span.extra(v-text="worldDialog.visitCount")
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Time Spent
|
||
el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" content="Info from local database may not be accurate")
|
||
i.el-icon-warning
|
||
span.extra(v-if="worldDialog.timeSpent === 0") -
|
||
span.extra(v-else) {{ worldDialog.timeSpent | timeToText }}
|
||
el-tab-pane(label="JSON")
|
||
el-button(type="default" @click="refreshWorldDialogTreeData()" size="mini" icon="el-icon-refresh" circle)
|
||
el-tree(:data="worldDialog.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")
|
||
|
||
//- dialog: avatar
|
||
el-dialog.x-dialog.x-avatar-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="avatarDialog" :visible.sync="avatarDialog.visible" :show-close="false" width="600px")
|
||
div(v-loading="avatarDialog.loading")
|
||
div(style="display:flex")
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="avatarDialog.ref.thumbnailImageUrl" style="flex:none;width:160px;height:120px;border-radius:4px")
|
||
img.x-link(v-lazy="avatarDialog.ref.imageUrl" style="width:500px;height:375px" @click="downloadAndSaveImage(avatarDialog.ref.imageUrl)")
|
||
div(style="flex:1;display:flex;align-items:center;margin-left:15px")
|
||
div(style="flex:1")
|
||
div
|
||
span.dialog-title(v-text="avatarDialog.ref.name")
|
||
div(style="margin-top:5px")
|
||
span.x-link(v-text="avatarDialog.ref.authorName" @click="showUserDialog(avatarDialog.ref.authorId)" style="color:#909399;font-family:monospace")
|
||
div(style="margin-top:5px")
|
||
el-tag(v-if="avatarDialog.ref.releaseStatus === 'public'" type="success" effect="plain" size="mini" style="margin-right:5px") Public
|
||
el-tag(v-else type="danger" effect="plain" size="mini" style="margin-right:5px") Private
|
||
el-tag(v-if="avatarDialog.isQuestFallback" type="info" effect="plain" size="mini" style="margin-right:5px") Fallback
|
||
el-tag(v-if="avatarDialog.fileSize" type="info" effect="plain" size="mini" v-text="avatarDialog.fileSize" style="margin-right:5px")
|
||
el-tag(v-if="avatarDialog.inCache" type="info" effect="plain" size="mini")
|
||
span(v-text="avatarDialog.cacheSize")
|
||
| Cache
|
||
div(style="margin-top:5px")
|
||
span(v-show="avatarDialog.ref.name !== avatarDialog.ref.description" v-text="avatarDialog.ref.description" style="font-size:12px")
|
||
div(style="flex:none;margin-left:10px")
|
||
el-tooltip(v-if="avatarDialog.inCache" placement="top" content="Delete avatar from cache" :disabled="hideTooltips")
|
||
el-button(icon="el-icon-delete" circle @click="deleteVRChatCache(avatarDialog.ref)" :disabled="isGameRunning && avatarDialog.cacheLocked")
|
||
el-tooltip(v-if="avatarDialog.isFavorite" placement="top" content="Remove from favorites" :disabled="hideTooltips")
|
||
el-button(type="warning" icon="el-icon-star-on" circle @click="avatarDialogCommand('Delete Favorite')" style="margin-left:5px")
|
||
el-tooltip(v-else placement="top" content="Add to favorites" :disabled="hideTooltips")
|
||
el-button(type="default" icon="el-icon-star-off" circle @click="avatarDialogCommand('Add Favorite')" style="margin-left:5px")
|
||
el-dropdown(trigger="click" @command="avatarDialogCommand" size="small" style="margin-left:5px")
|
||
el-button(:type="avatarDialog.isBlocked ? '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") Refresh
|
||
el-dropdown-item(icon="el-icon-check" command="Select Avatar") Select Avatar
|
||
el-dropdown-item(v-if="/quest/.test(avatarDialog.ref.tags)" icon="el-icon-check" command="Select Fallback Avatar") Select Fallback Avatar
|
||
el-dropdown-item(v-if="avatarDialog.isBlocked" icon="el-icon-circle-check" command="Unblock Avatar" style="color:#F56C6C") Unblock Avatar
|
||
el-dropdown-item(v-else icon="el-icon-circle-close" command="Block Avatar") Block Avatar
|
||
el-dropdown-item(v-if="avatarDialog.ref.authorId !== API.currentUser.id" icon="el-icon-picture-outline" command="Previous Images") Previous Images
|
||
template(v-if="avatarDialog.ref.authorId === API.currentUser.id")
|
||
el-dropdown-item(v-if="avatarDialog.ref.releaseStatus === 'public'" icon="el-icon-user-solid" command="Make Private" divided) Make Private
|
||
el-dropdown-item(v-else icon="el-icon-user" command="Make Public" divided) Make Public
|
||
el-dropdown-item(icon="el-icon-edit" command="Rename") Rename
|
||
el-dropdown-item(icon="el-icon-edit" command="Change Description") Change Description
|
||
el-dropdown-item(icon="el-icon-picture-outline" command="Change Image") Change Image
|
||
el-dropdown-item(v-if="avatarDialog.ref.unityPackageUrl" icon="el-icon-download" command="Download Unity Package") Download Unity Package
|
||
el-dropdown-item(icon="el-icon-user" command="Delete" style="color:#F56C6C" divided) Delete
|
||
el-tabs
|
||
el-tab-pane(label="Info")
|
||
.x-friend-list
|
||
.x-friend-item(style="width:100%;cursor:default")
|
||
.detail
|
||
span.name Avatar ID
|
||
span.extra {{ avatarDialog.id }}
|
||
el-tooltip(placement="top" content="Copy to clipboard" :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="copyAvatarId(avatarDialog.id)") Copy ID
|
||
el-dropdown-item(@click.native="copyAvatarUrl(avatarDialog.id)") Copy URL
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Created
|
||
span.extra {{ avatarDialog.ref.created_at | formatDate('long') }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Last Updated
|
||
span.extra {{ avatarDialog.ref.updated_at | formatDate('long') }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Version
|
||
span.extra(v-if="avatarDialog.ref.version !== 0" v-text="avatarDialog.ref.version")
|
||
span.extra(v-else) -
|
||
.x-friend-item(style="width:100%;cursor:default")
|
||
.detail
|
||
span.name Platform
|
||
span.extra(v-if="avatarDialogPlatform" v-text="avatarDialogPlatform")
|
||
span.extra(v-else) -
|
||
el-tab-pane(label="JSON")
|
||
el-button(type="default" @click="refreshAvatarDialogTreeData()" size="mini" icon="el-icon-refresh" circle)
|
||
el-tree(:data="avatarDialog.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")
|
||
|
||
//- dialog: group
|
||
el-dialog.x-dialog.x-group-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="groupDialog" :visible.sync="groupDialog.visible" :show-close="false" width="770px")
|
||
.group-banner-image
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="groupDialog.ref.bannerUrl" style="flex:none;width:100%;aspect-ratio:6/1;object-fit:cover;border-radius:4px")
|
||
img.x-link(v-lazy="groupDialog.ref.bannerUrl" style="width:854px;height:480px" @click="downloadAndSaveImage(groupDialog.ref.bannerUrl)")
|
||
.group-body(v-loading="groupDialog.loading")
|
||
div(style="display:flex")
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="groupDialog.ref.iconUrl" style="flex:none;width:120px;height:120px;border-radius:4px")
|
||
img.x-link(v-lazy="groupDialog.ref.iconUrl" style="width:500px;height:500px" @click="downloadAndSaveImage(groupDialog.ref.iconUrl)")
|
||
div(style="flex:1;display:flex;align-items:center;margin-left:15px")
|
||
.group-header(style="flex:1")
|
||
span(v-if="groupDialog.ref.ownerId === API.currentUser.id" style="margin-right:5px") 👑
|
||
span.dialog-title(v-text="groupDialog.ref.name" style="margin-right:5px")
|
||
span.group-discriminator(style="color:#909399;font-family:monospace;font-size:12px;margin-right:5px") {{ groupDialog.ref.shortCode }}.{{ groupDialog.ref.discriminator }}
|
||
el-tooltip(v-for="item in groupDialog.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")
|
||
div(style="margin-top:5px")
|
||
span.x-link(v-text="groupDialog.ownerDisplayName" @click="showUserDialog(groupDialog.ref.ownerId)" style="color:#909399;font-family:monospace")
|
||
.group-tags
|
||
el-tag(v-if="groupDialog.ref.isVerified" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Verified
|
||
|
||
el-tag(v-if="groupDialog.ref.privacy === 'private'" type="danger" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Private
|
||
el-tag(v-if="groupDialog.ref.privacy === 'default'" type="success" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Public
|
||
|
||
el-tag(v-if="groupDialog.ref.joinState === 'open'" type="success" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Open
|
||
el-tag(v-else-if="groupDialog.ref.joinState === 'request'" type="warning" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Request
|
||
el-tag(v-else-if="groupDialog.ref.joinState === 'invite'" type="danger" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Invite
|
||
el-tag(v-else-if="groupDialog.ref.joinState === 'closed'" type="danger" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Closed
|
||
|
||
el-tag(v-if="groupDialog.inGroup" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Joined
|
||
el-tag(v-if="groupDialog.ref.myMember && groupDialog.ref.myMember.bannedAt" type="danger" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Banned
|
||
|
||
template(v-if="groupDialog.inGroup && groupDialog.ref.myMember")
|
||
el-tag(v-if="groupDialog.ref.myMember.visibility === 'visible'" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Visible
|
||
el-tag(v-else-if="groupDialog.ref.myMember.visibility === 'friends'" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Friends
|
||
el-tag(v-else-if="groupDialog.ref.myMember.visibility === 'hidden'" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Hidden
|
||
el-tag(v-if="groupDialog.ref.myMember.isSubscribedToAnnouncements" type="info" effect="plain" size="mini" style="margin-right:5px;margin-top:5px") Subscribed
|
||
|
||
.group-description(style="margin-top:5px")
|
||
span(v-show="groupDialog.ref.name !== groupDialog.ref.description" v-text="groupDialog.ref.description" style="font-size:12px")
|
||
div(style="flex:none;margin-left:10px")
|
||
template(v-if="groupDialog.inGroup")
|
||
el-tooltip(v-if="groupDialog.ref.isRepresenting" placement="top" content="Stop Representing" :disabled="hideTooltips")
|
||
el-button(type="warning" icon="el-icon-star-on" circle @click="clearGroupRepresentation(groupDialog.id)" style="margin-left:5px")
|
||
el-tooltip(v-else placement="top" content="Set Representing" :disabled="hideTooltips")
|
||
span
|
||
el-button(type="default" icon="el-icon-star-off" circle @click="setGroupRepresentation(groupDialog.id)" style="margin-left:5px" :disabled="groupDialog.ref.privacy === 'private'")
|
||
template(v-else-if="groupDialog.ref.membershipStatus === 'requested'")
|
||
el-tooltip(placement="top" content="Cancel join request" :disabled="hideTooltips")
|
||
span
|
||
el-button(type="default" icon="el-icon-close" circle @click="cancelGroupRequest(groupDialog.id)" style="margin-left:5px")
|
||
template(v-else-if="groupDialog.ref.membershipStatus === 'invited'")
|
||
el-tooltip(placement="top" content="Pending invite" :disabled="hideTooltips")
|
||
span
|
||
el-button(type="default" icon="el-icon-check" circle @click="joinGroup(groupDialog.id)" style="margin-left:5px")
|
||
template(v-else)
|
||
el-tooltip(v-if="groupDialog.ref.joinState === 'request'" placement="top" content="Request to join" :disabled="hideTooltips")
|
||
el-button(type="default" icon="el-icon-message" circle @click="joinGroup(groupDialog.id)" style="margin-left:5px")
|
||
el-tooltip(v-if="groupDialog.ref.joinState === 'invite'" placement="top" content="Invite required" :disabled="hideTooltips")
|
||
span
|
||
el-button(type="default" icon="el-icon-message" disabled circle style="margin-left:5px")
|
||
el-tooltip(v-if="groupDialog.ref.joinState === 'open'" placement="top" content="Join Group" :disabled="hideTooltips")
|
||
el-button(type="default" icon="el-icon-check" circle @click="joinGroup(groupDialog.id)" style="margin-left:5px")
|
||
el-dropdown(trigger="click" @command="groupDialogCommand" size="small" style="margin-left:5px")
|
||
el-button(type="default" icon="el-icon-more" circle)
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(icon="el-icon-refresh" command="Refresh") Refresh
|
||
template(v-if="groupDialog.inGroup")
|
||
template(v-if="groupDialog.ref.myMember")
|
||
el-dropdown-item(v-if="groupDialog.ref.myMember.isSubscribedToAnnouncements" icon="el-icon-close" command="Unsubscribe To Announcements" divided) Unsubscribe From Announcements
|
||
el-dropdown-item(v-else icon="el-icon-check" command="Subscribe To Announcements" divided) Subscribe To Announcements
|
||
el-dropdown-item(v-if="hasGroupPermission(groupDialog.ref, 'group-invites-manage')" icon="el-icon-message" command="Invite To Group") Invite To Group
|
||
template(v-if="groupDialog.ref.myMember && groupDialog.ref.privacy === 'default'")
|
||
el-dropdown-item(icon="el-icon-view" command="Visibility Everyone" divided) #[i.el-icon-check(v-if="groupDialog.ref.myMember.visibility === 'visible'")] Visibility Everyone
|
||
el-dropdown-item(icon="el-icon-view" command="Visibility Friends") #[i.el-icon-check(v-if="groupDialog.ref.myMember.visibility === 'friends'")] Visibility Friends
|
||
el-dropdown-item(icon="el-icon-view" command="Visibility Hidden") #[i.el-icon-check(v-if="groupDialog.ref.myMember.visibility === 'hidden'")] Visibility Hidden
|
||
el-dropdown-item(icon="el-icon-delete" command="Leave Group" style="color:#F56C6C" divided) Leave Group
|
||
el-tabs(ref="groupDialogTabs" @tab-click="groupDialogTabClick")
|
||
el-tab-pane(label="Info")
|
||
.group-banner-image-info
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="groupDialog.ref.bannerUrl" style="flex:none;width:100%;aspect-ratio:6/1;object-fit:cover;border-radius:4px")
|
||
img.x-link(v-lazy="groupDialog.ref.bannerUrl" style="width:854px;height:480px" @click="downloadAndSaveImage(groupDialog.ref.bannerUrl)")
|
||
.x-friend-list(style="max-height:none")
|
||
.x-friend-item(v-if="groupDialog.ref.membershipStatus === 'member'" style="width:100%;cursor:default")
|
||
.detail
|
||
span.name Announcement
|
||
span(style="display:block" v-text="groupDialog.announcement.title")
|
||
div(v-if="groupDialog.announcement.imageUrl" style="display:inline-block;margin-right:5px")
|
||
el-popover(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="groupDialog.announcement.imageUrl" style="flex:none;width:60px;height:60px;border-radius:4px;object-fit:cover")
|
||
img.x-link(v-lazy="groupDialog.announcement.imageUrl" style="height:500px" @click="downloadAndSaveImage(groupDialog.announcement.imageUrl)")
|
||
pre.extra(style="display:inline-block;vertical-align:top;font-family:inherit;font-size:12px;white-space:pre-wrap;margin:0") {{ groupDialog.announcement.text || '-' }}
|
||
br
|
||
.extra(v-if="groupDialog.announcement.id" style="float:right;margin-left:5px")
|
||
el-tooltip(placement="bottom")
|
||
template(#content)
|
||
span {{ groupDialog.announcement.updatedAt | formatDate('long') }}
|
||
span(@click="showUserDialog(groupDialog.announcement.authorId)" style="cursor:pointer")
|
||
span(v-text="groupDialog.announcementDisplayName" style="margin-right:5px")
|
||
timer(:epoch="Date.parse(groupDialog.announcement.updatedAt)")
|
||
div(v-for="room in groupDialog.instances" :key="room.tag" style="width:100%")
|
||
div(style="margin:5px 0")
|
||
location(:location="room.tag")
|
||
el-tooltip(placement="top" content="Invite yourself" :disabled="hideTooltips")
|
||
invite-yourself(:location="room.tag" style="margin-left:5px")
|
||
el-tooltip(placement="top" content="Refresh player count" :disabled="hideTooltips")
|
||
el-button(v-if="room.tag !== lastLocation.location" @click="refreshInstancePlayerCount(room.tag)" size="mini" icon="el-icon-refresh" style="margin-left:5px" circle)
|
||
span(v-if="room.occupants" style="margin-left:5px") {{ room.occupants }} #[template(v-if="room.friendCount > 0") ({{ room.friendCount }})]
|
||
.x-friend-list(style="margin:10px 0;max-height:unset" v-if="room.users.length")
|
||
.x-friend-item(v-for="user in room.users" :key="user.id" @click="showUserDialog(user.id)" class="x-friend-item-border")
|
||
.avatar(:class="userStatusClass(user)")
|
||
img(v-lazy="userImage(user)")
|
||
.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-item(style="width:100%;cursor:default")
|
||
.detail
|
||
span.name Rules
|
||
pre.extra(style="font-family:inherit;font-size:12px;white-space:pre-wrap;margin:0 0.5em 0 0") {{ groupDialog.ref.rules || '-' }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Members
|
||
.extra {{ groupDialog.ref.memberCount }} ({{ groupDialog.ref.onlineMemberCount }})
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Created
|
||
span.extra {{ groupDialog.ref.createdAt | formatDate('long') }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Links
|
||
div(v-if="groupDialog.ref.links && groupDialog.ref.links.length > 0" style="margin-top:5px")
|
||
el-tooltip(v-if="link" v-for="(link, index) in groupDialog.ref.links" :key="index")
|
||
template(#content)
|
||
span(v-text="link")
|
||
img(:src="getFaviconUrl(link)" style="width:16px;height:16px;vertical-align:middle;margin-right:5px;cursor:pointer" @click.stop="openExternalLink(link)")
|
||
.extra(v-else) -
|
||
.x-friend-item(style="width:350px;cursor:default")
|
||
.detail
|
||
span.name Group URL
|
||
span.extra {{ groupDialog.ref.$url }}
|
||
el-tooltip(placement="top" content="Copy URL to clipboard" :disabled="hideTooltips")
|
||
el-button(type="default" @click="copyGroupUrl(groupDialog.ref.$url)" size="mini" icon="el-icon-s-order" circle style="margin-left:5px")
|
||
.x-friend-item(style="width:350px;cursor:default")
|
||
.detail
|
||
span.name Group ID
|
||
span.extra {{ groupDialog.id }}
|
||
el-tooltip(placement="top" content="Copy ID to clipboard" :disabled="hideTooltips")
|
||
el-button(type="default" @click="copyGroupId(groupDialog.id)" size="mini" icon="el-icon-s-order" circle style="margin-left:5px")
|
||
div(v-if="groupDialog.ref.membershipStatus === 'member'" style="width:100%;margin-top:10px;border-top:1px solid #e4e7ed14")
|
||
div(style="width:100%;display:flex;margin-top:10px")
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Joined At
|
||
span.extra {{ groupDialog.ref.myMember.joinedAt | formatDate('long') }}
|
||
.x-friend-item(style="cursor:default")
|
||
.detail
|
||
span.name Roles
|
||
span.extra(v-if="groupDialog.memberRoles.length === 0") -
|
||
span.extra(v-else)
|
||
template(v-for="(role, rIndex) in groupDialog.memberRoles" :key="rIndex")
|
||
el-tooltip(placement="top")
|
||
template(#content)
|
||
span Description: {{ role.description }}
|
||
br
|
||
span(v-if="role.updatedAt") Updated At: {{ role.updatedAt | formatDate('long') }}
|
||
span(v-else) Created At: {{ role.createdAt | formatDate('long') }}
|
||
br
|
||
span Permissions:
|
||
br
|
||
template(v-for="(permission, pIndex) in role.permissions" :key="pIndex")
|
||
span {{ permission }}
|
||
br
|
||
span {{ role.name }}{{ rIndex < groupDialog.memberRoles.length - 1 ? ', ' : '' }}
|
||
el-tab-pane(label="Members")
|
||
template(v-if="groupDialog.visible && groupDialog.ref.membershipStatus === 'member'")
|
||
span(v-if="hasGroupPermission(groupDialog.ref, 'group-members-viewall')" style="font-weight:bold;font-size:16px") All Members
|
||
span(v-else style="font-weight:bold;font-size:16px") Friends Only
|
||
br
|
||
el-button(type="default" @click="getGroupDialogGroupMembers()" size="mini" icon="el-icon-refresh" circle)
|
||
span(style="font-size:14px;margin-left:5px;margin-right:5px") {{ groupDialog.members.length }}/{{ groupDialog.ref.memberCount }}
|
||
ul.infinite-list.x-friend-list(v-if="groupDialog.members.length > 0" v-infinite-scroll="loadMoreGroupMembers" style="margin-top:10px;overflow:auto;max-height:250px")
|
||
li.infinite-list-item.x-friend-item(v-for="user in groupDialog.members" :key="user.id" @click="showUserDialog(user.userId)" class="x-friend-item-border")
|
||
.avatar
|
||
img(v-lazy="userImage(user.user)")
|
||
.detail
|
||
span.name(v-text="user.user.displayName" :style="{'color':user.user.$userColour}")
|
||
span.extra
|
||
.x-friend-item(v-if="!isGroupMembersDone" v-loading="isGroupMembersLoading" style="width:100%;height:45px;text-align:center" @click="loadMoreGroupMembers")
|
||
.detail(v-if="!isGroupMembersLoading")
|
||
span.name Load more...
|
||
el-tab-pane(label="JSON")
|
||
el-button(type="default" @click="refreshGroupDialogTreeData()" size="mini" icon="el-icon-refresh" circle)
|
||
el-tree(:data="groupDialog.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")
|
||
|
||
//- dialog: favorite
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="favoriteDialog" :visible.sync="favoriteDialog.visible" title="Choose Group" width="300px")
|
||
div(v-if="favoriteDialog.visible" v-loading="favoriteDialog.loading")
|
||
span(style="display:block;text-align:center") VRChat Favorites
|
||
template(v-if="favoriteDialog.currentGroup && favoriteDialog.currentGroup.key")
|
||
el-button(style="display:block;width:100%;margin:10px 0" @click="deleteFavorite(favoriteDialog.objectId)") #[i.el-icon-check] {{ favoriteDialog.currentGroup.displayName }} ({{ favoriteDialog.currentGroup.count }} / {{ favoriteDialog.currentGroup.capacity }})
|
||
template(v-else)
|
||
el-button(v-for="group in favoriteDialog.groups" :key="group" style="display:block;width:100%;margin:10px 0" @click="addFavorite(group)") {{ group.displayName }} ({{ group.count }} / {{ group.capacity }})
|
||
div(v-if="favoriteDialog.visible && favoriteDialog.type === 'world'" style="margin-top:20px")
|
||
span(style="display:block;text-align:center") Local Favorites
|
||
template(v-for="group in localWorldFavoriteGroups" :key="group")
|
||
el-button(v-if="hasLocalWorldFavorite(favoriteDialog.objectId, group)" style="display:block;width:100%;margin:10px 0" @click="removeLocalWorldFavorite(favoriteDialog.objectId, group)") #[i.el-icon-check] {{ group }} ({{ getLocalWorldFavoriteGroupLength(group) }})
|
||
el-button(v-else style="display:block;width:100%;margin:10px 0" @click="addLocalWorldFavorite(favoriteDialog.objectId, group)") {{ group }} ({{ getLocalWorldFavoriteGroupLength(group) }})
|
||
|
||
//- dialog: invite
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="inviteDialog" :visible.sync="inviteDialog.visible" title="Invite" width="450px")
|
||
div(v-if="inviteDialog.visible" v-loading="inviteDialog.loading")
|
||
location(:location="inviteDialog.worldId" :link="false")
|
||
el-select(v-model="inviteDialog.userIds" multiple clearable placeholder="Choose Friends" filterable :disabled="inviteDialog.loading" style="width:100%;margin-top:15px")
|
||
el-option-group(v-if="API.currentUser" label="ME")
|
||
el-option.x-friend-item(:label="API.currentUser.displayName" :value="API.currentUser.id" style="height:auto")
|
||
.avatar(:class="userStatusClass(API.currentUser)")
|
||
img(v-lazy="userImage(API.currentUser)")
|
||
.detail
|
||
span.name(v-text="API.currentUser.displayName")
|
||
el-option-group(v-if="friendsGroup0.length" label="VIP")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup0" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar(:class="userStatusClass(friend.ref)")
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
el-option-group(v-if="friendsGroup1.length" label="ONLINE")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup1" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar(:class="userStatusClass(friend.ref)")
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
el-option-group(v-if="friendsGroup2.length" label="ACTIVE")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup2" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
template(#footer)
|
||
el-button(size="small" :disabled="inviteDialog.loading || !inviteDialog.userIds.length" @click="showSendInviteDialog()") Invite With Message
|
||
el-button(type="primary" size="small" :disabled="inviteDialog.loading || !inviteDialog.userIds.length" @click="sendInvite()") Invite
|
||
|
||
//- dialog: social status
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="socialStatusDialog" :visible.sync="socialStatusDialog.visible" title="Social Status" width="400px")
|
||
div(v-loading="socialStatusDialog.loading")
|
||
el-collapse(style="border:0")
|
||
el-collapse-item
|
||
template(slot="title")
|
||
span(style="font-size:16px") History
|
||
data-tables(v-bind="socialStatusHistoryTable" @row-click="setSocialStatusFromHistory" style="cursor:pointer")
|
||
el-table-column(label="No" prop="no" width="40")
|
||
el-table-column(label="Status" prop="status")
|
||
el-select(v-model="socialStatusDialog.status" style="dispaly:block;margin-top:10px")
|
||
el-option(label="Online" value="active").
|
||
#[i.x-user-status.online] Online
|
||
el-option(label="Join Me" value="join me").
|
||
#[i.x-user-status.joinme] Join Me
|
||
el-option(label="Ask Me" value="ask me").
|
||
#[i.x-user-status.askme] Ask Me
|
||
el-option(label="Do Not Disturb" value="busy").
|
||
#[i.x-user-status.busy] Do Not Disturb
|
||
el-option(v-if="API.currentUser.$isModerator" label="Offline" value="offline").
|
||
#[i.x-user-status.offline] Offline
|
||
el-input(v-model="socialStatusDialog.statusDescription" placeholder="Status" maxlength="32" show-word-limit style="dispaly:block;margin-top:10px")
|
||
template(#footer)
|
||
el-button(type="primary" size="small" :disabled="socialStatusDialog.loading" @click="saveSocialStatus") Update
|
||
|
||
//- dialog: language
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="languageDialog" :visible.sync="languageDialog.visible" title="Language" width="400px")
|
||
div(v-loading="languageDialog.loading")
|
||
div(style="margin:5px 0")
|
||
el-tag(v-for="item in API.currentUser.$languages" :key="item.key" size="small" type="info" effect="plain" closable @close="removeUserLanguage(item.key)" style="margin-right:5px")
|
||
span.flags(:class="languageClass(item.key)" style="display:inline-block;margin-right:5px")
|
||
| {{ item.value }} ({{ item.key }})
|
||
div(v-if="languageDialog.languageChoice === true")
|
||
el-select(v-model="languageDialog.languageValue" size="mini")
|
||
el-option(v-for="item in languageDialog.languages" :key="item.key" :value="item.key" :label="item.value")
|
||
span.flags(:class="languageClass(item.key)" style="display:inline-block;margin-right:5px")
|
||
| {{ item.value }} ({{ item.key }})
|
||
el-button(@click="languageDialog.languageChoice=false; addUserLanguage(languageDialog.languageValue)" size="mini") Ok
|
||
el-button(@click="languageDialog.languageChoice=false" size="mini" style="margin-left:0") Cancel
|
||
div(v-else)
|
||
el-button(@click="languageDialog.languageValue='';languageDialog.languageChoice=true" size="mini") Add Language
|
||
|
||
//- dialog: bio
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="bioDialog" :visible.sync="bioDialog.visible" title="Bio" width="600px")
|
||
div(v-loading="bioDialog.loading")
|
||
el-input(type="textarea" v-model="bioDialog.bio" size="mini" maxlength="512" show-word-limit :autosize="{ minRows:2, maxRows:5 }" placeholder="Please input a bio")
|
||
el-input(v-for="(link, index) in bioDialog.bioLinks" :key="index" :value="link" v-model="bioDialog.bioLinks[index]" size="small" style="margin-top:5px")
|
||
img(slot="prepend" :src="getFaviconUrl(link)" style="width:16px;height:16px")
|
||
el-button(slot="append" icon="el-icon-delete" @click="bioDialog.bioLinks.splice(index, 1)")
|
||
el-button(@click="bioDialog.bioLinks.push('')" size="mini" style="margin-top:5px") Add Link
|
||
template(#footer)
|
||
el-button(type="primary" size="small" :disabled="bioDialog.loading" @click="saveBio") Update
|
||
|
||
//- dialog: new instance
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="newInstanceDialog" :visible.sync="newInstanceDialog.visible" title="New Instance" width="600px")
|
||
el-form(v-if="newInstanceDialog.visible" :model="newInstanceDialog" label-width="130px")
|
||
el-form-item(label="Access Type")
|
||
el-radio-group(v-model="newInstanceDialog.accessType" size="mini" @change="buildInstance")
|
||
el-radio-button(label="public")
|
||
el-radio-button(label="group")
|
||
el-radio-button(label="friends+")
|
||
el-radio-button(label="friends")
|
||
el-radio-button(label="invite+")
|
||
el-radio-button(label="invite")
|
||
//- el-form-item(label="Strict" v-if="newInstanceDialog.accessType === 'friends' || newInstanceDialog.accessType === 'invite'")
|
||
//- el-checkbox(v-model="newInstanceDialog.strict") Prevent non friends joining via URL/Instance ID
|
||
el-form-item(label="Region")
|
||
el-radio-group(v-model="newInstanceDialog.region" size="mini" @change="buildInstance")
|
||
el-radio-button(label="US West")
|
||
el-radio-button(label="US East")
|
||
el-radio-button(label="Europe")
|
||
el-radio-button(label="Japan")
|
||
el-form-item(label="World ID")
|
||
el-input(v-model="newInstanceDialog.worldId" size="mini" @click.native="$event.target.tagName === 'INPUT' && $event.target.select()")
|
||
el-form-item(label="Instance ID")
|
||
el-input(v-model="newInstanceDialog.instanceName" placeholder="Random" size="mini")
|
||
el-form-item(label="Instance Creator" v-if="newInstanceDialog.accessType !== 'public' && newInstanceDialog.accessType !== 'group'")
|
||
el-select(v-model="newInstanceDialog.userId" clearable placeholder="Choose User" filterable style="width:100%")
|
||
el-option-group(v-if="API.currentUser" label="ME")
|
||
el-option.x-friend-item(:label="API.currentUser.displayName" :value="API.currentUser.id" style="height:auto")
|
||
.avatar(:class="userStatusClass(API.currentUser)")
|
||
img(v-lazy="userImage(API.currentUser)")
|
||
.detail
|
||
span.name(v-text="API.currentUser.displayName")
|
||
el-option-group(v-if="friendsGroup0.length" label="VIP")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup0" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar(:class="userStatusClass(friend.ref)")
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
el-option-group(v-if="friendsGroup1.length" label="ONLINE")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup1" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar(:class="userStatusClass(friend.ref)")
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
el-option-group(v-if="friendsGroup2.length" label="ACTIVE")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup2" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
el-option-group(v-if="friendsGroup3.length" label="OFFLINE")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup3" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
el-form-item(label="Group ID" v-if="newInstanceDialog.accessType === 'group'")
|
||
el-input(v-model="newInstanceDialog.groupId" placeholder="grp_UUID" size="mini")
|
||
el-form-item(label="Location")
|
||
el-input(v-model="newInstanceDialog.location" size="mini" readonly)
|
||
el-form-item(label="URL")
|
||
el-input(v-model="newInstanceDialog.url" size="mini" readonly @click.native="$event.target.tagName === 'INPUT' && $event.target.select()")
|
||
template(#footer)
|
||
el-button(size="small" @click="copyInstanceUrl(newInstanceDialog.location)") Copy URL
|
||
el-button(size="small" @click="selfInvite(newInstanceDialog.location)") Self Invite
|
||
el-button(size="small" @click="showInviteDialog(newInstanceDialog.location)" :disabled="(newInstanceDialog.accessType === 'friends' || newInstanceDialog.accessType === 'invite') && newInstanceDialog.userId !== API.currentUser.id") Invite
|
||
el-button(type="primary" size="small" @click="showLaunchDialog(newInstanceDialog.location, newInstanceDialog.secureOrShortName)") Launch
|
||
|
||
//- dialog: launch options
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="launchOptionsDialog" :visible.sync="launchOptionsDialog.visible" title="Launch Options" width="500px")
|
||
div(style="font-size:12px")
|
||
| These options are for advanced users only. #[br]
|
||
| to change max fps: --fps=<N> e.g.) #[el-tag(size="mini") --fps=144]
|
||
el-input(type="textarea" v-model="launchOptionsDialog.launchArguments" size="mini" show-word-limit :autosize="{ minRows:2, maxRows:5 }" placeholder="" style="margin-top:10px")
|
||
div(style="font-size:12px;margin-top:10px")
|
||
| VRChat Path Override
|
||
el-input(type="textarea" v-model="launchOptionsDialog.vrcLaunchPathOverride" placeholder="C:\\Program Files (x86)\\Steam\\steamapps\\common\\VRChat" :rows="1" style="dispaly:block;margin-top:10px")
|
||
template(#footer)
|
||
div(style="display:flex")
|
||
el-button(size="small" @click="openExternalLink('https://docs.vrchat.com/docs/launch-options')") VRChat Docs
|
||
el-button(size="small" @click="openExternalLink('https://docs.unity3d.com/Manual/CommandLineArguments.html')") Unity Manual
|
||
el-button(type="primary" size="small" :disabled="launchOptionsDialog.loading" @click="updateLaunchOptions" style="margin-left:auto") Save
|
||
|
||
//- dialog: VRChat Config JSON
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="VRChatConfigDialog" :visible.sync="VRChatConfigDialog.visible" title="VRChat Config JSON" width="420px")
|
||
div(style='font-size:12px;word-break:keep-all')
|
||
| These options are for advanced users only. #[br]
|
||
| Leave field empty to set as default, game restart required to apply settings.
|
||
br
|
||
span Cache Size:
|
||
span(v-text="VRChatUsedCacheSize")
|
||
span /
|
||
span(v-text="VRChatTotalCacheSize")
|
||
span GB
|
||
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
|
||
el-button(type="default" :loading="VRChatCacheSizeLoading" @click="getVRChatCacheSize" size="small" icon="el-icon-refresh" circle style="margin-left:5px")
|
||
br
|
||
span Delete all cache
|
||
el-button(size="small" style="margin-left:5px" icon="el-icon-delete" @click="showDeleteAllVRChatCacheConfirm()") Delete Cache
|
||
br
|
||
span Delete old versions from cache
|
||
el-button(size="small" style="margin-left:5px" icon="el-icon-folder-delete" @click="sweepVRChatCache()") Sweep Cache
|
||
br
|
||
div(style="display:inline-block;margin-top:10px" v-for="(item, value) in VRChatConfigList" :key="value")
|
||
span(v-text="item.name" style="word-break:keep-all")
|
||
|:
|
||
el-input(v-model="VRChatConfigFile[value]" :placeholder="item.default" size="mini" :type="item.type?item.type:'text'" :min="item.min" :max="item.max")
|
||
div(style="display:inline-block;margin-top:10px")
|
||
span Camera Resolution
|
||
br
|
||
el-dropdown(@command="(command) => setVRChatCameraResolution(command)" size="small" trigger="click" style="margin-top:5px")
|
||
el-button(size="small")
|
||
span #[span(v-text="getVRChatCameraResolution()")] #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(v-for="row in VRChatResolutions" :key="row.index" v-text="row.name" :command="row")
|
||
div(style="display:inline-block;margin-top:10px;margin-left:10px")
|
||
span Screenshot Resolution
|
||
br
|
||
el-dropdown(@command="(command) => setVRChatScreenshotResolution(command)" size="small" trigger="click" style="margin-top:5px")
|
||
el-button(size="small")
|
||
span #[span(v-text="getVRChatScreenshotResolution()")] #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(v-for="row in VRChatResolutions" :key="row.index" v-text="row.name" :command="row")
|
||
el-checkbox(v-model="VRChatConfigFile.disableRichPresence" style="margin-top:5px;display:block") Disable Discord Rich Presence
|
||
template(#footer)
|
||
el-button(size="small" @click="openExternalLink('https://docs.vrchat.com/docs/configuration-file')") VRChat Docs
|
||
el-button(size="small" @click="VRChatConfigDialog.visible = false") Cancel
|
||
el-button(type="primary" size="small" :disabled="VRChatConfigDialog.loading" @click="saveVRChatConfigFile") Save
|
||
|
||
//- dialog: YouTube Api Dialog
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="youTubeApiDialog" :visible.sync="youTubeApiDialog.visible" title="YouTube API" width="400px")
|
||
div(style='font-size:12px;')
|
||
| Enter your YouTube API Key (optional) #[br]
|
||
el-input(type="textarea" v-model="youTubeApiKey" placeholder="YouTube API Key" maxlength="39" show-word-limit style="dispaly:block;margin-top:10px")
|
||
template(#footer)
|
||
div(style="display:flex")
|
||
el-button(size="small" @click="openExternalLink('https://rapidapi.com/blog/how-to-get-youtube-api-key/')") Guide
|
||
el-button(type="primary" size="small" @click="testYouTubeApiKey" style="margin-left:auto") Save
|
||
|
||
//- dialog: Set World Tags
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="setWorldTagsDialog" :visible.sync="setWorldTagsDialog.visible" title="Set World Tags" width="400px")
|
||
el-checkbox(v-model="setWorldTagsDialog.debugAllowed") Enable world debugging for others
|
||
div(style='font-size:12px;margin-top:10px')
|
||
| Enter tags comma separated #[br]
|
||
el-input(type="textarea" v-model="setWorldTagsDialog.tags" size="mini" show-word-limit :autosize="{ minRows:2, maxRows:5 }" placeholder="" style="margin-top:10px")
|
||
template(#footer)
|
||
div(style="display:flex")
|
||
el-button(size="small" @click="setWorldTagsDialog.visible = false") Cancel
|
||
el-button(type="primary" size="small" @click="saveSetWorldTagsDialog") Save
|
||
|
||
//- dialog: Cache Download
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="downloadDialog" :visible.sync="downloadDialog.visible" title="Download History" width="770px")
|
||
template(v-if="downloadDialog.visible")
|
||
div(v-if="downloadInProgress && downloadCurrent.ref")
|
||
span(v-text="downloadCurrent.ref.name")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click="cancelDownload(downloadCurrent.id)" style="margin-left:5px")
|
||
el-progress(:percentage="downloadProgress" :format="downloadProgressText")
|
||
template(v-if="downloadQueueTable.data.length >= 1")
|
||
span(style="margin-top:15px") Queue:
|
||
data-tables(v-bind="downloadQueueTable" style="margin-top:10px")
|
||
el-table-column(label="Name" prop="name")
|
||
el-table-column(label="Type" prop="type" width="70")
|
||
el-table-column(label="Cancel" width="60" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click="cancelDownload(scope.row.ref.id)")
|
||
span(style="margin-top:15px") History:
|
||
data-tables(v-bind="downloadHistoryTable" style="margin-top:10px")
|
||
el-table-column(label="Time" prop="date" width="90")
|
||
template(v-once #default="scope")
|
||
timer(:epoch="scope.row.date")
|
||
el-table-column(label="Name" prop="name")
|
||
template(v-once #default="scope")
|
||
span(v-text="scope.row.ref.name")
|
||
el-table-column(label="Type" prop="type" width="70")
|
||
el-table-column(label="Status" prop="status" width="80")
|
||
template(#footer)
|
||
el-button(v-if="downloadQueue.size >= 1" size="small" @click="cancelAllDownloads") Cancel All
|
||
el-button(size="small" @click="downloadDialog.visible = false") Close
|
||
|
||
//- dialog: update VRCX
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="VRCXUpdateDialog" :visible.sync="VRCXUpdateDialog.visible" title="VRCX Updater" width="400px")
|
||
div(v-loading="checkingForVRCXUpdate" style="margin-top:15px")
|
||
div(v-if="VRCXUpdateDialog.updatePending" style="margin-bottom:15px")
|
||
span(v-text="pendingVRCXUpdate")
|
||
br
|
||
span Ready for install, restart VRCX to apply.
|
||
el-select(v-model="branch" @change="loadBranchVersions" style="display:inline-block;width:150px;margin-right:15px")
|
||
el-option(v-once v-for="branch in branches" :key="branch.name" :label="branch.name" :value="branch.name")
|
||
el-select(v-model="VRCXUpdateDialog.release" style="display:inline-block;width:150px")
|
||
el-option(v-for="item in VRCXUpdateDialog.releases" :key="item.name" :label="item.tag_name" :value="item.name")
|
||
div(v-if="!VRCXUpdateDialog.updatePending && VRCXUpdateDialog.release === appVersion" style="margin-top:15px")
|
||
span VRCX is up to date.
|
||
template(#footer)
|
||
el-button(v-if="(VRCXUpdateDialog.updatePending && VRCXUpdateDialog.release !== pendingVRCXUpdate) || VRCXUpdateDialog.release !== appVersion" type="primary" size="small" @click="installVRCXUpdate") Download
|
||
el-button(v-if="VRCXUpdateDialog.updatePending" type="primary" size="small" @click="restartVRCX") Install
|
||
|
||
//- dialog: launch
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="launchDialog" :visible.sync="launchDialog.visible" title="Launch" width="450px")
|
||
el-form(:model="launchDialog" label-width="80px")
|
||
el-form-item(label="URL")
|
||
el-input(v-model="launchDialog.url" size="mini" @click.native="$event.target.tagName === 'INPUT' && $event.target.select()" style="width:260px")
|
||
el-tooltip(placement="right" content="Copy to clipboard" :disabled="hideTooltips")
|
||
el-button(@click="copyInstanceMessage(launchDialog.url)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle)
|
||
el-form-item(v-if="launchDialog.shortUrl" label="Short URL")
|
||
el-tooltip(placement="top" style="margin-left:5px" content="Short URL's expire after a set period of time")
|
||
i.el-icon-warning
|
||
el-input(v-model="launchDialog.shortUrl" size="mini" @click.native="$event.target.tagName === 'INPUT' && $event.target.select()" style="width:241px")
|
||
el-tooltip(placement="right" content="Copy to clipboard" :disabled="hideTooltips")
|
||
el-button(@click="copyInstanceMessage(launchDialog.shortUrl)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle)
|
||
el-form-item(label="Location")
|
||
el-input(v-model="launchDialog.location" size="mini" @click.native="$event.target.tagName === 'INPUT' && $event.target.select()" style="width:260px")
|
||
el-tooltip(placement="right" content="Copy to clipboard" :disabled="hideTooltips")
|
||
el-button(@click="copyInstanceMessage(launchDialog.location)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle)
|
||
template(#footer)
|
||
el-checkbox(v-model="launchDialog.desktop" style="float:left;margin-top:5px") Start as Desktop (No VR)
|
||
el-button(size="small" @click="showPreviousInstanceInfoDialog(launchDialog.location)") Info
|
||
el-button(size="small" @click="showInviteDialog(launchDialog.location)" :disabled="!checkCanInvite(launchDialog.location)") Invite
|
||
el-button(type="primary" size="small" @click="launchGame(launchDialog.location, launchDialog.secureOrShortName)" :disabled="!launchDialog.secureOrShortName") Launch
|
||
|
||
//- dialog: export friends list
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="exportFriendsListDialog" title="Export Friends List" width="650px")
|
||
el-input(type="textarea" v-if="exportFriendsListDialog" v-model="exportFriendsListContent" size="mini" rows="15" resize="none" readonly style="margin-top:15px" @click.native="$event.target.tagName === 'TEXTAREA' && $event.target.select()")
|
||
|
||
//- dialog: export avatars list
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="exportAvatarsListDialog" title="Export Own Avatars" width="650px")
|
||
el-input(type="textarea" v-if="exportAvatarsListDialog" v-model="exportAvatarsListContent" size="mini" rows="15" resize="none" readonly style="margin-top:15px" @click.native="$event.target.tagName === 'TEXTAREA' && $event.target.select()")
|
||
|
||
//- dialog: Discord username list
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="discordNamesDialogVisible" title="Discord Names" width="650px")
|
||
div(style='font-size:12px;')
|
||
| Click load missing entries in the Friends List tab to search entire friends list
|
||
el-input(type="textarea" v-if="discordNamesDialogVisible" v-model="discordNamesContent" size="mini" rows="15" resize="none" readonly style="margin-top:15px")
|
||
|
||
//- dialog: Notification position
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="notificationPositionDialog" :visible.sync="notificationPositionDialog.visible" title="Notification Position" width="400px")
|
||
div(style='font-size:12px;')
|
||
| Choose a notification position.
|
||
svg(version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 300 200" style="margin-top:15px;" xml:space="preserve")
|
||
path(style="fill:black;" d="M291.89,5A3.11,3.11,0,0,1,295,8.11V160.64a3.11,3.11,0,0,1-3.11,3.11H8.11A3.11,3.11,0,0,1,5,160.64V8.11A3.11,3.11,0,0,1,8.11,5H291.89m0-5H8.11A8.11,8.11,0,0,0,0,8.11V160.64a8.11,8.11,0,0,0,8.11,8.11H291.89a8.11,8.11,0,0,0,8.11-8.11V8.11A8.11,8.11,0,0,0,291.89,0Z")
|
||
rect(style="fill:#c4c4c4;" x="5" y="5" width="290" height="158.75" rx="2.5")
|
||
el-radio-group(v-model="notificationPosition" size="mini" @change="changeNotificationPosition")
|
||
el-radio(label="topLeft" v-model="notificationPosition" style="margin:0;position:absolute;left:35px;top:120px;")
|
||
el-radio(label="top" v-model="notificationPosition" style="margin:0;position:absolute;left:195px;top:120px;")
|
||
el-radio(label="topRight" v-model="notificationPosition" style="margin:0;position:absolute;right:25px;top:120px;")
|
||
el-radio(label="centerLeft" v-model="notificationPosition" style="margin:0;position:absolute;left:35px;top:200px;")
|
||
el-radio(label="center" v-model="notificationPosition" style="margin:0;position:absolute;left:195px;top:200px;")
|
||
el-radio(label="centerRight" v-model="notificationPosition" style="margin:0;position:absolute;right:25px;top:200px;")
|
||
el-radio(label="bottomLeft" v-model="notificationPosition" style="margin:0;position:absolute;left:35px;top:280px;")
|
||
el-radio(label="bottom" v-model="notificationPosition" style="margin:0;position:absolute;left:195px;top:280px;")
|
||
el-radio(label="bottomRight" v-model="notificationPosition" style="margin:0;position:absolute;right:25px;top:280px;")
|
||
template(#footer)
|
||
div(style="display:flex")
|
||
el-button(type="primary" size="small" style="margin-left:auto" @click="notificationPositionDialog.visible = false") OK
|
||
|
||
//- dialog: Noty feed filters
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="notyFeedFiltersDialog" :visible.sync="notyFeedFiltersDialog.visible" title="Notification Filters" width="550px")
|
||
.toggle-list
|
||
.toggle-item
|
||
span.toggle-name OnPlayerJoining
|
||
el-radio-group(v-model="sharedFeedFilters.noty.OnPlayerJoining" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name OnPlayerJoined
|
||
el-radio-group(v-model="sharedFeedFilters.noty.OnPlayerJoined" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name OnPlayerLeft
|
||
el-radio-group(v-model="sharedFeedFilters.noty.OnPlayerLeft" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Online
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Online" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Offline
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Offline" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name GPS
|
||
el-radio-group(v-model="sharedFeedFilters.noty.GPS" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Status
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Status" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Invite
|
||
el-radio-group(v-model="sharedFeedFilters.noty.invite" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Request Invite
|
||
el-radio-group(v-model="sharedFeedFilters.noty.requestInvite" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Invite Response
|
||
el-radio-group(v-model="sharedFeedFilters.noty.inviteResponse" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Request Invite Response
|
||
el-radio-group(v-model="sharedFeedFilters.noty.requestInviteResponse" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Friend Request
|
||
el-radio-group(v-model="sharedFeedFilters.noty.friendRequest" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name New Friend
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Friend" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Unfriend
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Unfriend" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Display Name
|
||
el-radio-group(v-model="sharedFeedFilters.noty.DisplayName" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Trust Level
|
||
el-radio-group(v-model="sharedFeedFilters.noty.TrustLevel" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Group Announcement
|
||
el-radio-group(v-model="sharedFeedFilters.noty['group.announcement']" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Group Join/Leave
|
||
el-radio-group(v-model="sharedFeedFilters.noty['group.informative']" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Group Invite
|
||
el-radio-group(v-model="sharedFeedFilters.noty['group.invite']" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Group Join Request
|
||
el-radio-group(v-model="sharedFeedFilters.noty['group.joinRequest']" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Portal Spawn
|
||
el-radio-group(v-model="sharedFeedFilters.noty.PortalSpawn" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Video Play
|
||
el-tooltip(placement="top" style="margin-left:5px" content="Requires VRCX YouTube API option enabled")
|
||
i.el-icon-warning
|
||
el-radio-group(v-model="sharedFeedFilters.noty.VideoPlay" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Events
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Event" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Blocked Player Joins
|
||
el-radio-group(v-model="sharedFeedFilters.noty.BlockedOnPlayerJoined" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Blocked Player Leaves
|
||
el-radio-group(v-model="sharedFeedFilters.noty.BlockedOnPlayerLeft" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Muted Player Joins
|
||
el-radio-group(v-model="sharedFeedFilters.noty.MutedOnPlayerJoined" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Muted Player Leaves
|
||
el-radio-group(v-model="sharedFeedFilters.noty.MutedOnPlayerLeft" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
template(v-if="photonLoggingEnabled")
|
||
br
|
||
.toggle-item
|
||
span.toggle-name Photon Event Logging
|
||
.toggle-item
|
||
span.toggle-name Lobby Avatar Change
|
||
el-radio-group(v-model="sharedFeedFilters.noty.AvatarChange" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Lobby ChatBox Message
|
||
el-radio-group(v-model="sharedFeedFilters.noty.ChatBoxMessage" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Blocked
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Blocked" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Unblocked
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Unblocked" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Muted
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Muted" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Unmuted
|
||
el-radio-group(v-model="sharedFeedFilters.noty.Unmuted" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelSharedFeedFilters") Cancel
|
||
el-button(type="primary" size="small" style="margin-left:10px" @click="saveSharedFeedFilters") Save
|
||
|
||
//- dialog: wrist feed filters
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="wristFeedFiltersDialog" :visible.sync="wristFeedFiltersDialog.visible" title="Wrist Feed Filters" width="550px")
|
||
.toggle-list
|
||
.toggle-item
|
||
span.toggle-name Self Location
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Location" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name OnPlayerJoining
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.OnPlayerJoining" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name OnPlayerJoined
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.OnPlayerJoined" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name OnPlayerLeft
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.OnPlayerLeft" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Online
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Online" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Offline
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Offline" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name GPS
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.GPS" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Status
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Status" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Invite
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.invite" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Request Invite
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.requestInvite" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Invite Response
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.inviteResponse" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Request Invite Response
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.requestInviteResponse" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Friend Request
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.friendRequest" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name New Friend
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Friend" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Unfriend
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Unfriend" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Display Name
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.DisplayName" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Trust Level
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.TrustLevel" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
.toggle-item
|
||
span.toggle-name Group Announcement
|
||
el-radio-group(v-model="sharedFeedFilters.wrist['group.announcement']" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Group Join/Leave
|
||
el-radio-group(v-model="sharedFeedFilters.wrist['group.informative']" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Group Invite
|
||
el-radio-group(v-model="sharedFeedFilters.wrist['group.invite']" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Group Join Request
|
||
el-radio-group(v-model="sharedFeedFilters.wrist['group.joinRequest']" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Portal Spawn
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.PortalSpawn" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Video Play
|
||
el-tooltip(placement="top" style="margin-left:5px" content="Requires VRCX YouTube API option enabled")
|
||
i.el-icon-warning
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.VideoPlay" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Events
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Event" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Blocked Player Joins
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.BlockedOnPlayerJoined" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Blocked Player Leaves
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.BlockedOnPlayerLeft" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Muted Player Joins
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.MutedOnPlayerJoined" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Muted Player Leaves
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.MutedOnPlayerLeft" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
template(v-if="photonLoggingEnabled")
|
||
br
|
||
.toggle-item
|
||
span.toggle-name Photon Event Logging
|
||
.toggle-item
|
||
span.toggle-name Lobby Avatar Change
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.AvatarChange" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Lobby ChatBox Message
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.ChatBoxMessage" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="VIP")
|
||
el-radio-button(label="Friends")
|
||
el-radio-button(label="Everyone")
|
||
.toggle-item
|
||
span.toggle-name Blocked
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Blocked" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Unblocked
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Unblocked" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Muted
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Muted" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
.toggle-item
|
||
span.toggle-name Unmuted
|
||
el-radio-group(v-model="sharedFeedFilters.wrist.Unmuted" size="mini")
|
||
el-radio-button(label="Off")
|
||
el-radio-button(label="On")
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelSharedFeedFilters") Cancel
|
||
el-button(type="primary" size="small" @click="saveSharedFeedFilters") Save
|
||
|
||
//- dialog: Edit Invite Message
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="editInviteMessageDialog" :visible.sync="editInviteMessageDialog.visible" title="Edit Invite Message" width="400px")
|
||
div(style='font-size:12px')
|
||
span 1 hour edit cool down time.
|
||
el-input(type="textarea" v-model="editInviteMessageDialog.newMessage" size="mini" maxlength="64" show-word-limit :autosize="{ minRows:2, maxRows:5 }" placeholder="" style="margin-top:10px")
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelEditInviteMessage") Cancel
|
||
el-button(type="primary" size="small" @click="saveEditInviteMessage") Save
|
||
|
||
//- dialog: Edit And Send Invite Response Message
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="editAndSendInviteResponseDialog" :visible.sync="editAndSendInviteResponseDialog.visible" title="Edit and Send Invite Message" width="400px")
|
||
div(style='font-size:12px')
|
||
span 1 hour edit cool down time.
|
||
el-input(type="textarea" v-model="editAndSendInviteResponseDialog.newMessage" size="mini" maxlength="64" show-word-limit :autosize="{ minRows:2, maxRows:5 }" placeholder="" style="margin-top:10px")
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelEditAndSendInviteResponse") Cancel
|
||
el-button(type="primary" size="small" @click="saveEditAndSendInviteResponse") Send
|
||
|
||
//- dialog Table: Send Invite Response Message
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="sendInviteResponseDialog" :visible.sync="sendInviteResponseDialogVisible" title="Send Invite Response Message" width="800px")
|
||
template(v-if="API.currentUser.$isVRCPlus")
|
||
input.inviteImageUploadButton(type="file" accept="image/png" @change="inviteImageUpload")
|
||
data-tables(v-if="sendInviteResponseDialogVisible" v-bind="inviteResponseMessageTable" @row-click="showSendInviteResponseConfirmDialog" style="margin-top:10px;cursor:pointer")
|
||
el-table-column(label="Slot" prop="slot" sortable="custom" width="70")
|
||
el-table-column(label="Message" prop="message")
|
||
el-table-column(label="Cool Down" prop="updatedAt" sortable="custom" width="110" align="right")
|
||
template(v-once #default="scope")
|
||
countdown-timer(:datetime="scope.row.updatedAt" :hours="1")
|
||
el-table-column(label="Action" width="70" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-edit" size="mini" @click="showEditAndSendInviteResponseDialog('response', scope.row)")
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelSendInviteResponse") Cancel
|
||
el-button(type="small" @click="API.refreshInviteMessageTableData('response')") Refresh
|
||
|
||
//- dialog Table: Send Invite Request Response Message
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="sendInviteRequestResponseDialog" :visible.sync="sendInviteRequestResponseDialogVisible" title="Send Invite Request Response Message" width="800px")
|
||
template(v-if="API.currentUser.$isVRCPlus")
|
||
input.inviteImageUploadButton(type="file" accept="image/png" @change="inviteImageUpload")
|
||
data-tables(v-if="sendInviteRequestResponseDialogVisible" v-bind="inviteRequestResponseMessageTable" @row-click="showSendInviteResponseConfirmDialog" style="margin-top:10px;cursor:pointer")
|
||
el-table-column(label="Slot" prop="slot" sortable="custom" width="70")
|
||
el-table-column(label="Message" prop="message")
|
||
el-table-column(label="Cool Down" prop="updatedAt" sortable="custom" width="110" align="right")
|
||
template(v-once #default="scope")
|
||
countdown-timer(:datetime="scope.row.updatedAt" :hours="1")
|
||
el-table-column(label="Action" width="70" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-edit" size="mini" @click="showEditAndSendInviteResponseDialog('requestResponse', scope.row)")
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelSendInviteRequestResponse") Cancel
|
||
el-button(type="small" @click="API.refreshInviteMessageTableData('requestResponse')") Refresh
|
||
|
||
//- dialog: Send Invite Response Message Confirm
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="sendInviteResponseConfirmDialog" :visible.sync="sendInviteResponseConfirmDialog.visible" title="Send Invite Response Message" width="400px")
|
||
div(style='font-size:12px')
|
||
span Are you sure you want to send?
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelInviteResponseConfirm") Cancel
|
||
el-button(type="primary" size="small" @click="sendInviteResponseConfirm") Confirm
|
||
|
||
//- dialog Table: Send Invite Message
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="sendInviteDialog" :visible.sync="sendInviteDialogVisible" title="Send Invite Message" width="800px")
|
||
template(v-if="API.currentUser.$isVRCPlus")
|
||
input.inviteImageUploadButton(type="file" accept="image/png" @change="inviteImageUpload")
|
||
data-tables(v-if="sendInviteDialogVisible" v-bind="inviteMessageTable" @row-click="showSendInviteConfirmDialog" style="margin-top:10px;cursor:pointer")
|
||
el-table-column(label="Slot" prop="slot" sortable="custom" width="70")
|
||
el-table-column(label="Message" prop="message")
|
||
el-table-column(label="Cool Down" prop="updatedAt" sortable="custom" width="110" align="right")
|
||
template(v-once #default="scope")
|
||
countdown-timer(:datetime="scope.row.updatedAt" :hours="1")
|
||
el-table-column(label="Action" width="70" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-edit" size="mini" @click="showEditAndSendInviteDialog('message', scope.row)")
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelSendInvite") Cancel
|
||
el-button(type="small" @click="API.refreshInviteMessageTableData('message')") Refresh
|
||
|
||
//- dialog Table: Send Invite Request Message
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="sendInviteRequestDialog" :visible.sync="sendInviteRequestDialogVisible" title="Send Invite Request Message" width="800px")
|
||
template(v-if="API.currentUser.$isVRCPlus")
|
||
input.inviteImageUploadButton(type="file" accept="image/png" @change="inviteImageUpload")
|
||
data-tables(v-if="sendInviteRequestDialogVisible" v-bind="inviteRequestMessageTable" @row-click="showSendInviteConfirmDialog" style="margin-top:10px;cursor:pointer")
|
||
el-table-column(label="Slot" prop="slot" sortable="custom" width="70")
|
||
el-table-column(label="Message" prop="message")
|
||
el-table-column(label="Cool Down" prop="updatedAt" sortable="custom" width="110" align="right")
|
||
template(v-once #default="scope")
|
||
countdown-timer(:datetime="scope.row.updatedAt" :hours="1")
|
||
el-table-column(label="Action" width="70" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-edit" size="mini" @click="showEditAndSendInviteDialog('request', scope.row)")
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelSendInviteRequest") Cancel
|
||
el-button(type="small" @click="API.refreshInviteMessageTableData('request')") Refresh
|
||
|
||
//- dialog: Send Invite Message Confirm
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="sendInviteConfirmDialog" :visible.sync="sendInviteConfirmDialog.visible" title="Send Invite Message" width="400px")
|
||
div(style='font-size:12px')
|
||
span Are you sure you want to send?
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelInviteConfirm") Cancel
|
||
el-button(type="primary" size="small" @click="sendInviteConfirm") Confirm
|
||
|
||
//- dialog: Edit And Send Invite Message
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="editAndSendInviteDialog" :visible.sync="editAndSendInviteDialog.visible" title="Edit and Send Invite Message" width="400px")
|
||
div(style='font-size:12px')
|
||
span 1 hour edit cool down time.
|
||
el-input(type="textarea" v-model="editAndSendInviteDialog.newMessage" size="mini" maxlength="64" show-word-limit :autosize="{ minRows:2, maxRows:5 }" placeholder="" style="margin-top:10px")
|
||
template(#footer)
|
||
el-button(type="small" @click="cancelEditAndSendInvite") Cancel
|
||
el-button(type="primary" size="small" @click="saveEditAndSendInvite") Send
|
||
|
||
//- dialog: Change avatar image
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="changeAvatarImageDialog" :visible.sync="changeAvatarImageDialogVisible" title="Change Avatar Image" width="800px")
|
||
div(v-if="changeAvatarImageDialogVisible" v-loading="changeAvatarImageDialogLoading")
|
||
input(type="file" accept="image/*" @change="onFileChangeAvatarImage" id="AvatarImageUploadButton" style="display:none")
|
||
span Recommended image size 1200x900px (4:3)
|
||
br
|
||
el-button-group(style="padding-bottom:10px;padding-top:10px")
|
||
el-button(type="default" size="small" @click="displayPreviousImages('Avatar', 'Change')" icon="el-icon-refresh") Refresh
|
||
el-button(type="default" size="small" @click="uploadAvatarImage" icon="el-icon-upload2") Upload Image
|
||
//- el-button(type="default" size="small" @click="deleteAvatarImage" icon="el-icon-delete") Delete Latest Image
|
||
br
|
||
div(style="display:inline-block" v-for="image in previousImagesTable" :key="image.version" v-if="image.file")
|
||
.x-change-image-item(@click="setAvatarImage(image)" style="cursor:pointer" :class="{ 'current-image': compareCurrentImage(image) }")
|
||
img.image(v-lazy="image.file.url")
|
||
|
||
//- dialog: Change world image
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="changeWorldImageDialog" :visible.sync="changeWorldImageDialogVisible" title="Change World Image" width="800px")
|
||
div(v-if="changeWorldImageDialogVisible" v-loading="changeWorldImageDialogLoading")
|
||
input(type="file" accept="image/*" @change="onFileChangeWorldImage" id="WorldImageUploadButton" style="display:none")
|
||
span Recommended image size 1200x900px (4:3)
|
||
br
|
||
el-button-group(style="padding-bottom:10px;padding-top:10px")
|
||
el-button(type="default" size="small" @click="displayPreviousImages('World', 'Change')" icon="el-icon-refresh") Refresh
|
||
el-button(type="default" size="small" @click="uploadWorldImage" icon="el-icon-upload2") Upload Image
|
||
//- el-button(type="default" size="small" @click="deleteWorldImage" icon="el-icon-delete") Delete Latest Image
|
||
br
|
||
div(style="display:inline-block" v-for="image in previousImagesTable" :key="image.version" v-if="image.file")
|
||
.x-change-image-item(@click="setWorldImage(image)" style="cursor:pointer" :class="{ 'current-image': compareCurrentImage(image) }")
|
||
img.image(v-lazy="image.file.url")
|
||
|
||
//- dialog: Display previous avatar/world images
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="previousImagesDialog" :visible.sync="previousImagesDialogVisible" title="Previous Images" width="800px")
|
||
div(v-if="previousImagesDialogVisible")
|
||
div(style="display:inline-block" v-for="image in previousImagesTable" :key="image.version" v-if="image.file")
|
||
el-popover.x-change-image-item(placement="right" width="500px" trigger="click")
|
||
img.x-link(slot="reference" v-lazy="image.file.url")
|
||
img.x-link(v-lazy="image.file.url" style="width:500px;height:375px" @click="downloadAndSaveImage(image.file.url)")
|
||
|
||
//- dialog: Gallery/VRCPlusIcons
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="galleryDialog" :visible.sync="galleryDialogVisible" title="Gallery and Icons" width="100%")
|
||
span(style="padding-bottom:10px") Recommended image size 1200x900px (4:3)
|
||
el-tabs(type="card")
|
||
el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogGalleryLoading")
|
||
span(slot="label") Gallery
|
||
span(style="color:#909399;font-size:12px;margin-left:5px") {{ galleryTable.length }}/64
|
||
input(type="file" accept="image/*" @change="onFileChangeGallery" id="GalleryUploadButton" style="display:none")
|
||
el-button-group
|
||
el-button(type="default" size="small" @click="refreshGalleryTable" icon="el-icon-refresh") Refresh
|
||
el-button(type="default" size="small" @click="displayGalleryUpload" icon="el-icon-upload2" :disabled="!API.currentUser.$isVRCPlus") Upload
|
||
el-button(type="default" size="small" @click="setProfilePicOverride('')" icon="el-icon-close" :disabled="!API.currentUser.profilePicOverride") Clear
|
||
br
|
||
.x-friend-item(v-if="image.versions && image.versions.length > 0" v-for="image in galleryTable" :key="image.id" style="display:inline-block;margin-top:10px;width:unset;cursor:default")
|
||
.vrcplus-icon(v-if="image.versions[image.versions.length - 1].file.url" @click="setProfilePicOverride(image.id)" :class="{ 'current-vrcplus-icon': compareCurrentProfilePic(image.id) }")
|
||
img.avatar(v-lazy="image.versions[image.versions.length - 1].file.url")
|
||
div(style="float:right;margin-top:5px")
|
||
el-button(type="default" @click="downloadAndSaveImage(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-paperclip" circle)
|
||
el-button(type="default" @click="deleteGalleryImage(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
el-tab-pane(v-if="galleryDialogVisible" v-loading="galleryDialogIconsLoading")
|
||
span(slot="label") Icons
|
||
span(style="color:#909399;font-size:12px;margin-left:5px") {{ VRCPlusIconsTable.length }}/64
|
||
input(type="file" accept="image/*" @change="onFileChangeVRCPlusIcon" id="VRCPlusIconUploadButton" style="display:none")
|
||
el-button-group
|
||
el-button(type="default" size="small" @click="refreshVRCPlusIconsTable" icon="el-icon-refresh") Refresh
|
||
el-button(type="default" size="small" @click="displayVRCPlusIconUpload" icon="el-icon-upload2" :disabled="!API.currentUser.$isVRCPlus") Upload
|
||
el-button(type="default" size="small" @click="setVRCPlusIcon('')" icon="el-icon-close" :disabled="!API.currentUser.userIcon") Clear
|
||
br
|
||
.x-friend-item(v-if="image.versions && image.versions.length > 0" v-for="image in VRCPlusIconsTable" :key="image.id" style="display:inline-block;margin-top:10px;width:unset;cursor:default")
|
||
.vrcplus-icon(v-if="image.versions[image.versions.length - 1].file.url" @click="setVRCPlusIcon(image.id)" :class="{ 'current-vrcplus-icon': compareCurrentVRCPlusIcon(image.id) }")
|
||
img.avatar(v-lazy="image.versions[image.versions.length - 1].file.url")
|
||
div(style="float:right;margin-top:5px")
|
||
el-button(type="default" @click="downloadAndSaveImage(image.versions[image.versions.length - 1].file.url)" size="mini" icon="el-icon-paperclip" circle)
|
||
el-button(type="default" @click="deleteVRCPlusIcon(image.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
|
||
|
||
//- dialog Table: Previous Instances User
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="previousInstancesUserDialog" :visible.sync="previousInstancesUserDialog.visible" title="Previous Instances" width="800px")
|
||
span(v-text="previousInstancesUserDialog.userRef.displayName" style="font-size:14px")
|
||
el-input(v-model="previousInstancesUserDialogTable.filters[0].value" placeholder="Search" style="display:block;width:150px;margin-top:15px")
|
||
data-tables(v-if="previousInstancesUserDialog.visible" v-bind="previousInstancesUserDialogTable" v-loading="previousInstancesUserDialog.loading" style="margin-top:10px")
|
||
el-table-column(label="Date" prop="created_at" sortable width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="left")
|
||
template(#content)
|
||
span {{ scope.row.created_at | formatDate('long') }}
|
||
span {{ scope.row.created_at | formatDate('short') }}
|
||
el-table-column(label="World" prop="name" sortable)
|
||
template(v-once #default="scope")
|
||
location(:location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName")
|
||
el-table-column(label="Instance Creator" prop="location" width="160")
|
||
template(v-once #default="scope")
|
||
display-name(:userid="scope.row.$location.userId" :location="scope.row.$location.tag" :key="previousInstancesUserDialog.forceUpdate")
|
||
el-table-column(label="Time" prop="time" width="90" sortable)
|
||
template(v-once #default="scope")
|
||
span(v-text="scope.row.timer")
|
||
el-table-column(label="Action" width="90" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-info" size="mini" @click="showLaunchDialog(scope.row.location)")
|
||
el-button(type="text" icon="el-icon-tickets" size="mini" @click="showPreviousInstanceInfoDialog(scope.row.location)")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click="confirmDeleteGameLogUserInstance(scope.row)")
|
||
|
||
//- dialog Table: Previous Instances World
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="previousInstancesWorldDialog" :visible.sync="previousInstancesWorldDialog.visible" title="Previous Instances" width="800px")
|
||
span(v-text="previousInstancesWorldDialog.worldRef.name" style="font-size:14px")
|
||
el-input(v-model="previousInstancesWorldDialogTable.filters[0].value" placeholder="Search" style="display:block;width:150px;margin-top:15px")
|
||
data-tables(v-if="previousInstancesWorldDialog.visible" v-bind="previousInstancesWorldDialogTable" v-loading="previousInstancesWorldDialog.loading" style="margin-top:10px")
|
||
el-table-column(label="Date" prop="created_at" sortable width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="left")
|
||
template(#content)
|
||
span {{ scope.row.created_at | formatDate('long') }}
|
||
span {{ scope.row.created_at | formatDate('short') }}
|
||
el-table-column(label="Instance Name" prop="name")
|
||
template(v-once #default="scope")
|
||
location-world(:locationobject="scope.row.$location" :grouphint="scope.row.groupName" :currentuserid="API.currentUser.id")
|
||
el-table-column(label="Instance Creator" prop="location")
|
||
template(v-once #default="scope")
|
||
display-name(:userid="scope.row.$location.userId" :location="scope.row.$location.tag" :key="previousInstancesWorldDialog.forceUpdate")
|
||
el-table-column(label="Time" prop="time" width="90" sortable)
|
||
template(v-once #default="scope")
|
||
span(v-text="scope.row.timer")
|
||
el-table-column(label="Action" width="90" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-tickets" size="mini" @click="showPreviousInstanceInfoDialog(scope.row.location)")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click="confirmDeleteGameLogWorldInstance(scope.row)")
|
||
|
||
//- dialog Table: Previous Instance Info
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="previousInstanceInfoDialog" :visible.sync="previousInstanceInfoDialog.visible" title="Previous Instance Info" width="800px")
|
||
location(:location="previousInstanceInfoDialog.$location.tag" style="font-size:14px")
|
||
el-input(v-model="previousInstanceInfoDialogTable.filters[0].value" placeholder="Search" style="display:block;width:150px;margin-top:15px")
|
||
data-tables(v-if="previousInstanceInfoDialog.visible" v-bind="previousInstanceInfoDialogTable" v-loading="previousInstanceInfoDialog.loading" style="margin-top:10px")
|
||
el-table-column(label="Date" prop="created_at" sortable width="120")
|
||
template(v-once #default="scope")
|
||
el-tooltip(placement="left")
|
||
template(#content)
|
||
span {{ scope.row.created_at | formatDate('long') }}
|
||
span {{ scope.row.created_at | formatDate('short') }}
|
||
el-table-column(label="Display Name" prop="displayName" sortable)
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.displayName" @click="lookupUser(scope.row)")
|
||
el-table-column(label="Time" prop="time" width="90" sortable)
|
||
template(v-once #default="scope")
|
||
span(v-text="scope.row.timer")
|
||
el-table-column(label="Count" prop="count" width="90" sortable)
|
||
template(v-once #default="scope")
|
||
span(v-text="scope.row.count")
|
||
|
||
//- dialog: export world list
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="worldExportDialogRef" :visible.sync="worldExportDialogVisible" title="World Favorites Export" width="650px")
|
||
el-dropdown(@click.native.stop trigger="click" size="small")
|
||
el-button(size="mini")
|
||
span(v-if="worldExportFavoriteGroup") {{ worldExportFavoriteGroup.displayName }} ({{ worldExportFavoriteGroup.count }}/{{ worldExportFavoriteGroup.capacity }}) #[i.el-icon-arrow-down.el-icon--right]
|
||
span(v-else) Select Group #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldExportGroup(null)") None
|
||
template(v-for="groupAPI in API.favoriteWorldGroups" :key="groupAPI.name")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldExportGroup(groupAPI)") {{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
|
||
el-dropdown(@click.native.stop trigger="click" size="small" style="margin-left:10px")
|
||
el-button(size="mini")
|
||
span(v-if="worldExportLocalFavoriteGroup") {{ worldExportLocalFavoriteGroup }} ({{ getLocalWorldFavoriteGroupLength(worldExportLocalFavoriteGroup) }}) #[i.el-icon-arrow-down.el-icon--right]
|
||
span(v-else) Select Group #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldExportLocalGroup(null)") None
|
||
template(v-for="group in localWorldFavoriteGroups" :key="group")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldExportLocalGroup(group)") {{ group }} ({{ localWorldFavorites[group].length }})
|
||
br
|
||
el-input(type="textarea" v-if="worldExportDialogVisible" v-model="worldExportContent" size="mini" rows="15" resize="none" readonly style="margin-top:15px" @click.native="$event.target.tagName === 'TEXTAREA' && $event.target.select()")
|
||
|
||
//- dialog: World import dialog
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="worldImportDialog" :visible.sync="worldImportDialog.visible" title="World Favorites Import" width="650px")
|
||
div(style="font-size:12px")
|
||
| Enter a list of world IDs
|
||
el-input(type="textarea" v-model="worldImportDialog.input" size="mini" rows="10" resize="none" style="margin-top:15px")
|
||
el-button(size="small" @click="processWorldImportList" :disabled="!worldImportDialog.input") Process List
|
||
span(v-if="worldImportDialog.progress" style="margin-top:10px") #[i.el-icon-loading(style="margin-right:5px")] Progress: {{ worldImportDialog.progress }}/{{ worldImportDialog.progressTotal }}
|
||
br
|
||
el-dropdown(@click.native.stop trigger="click" size="small" style="margin-right:5px")
|
||
el-button(size="mini")
|
||
span(v-if="worldImportDialog.worldImportFavoriteGroup") {{ worldImportDialog.worldImportFavoriteGroup.displayName }} ({{ worldImportDialog.worldImportFavoriteGroup.count }}/{{ worldImportDialog.worldImportFavoriteGroup.capacity }}) #[i.el-icon-arrow-down.el-icon--right]
|
||
span(v-else) Select Group #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
template(v-for="groupAPI in API.favoriteWorldGroups" :key="groupAPI.name")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldImportGroup(groupAPI)" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
|
||
el-dropdown(@click.native.stop trigger="click" size="small" style="margin:5px")
|
||
el-button(size="mini")
|
||
span(v-if="worldImportDialog.worldImportLocalFavoriteGroup") {{ worldImportDialog.worldImportLocalFavoriteGroup }} ({{ getLocalWorldFavoriteGroupLength(worldImportDialog.worldImportLocalFavoriteGroup) }}) #[i.el-icon-arrow-down.el-icon--right]
|
||
span(v-else) Select Group #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
template(v-for="group in localWorldFavoriteGroups" :key="group")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldImportLocalGroup(group)" ) {{ group }} ({{ getLocalWorldFavoriteGroupLength(group) }})
|
||
el-button(size="small" @click="importWorldImportTable" style="margin:5px" :disabled="worldImportTable.data.length === 0 || (!worldImportDialog.worldImportFavoriteGroup && !worldImportDialog.worldImportLocalFavoriteGroup)") Import Worlds
|
||
el-button(v-if="worldImportDialog.loading" size="small" @click="cancelWorldImport" style="margin-top:10px") Cancel
|
||
span(v-if="worldImportDialog.worldImportFavoriteGroup") {{ worldImportTable.data.length }} / {{ worldImportDialog.worldImportFavoriteGroup.capacity - worldImportDialog.worldImportFavoriteGroup.count }}
|
||
span(v-if="worldImportDialog.importProgress" style="margin:10px") #[i.el-icon-loading(style="margin-right:5px")] Import Progress: {{ worldImportDialog.importProgress }}/{{ worldImportDialog.importProgressTotal }}
|
||
br
|
||
el-button(size="small" @click="clearWorldImportTable") Clear Table
|
||
template(v-if="worldImportDialog.errors")
|
||
el-button(size="small" @click="worldImportDialog.errors = ''" style="margin-left:5px") Clear Errors
|
||
h2(style="font-weight:bold;margin:0") Errors:
|
||
pre(v-text="worldImportDialog.errors" style="white-space:pre-wrap;font-size:12px")
|
||
data-tables(v-if="worldImportDialog.visible" v-bind="worldImportTable" v-loading="worldImportDialog.loading" style="margin-top:10px")
|
||
el-table-column(label="Image" width="70" prop="thumbnailImageUrl")
|
||
template(v-once #default="scope")
|
||
el-popover(placement="right" height="500px" trigger="hover")
|
||
img.friends-list-avatar(slot="reference" v-lazy="scope.row.thumbnailImageUrl")
|
||
img.friends-list-avatar(v-lazy="scope.row.imageUrl" style="height:500px;cursor:pointer" @click="downloadAndSaveImage(scope.row.imageUrl)")
|
||
el-table-column(label="Name" prop="name")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.name" @click="showWorldDialog(scope.row.id)")
|
||
el-table-column(label="Author" width="120" prop="authorName")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.authorName" @click="showUserDialog(scope.row.authorId)")
|
||
el-table-column(label="Status" width="70" prop="releaseStatus")
|
||
template(v-once #default="scope")
|
||
span(v-text="scope.row.releaseStatus" v-if="scope.row.releaseStatus === 'public'" style="color:#67c23a")
|
||
span(v-text="scope.row.releaseStatus" v-else-if="scope.row.releaseStatus === 'private'" style="color:#f56c6c")
|
||
span(v-text="scope.row.releaseStatus" v-else)
|
||
el-table-column(label="Action" width="90" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click="deleteItemWorldImport(scope.row)")
|
||
|
||
//- dialog: export avatar list
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="avatarExportDialogRef" :visible.sync="avatarExportDialogVisible" title="Avatar Favorites Export" width="650px")
|
||
el-dropdown(@click.native.stop trigger="click" size="small")
|
||
el-button(size="mini")
|
||
span(v-if="avatarExportFavoriteGroup") {{ avatarExportFavoriteGroup.displayName }} ({{ avatarExportFavoriteGroup.count }}/{{ avatarExportFavoriteGroup.capacity }}) #[i.el-icon-arrow-down.el-icon--right]
|
||
span(v-else) All Favorites #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectAvatarExportGroup(null)") All Favorites
|
||
template(v-for="groupAPI in API.favoriteAvatarGroups" :key="groupAPI.name")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectAvatarExportGroup(groupAPI)") {{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
|
||
br
|
||
el-input(type="textarea" v-if="avatarExportDialogVisible" v-model="avatarExportContent" size="mini" rows="15" resize="none" readonly style="margin-top:15px" @click.native="$event.target.tagName === 'TEXTAREA' && $event.target.select()")
|
||
|
||
//- dialog: Avatar import dialog
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="avatarImportDialog" :visible.sync="avatarImportDialog.visible" title="Avatar Favorites Import" width="650px")
|
||
div(style="font-size:12px")
|
||
| Enter a list of avatar IDs
|
||
el-input(type="textarea" v-model="avatarImportDialog.input" size="mini" rows="10" resize="none" style="margin-top:15px")
|
||
el-button(size="small" @click="processAvatarImportList" :disabled="!avatarImportDialog.input") Process List
|
||
span(v-if="avatarImportDialog.progress" style="margin-top:10px") #[i.el-icon-loading(style="margin-right:5px")] Progress: {{ avatarImportDialog.progress }}/{{ avatarImportDialog.progressTotal }}
|
||
br
|
||
el-dropdown(@click.native.stop trigger="click" size="small")
|
||
el-button(size="mini")
|
||
span(v-if="avatarImportDialog.avatarImportFavoriteGroup") {{ avatarImportDialog.avatarImportFavoriteGroup.displayName }} ({{ avatarImportDialog.avatarImportFavoriteGroup.count }}/{{ avatarImportDialog.avatarImportFavoriteGroup.capacity }}) #[i.el-icon-arrow-down.el-icon--right]
|
||
span(v-else) Select Group #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
template(v-for="groupAPI in API.favoriteAvatarGroups" :key="groupAPI.name")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectAvatarImportGroup(groupAPI)" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
|
||
el-button(size="small" @click="importAvatarImportTable" style="margin:5px" :disabled="avatarImportTable.data.length === 0 || !avatarImportDialog.avatarImportFavoriteGroup") Import Avatars
|
||
el-button(v-if="avatarImportDialog.loading" size="small" @click="cancelAvatarImport" style="margin-top:10px") Cancel
|
||
span(v-if="avatarImportDialog.avatarImportFavoriteGroup") {{ avatarImportTable.data.length }} / {{ avatarImportDialog.avatarImportFavoriteGroup.capacity - avatarImportDialog.avatarImportFavoriteGroup.count }}
|
||
span(v-if="avatarImportDialog.importProgress" style="margin:10px") #[i.el-icon-loading(style="margin-right:5px")] Import Progress: {{ avatarImportDialog.importProgress }}/{{ avatarImportDialog.importProgressTotal }}
|
||
br
|
||
el-button(size="small" @click="clearAvatarImportTable") Clear Table
|
||
template(v-if="avatarImportDialog.errors")
|
||
el-button(size="small" @click="avatarImportDialog.errors = ''" style="margin-left:5px") Clear Errors
|
||
h2(style="font-weight:bold;margin:0") Errors:
|
||
pre(v-text="avatarImportDialog.errors" style="white-space:pre-wrap;font-size:12px")
|
||
data-tables(v-if="avatarImportDialog.visible" v-bind="avatarImportTable" v-loading="avatarImportDialog.loading" style="margin-top:10px")
|
||
el-table-column(label="Image" width="70" prop="thumbnailImageUrl")
|
||
template(v-once #default="scope")
|
||
el-popover(placement="right" height="500px" trigger="hover")
|
||
img.friends-list-avatar(slot="reference" v-lazy="scope.row.thumbnailImageUrl")
|
||
img.friends-list-avatar(v-lazy="scope.row.imageUrl" style="height:500px;cursor:pointer" @click="downloadAndSaveImage(scope.row.imageUrl)")
|
||
el-table-column(label="Name" prop="name")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.name" @click="showAvatarDialog(scope.row.id)")
|
||
el-table-column(label="Author" width="120" prop="authorName")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.authorName" @click="showUserDialog(scope.row.authorId)")
|
||
el-table-column(label="Status" width="70" prop="releaseStatus")
|
||
template(v-once #default="scope")
|
||
span(v-text="scope.row.releaseStatus" v-if="scope.row.releaseStatus === 'public'" style="color:#67c23a")
|
||
span(v-text="scope.row.releaseStatus" v-else-if="scope.row.releaseStatus === 'private'" style="color:#f56c6c")
|
||
span(v-text="scope.row.releaseStatus" v-else)
|
||
el-table-column(label="Action" width="90" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click="deleteItemAvatarImport(scope.row)")
|
||
|
||
//- dialog: export friend list
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="friendExportDialogRef" :visible.sync="friendExportDialogVisible" title="Friend Favorites Export" width="650px")
|
||
el-dropdown(@click.native.stop trigger="click" size="small")
|
||
el-button(size="mini")
|
||
span(v-if="friendExportFavoriteGroup") {{ friendExportFavoriteGroup.displayName }} ({{ friendExportFavoriteGroup.count }}/{{ friendExportFavoriteGroup.capacity }}) #[i.el-icon-arrow-down.el-icon--right]
|
||
span(v-else) All Favorites #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectFriendExportGroup(null)") All Favorites
|
||
template(v-for="groupAPI in API.favoriteFriendGroups" :key="groupAPI.name")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectFriendExportGroup(groupAPI)") {{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
|
||
br
|
||
el-input(type="textarea" v-if="friendExportDialogVisible" v-model="friendExportContent" size="mini" rows="15" resize="none" readonly style="margin-top:15px" @click.native="$event.target.tagName === 'TEXTAREA' && $event.target.select()")
|
||
|
||
//- dialog: Friend import dialog
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="friendImportDialog" :visible.sync="friendImportDialog.visible" title="Friend Favorites Import" width="650px")
|
||
div(style="font-size:12px")
|
||
| Enter a list of user IDs
|
||
el-input(type="textarea" v-model="friendImportDialog.input" size="mini" rows="10" resize="none" style="margin-top:15px")
|
||
el-button(size="small" @click="processFriendImportList" :disabled="!friendImportDialog.input") Process List
|
||
span(v-if="friendImportDialog.progress" style="margin-top:10px") #[i.el-icon-loading(style="margin-right:5px")] Progress: {{ friendImportDialog.progress }}/{{ friendImportDialog.progressTotal }}
|
||
br
|
||
el-dropdown(@click.native.stop trigger="click" size="small")
|
||
el-button(size="mini")
|
||
span(v-if="friendImportDialog.friendImportFavoriteGroup") {{ friendImportDialog.friendImportFavoriteGroup.displayName }} ({{ friendImportDialog.friendImportFavoriteGroup.count }}/{{ friendImportDialog.friendImportFavoriteGroup.capacity }}) #[i.el-icon-arrow-down.el-icon--right]
|
||
span(v-else) Select Group #[i.el-icon-arrow-down.el-icon--right]
|
||
el-dropdown-menu(#default="dropdown")
|
||
template(v-for="groupAPI in API.favoriteFriendGroups" :key="groupAPI.name")
|
||
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectFriendImportGroup(groupAPI)" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
|
||
el-button(size="small" @click="importFriendImportTable" style="margin:5px" :disabled="friendImportTable.data.length === 0 || !friendImportDialog.friendImportFavoriteGroup") Import Friends
|
||
el-button(v-if="friendImportDialog.loading" size="small" @click="cancelFriendImport" style="margin-top:10px") Cancel
|
||
span(v-if="friendImportDialog.friendImportFavoriteGroup") {{ friendImportTable.data.length }} / {{ friendImportDialog.friendImportFavoriteGroup.capacity - friendImportDialog.friendImportFavoriteGroup.count }}
|
||
span(v-if="friendImportDialog.importProgress" style="margin:10px") #[i.el-icon-loading(style="margin-right:5px")] Import Progress: {{ friendImportDialog.importProgress }}/{{ friendImportDialog.importProgressTotal }}
|
||
br
|
||
el-button(size="small" @click="clearFriendImportTable") Clear Table
|
||
template(v-if="friendImportDialog.errors")
|
||
el-button(size="small" @click="friendImportDialog.errors = ''" style="margin-left:5px") Clear Errors
|
||
h2(style="font-weight:bold;margin:0") Errors:
|
||
pre(v-text="friendImportDialog.errors" style="white-space:pre-wrap;font-size:12px")
|
||
data-tables(v-if="friendImportDialog.visible" v-bind="friendImportTable" v-loading="friendImportDialog.loading" style="margin-top:10px")
|
||
el-table-column(label="Image" width="70" prop="currentAvatarThumbnailImageUrl")
|
||
template(v-once #default="scope")
|
||
el-popover(placement="right" height="500px" trigger="hover")
|
||
img.friends-list-avatar(slot="reference" v-lazy="userImage(scope.row)")
|
||
img.friends-list-avatar(v-lazy="userImageFull(scope.row)" style="height:500px;cursor:pointer" @click="downloadAndSaveImage(userImageFull(scope.row))")
|
||
el-table-column(label="Name" prop="displayName")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.displayName" @click="showUserDialog(scope.row.id)")
|
||
el-table-column(label="Action" width="90" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click="deleteItemFriendImport(scope.row)")
|
||
|
||
//- dialog: Note export dialog
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="noteExportDialog" :visible.sync="noteExportDialog.visible" title="Note Export" width="1000px")
|
||
div(style="font-size:12px")
|
||
| This process will export all of your VRCX memos and import them into VRChat notes. #[br]
|
||
| Be warned of the following limitations: #[br]
|
||
| - API endpoint has a rate limit that requires a large delay between requests. #[br]
|
||
| - Character limit of 256 per note. #[br]
|
||
| - Swear words filter (no fun allowed). #[br]
|
||
| - No new lines (they will replaced with a space). #[br]
|
||
| - This will overwrite any existing VRChat notes for these users. #[br]
|
||
| - Any edits made here wont affect VRCX memos but will affect VRChat notes once exported. #[br]
|
||
el-button(size="small" @click="updateNoteExportDialog" :disabled="noteExportDialog.loading" style="margin-top:10px") Refresh
|
||
el-button(size="small" @click="exportNoteExport" :disabled="noteExportDialog.loading" style="margin-top:10px") Export
|
||
el-button(v-if="noteExportDialog.loading" size="small" @click="cancelNoteExport" style="margin-top:10px") Cancel
|
||
span(v-if="noteExportDialog.loading" style="margin:10px") #[i.el-icon-loading(style="margin-right:5px")] Progress: {{ noteExportDialog.progress }}/{{ noteExportDialog.progressTotal }}
|
||
template(v-if="noteExportDialog.errors")
|
||
el-button(size="small" @click="noteExportDialog.errors = ''") Clear Errors
|
||
h2(style="font-weight:bold;margin:0") Errors:
|
||
pre(v-text="noteExportDialog.errors" style="white-space:pre-wrap;font-size:12px")
|
||
data-tables(v-if="noteExportDialog.visible" v-bind="noteExportTable" v-loading="noteExportDialog.loading" style="margin-top:10px")
|
||
el-table-column(label="Image" width="70" prop="currentAvatarThumbnailImageUrl")
|
||
template(v-once #default="scope")
|
||
el-popover(placement="right" height="500px" trigger="hover")
|
||
img.friends-list-avatar(slot="reference" v-lazy="userImage(scope.row.ref)")
|
||
img.friends-list-avatar(v-lazy="userImageFull(scope.row.ref)" style="height:500px;cursor:pointer" @click="downloadAndSaveImage(userImageFull(scope.row.ref))")
|
||
el-table-column(label="Name" width="170" prop="name")
|
||
template(v-once #default="scope")
|
||
span.x-link(v-text="scope.row.name" @click="showUserDialog(scope.row.id)")
|
||
el-table-column(label="Note" prop="memo")
|
||
template(v-once #default="scope")
|
||
el-input(v-model="scope.row.memo" type="textarea" maxlength="256" show-word-limit :rows="2" :autosize="{ minRows: 1, maxRows: 10 }" size="mini" resize="none")
|
||
el-table-column(label="Skip Export" width="90" align="right")
|
||
template(v-once #default="scope")
|
||
el-button(type="text" icon="el-icon-close" size="mini" @click="removeFromNoteExportTable(scope.row)")
|
||
|
||
//- dialog: avatar database provider
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="avatarProviderDialog" :visible.sync="avatarProviderDialog.visible" title="Avatar Database Provider" width="600px")
|
||
div
|
||
el-input(v-for="(provider, index) in avatarRemoteDatabaseProviderList" :key="index" :value="provider" v-model="avatarRemoteDatabaseProviderList[index]" @change="saveAvatarProviderList" size="small" style="margin-top:5px")
|
||
el-button(slot="append" icon="el-icon-delete" @click="removeAvatarProvider(provider)")
|
||
el-button(@click="avatarRemoteDatabaseProviderList.push('')" size="mini" style="margin-top:5px") Add Provider
|
||
|
||
//- dialog: chatbox blacklist
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="chatboxBlacklistDialog" :visible.sync="chatboxBlacklistDialog.visible" title="Chatbox Blacklist" width="600px")
|
||
div(v-loading="chatboxBlacklistDialog.loading" v-if="chatboxBlacklistDialog.visible")
|
||
h2 Keyword Blacklist
|
||
el-input(v-for="(item, index) in chatboxBlacklist" :key="index" :value="item" v-model="chatboxBlacklist[index]" size="small" style="margin-top:5px" @change="saveChatboxBlacklist")
|
||
el-button(slot="append" icon="el-icon-delete" @click="chatboxBlacklist.splice(index, 1); saveChatboxBlacklist()")
|
||
el-button(@click="chatboxBlacklist.push('')" size="mini" style="margin-top:5px") Add Item
|
||
br
|
||
h2 User Blacklist
|
||
el-tag(v-for="user in chatboxUserBlacklist" type="info" disable-transitions="true" :key="user[0]" style="margin-right:5px;margin-top:5px" closable @close="deleteChatboxUserBlacklist(user[0])")
|
||
span {{user[1]}}
|
||
|
||
//- dialog: invite group
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="inviteGroupDialog" :visible.sync="inviteGroupDialog.visible" title="Invite To Group" width="450px")
|
||
div(v-if="inviteGroupDialog.visible" v-loading="inviteGroupDialog.loading")
|
||
span Don't spam invite users, inviting too many users to a group is known to cause a ban.
|
||
br
|
||
el-select(v-model="inviteGroupDialog.groupId" clearable placeholder="Choose Group" filterable :disabled="inviteGroupDialog.loading" @change="isAllowedToInviteToGroup" style="margin-top:15px")
|
||
el-option-group(v-if="inviteGroupDialog.groups.length" label="Groups" style="width:410px")
|
||
el-option.x-friend-item(v-for="group in inviteGroupDialog.groups" :key="group.id" :label="group.name" :value="group.id" style="height:auto")
|
||
.avatar
|
||
img(v-lazy="group.iconUrl")
|
||
.detail
|
||
span.name(v-text="group.name")
|
||
el-select(v-model="inviteGroupDialog.userIds" clearable placeholder="Choose Friends" filterable :disabled="inviteGroupDialog.loading" style="width:100%;margin-top:15px")
|
||
el-option-group(v-if="inviteGroupDialog.userId" label="Selected User")
|
||
el-option.x-friend-item(:key="inviteGroupDialog.userObject.id" :label="inviteGroupDialog.userObject.displayName" :value="inviteGroupDialog.userObject.id" style="height:auto")
|
||
template(v-if="inviteGroupDialog.userObject.id")
|
||
.avatar(:class="userStatusClass(inviteGroupDialog.userObject)")
|
||
img(v-lazy="userImage(inviteGroupDialog.userObject)")
|
||
.detail
|
||
span.name(v-text="inviteGroupDialog.userObject.displayName" :style="{'color':inviteGroupDialog.userObject.$userColour}")
|
||
span(v-else v-text="inviteGroupDialog.userId")
|
||
el-option-group(v-if="friendsGroup0.length" label="VIP")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup0" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar(:class="userStatusClass(friend.ref)")
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
el-option-group(v-if="friendsGroup1.length" label="ONLINE")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup1" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar(:class="userStatusClass(friend.ref)")
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
el-option-group(v-if="friendsGroup2.length" label="ACTIVE")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup2" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
el-option-group(v-if="friendsGroup3.length" label="OFFLINE")
|
||
el-option.x-friend-item(v-for="friend in friendsGroup3" :key="friend.id" :label="friend.name" :value="friend.id" style="height:auto")
|
||
template(v-if="friend.ref")
|
||
.avatar
|
||
img(v-lazy="userImage(friend.ref)")
|
||
.detail
|
||
span.name(v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}")
|
||
span(v-else v-text="friend.id")
|
||
template(#footer)
|
||
el-button(type="primary" size="small" :disabled="inviteGroupDialog.loading || !inviteGroupDialog.userIds.length" @click="sendGroupInvite()") Invite
|
||
|
||
//- dialog: open source software notice
|
||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="ossDialog" title="Open Source Software Notice" width="650px")
|
||
div(v-if="ossDialog" style="height:350px;overflow:hidden scroll;word-break:break-all")
|
||
div
|
||
span VRCX is based on open source software. It was possible because of their contribution.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") animate.css
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
The MIT License (MIT)
|
||
|
||
Copyright (c) 2019 Daniel Eden
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") CefSharp
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
// Copyright © The CefSharp Authors. All rights reserved.
|
||
//
|
||
// Redistribution and use in source and binary forms, with or without
|
||
// modification, are permitted provided that the following conditions are
|
||
// met:
|
||
//
|
||
// * Redistributions of source code must retain the above copyright
|
||
// notice, this list of conditions and the following disclaimer.
|
||
//
|
||
// * Redistributions in binary form must reproduce the above
|
||
// copyright notice, this list of conditions and the following disclaimer
|
||
// in the documentation and/or other materials provided with the
|
||
// distribution.
|
||
//
|
||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||
// Framework nor the name CefSharp nor the names of its contributors
|
||
// may be used to endorse or promote products derived from this software
|
||
// without specific prior written permission.
|
||
//
|
||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") DiscordRichPresence
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
MIT License
|
||
|
||
Copyright (c) 2018 Lachee
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") element
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
The MIT License (MIT)
|
||
|
||
Copyright (c) 2016-present ElemeFE
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") librsync.net
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
The MIT License (MIT)
|
||
|
||
Copyright (c) 2015 Brad Dodson
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") Newtonsoft.Json
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
The MIT License (MIT)
|
||
|
||
Copyright (c) 2007 James Newton-King
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") normalize
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
The MIT License (MIT)
|
||
|
||
Copyright © Nicolas Gallagher and Jonathan Neal
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") noty
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
Copyright (c) 2012 Nedim Arabacı
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining
|
||
a copy of this software and associated documentation files (the
|
||
"Software"), to deal in the Software without restriction, including
|
||
without limitation the rights to use, copy, modify, merge, publish,
|
||
distribute, sublicense, and/or sell copies of the Software, and to
|
||
permit persons to whom the Software is furnished to do so, subject to
|
||
the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be
|
||
included in all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") OpenVR SDK
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
Copyright (c) 2015, Valve Corporation
|
||
All rights reserved.
|
||
|
||
Redistribution and use in source and binary forms, with or without modification,
|
||
are permitted provided that the following conditions are met:
|
||
|
||
1. Redistributions of source code must retain the above copyright notice, this
|
||
list of conditions and the following disclaimer.
|
||
|
||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||
this list of conditions and the following disclaimer in the documentation and/or
|
||
other materials provided with the distribution.
|
||
|
||
3. Neither the name of the copyright holder nor the names of its contributors
|
||
may be used to endorse or promote products derived from this software without
|
||
specific prior written permission.
|
||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") Twemoji
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
MIT License
|
||
|
||
Copyright (c) 2021 Twitter
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") SharpDX
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
Copyright (c) 2010-2014 SharpDX - Alexandre Mutel
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
THE SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") vue
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
The MIT License (MIT)
|
||
|
||
Copyright (c) 2013-present, Yuxi (Evan) You
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
THE SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") vue-data-tables
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
The MIT License (MIT)
|
||
|
||
Copyright (c) 2018 Leon Zhang
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.
|
||
div(style="margin-top:15px")
|
||
p(style="font-weight:bold") vue-lazyload
|
||
pre(style="font-size:12px;white-space:pre-line").
|
||
The MIT License (MIT)
|
||
|
||
Copyright (c) 2016 Awe
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.
|
||
|
||
//- dialog: Enable primary password
|
||
el-dialog.x-dialog(
|
||
:visible.sync="enablePrimaryPasswordDialog.visible"
|
||
:before-close="enablePrimaryPasswordDialog.beforeClose"
|
||
ref="primaryPasswordDialog"
|
||
:close-on-click-modal="false"
|
||
title="Primary Password Required"
|
||
width="400px"
|
||
)
|
||
el-input(
|
||
v-model="enablePrimaryPasswordDialog.password"
|
||
placeholder="Input new password"
|
||
type="password"
|
||
size="mini"
|
||
maxlength="32"
|
||
show-password
|
||
autofocus
|
||
)
|
||
el-input(
|
||
v-model="enablePrimaryPasswordDialog.rePassword"
|
||
placeholder="Re-input password"
|
||
type="password"
|
||
style="margin-top:5px"
|
||
size="mini"
|
||
maxlength="32"
|
||
show-password
|
||
)
|
||
template(#footer)
|
||
el-button(
|
||
type="primary" size="small" @click="setPrimaryPassword"
|
||
:disabled="enablePrimaryPasswordDialog.password.length===0||enablePrimaryPasswordDialog.password!==enablePrimaryPasswordDialog.rePassword"
|
||
) OK
|
||
script(src="vendor.js")
|
||
script(src="app.js")
|