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") div(style="width:300px;margin:auto" v-loading="loginForm.loading") 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 div(style="text-align:center;font-size:12px") 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 is not 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="openExternalLink(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 span.x-link(v-if="currentInstanceLocation.instanceName" @click="showLaunchDialog(lastLocation.location)") span \#{{ currentInstanceLocation.instanceName }} {{ currentInstanceLocation.accessType }} span.flags(v-if="currentInstanceLocation.region" :class="currentInstanceLocation.region" style="display:inline-block;margin-left:5px") span.flags(v-else class="us" style="display:inline-block;margin-left:5px") i.el-icon-lock(v-if="currentInstanceLocation.strict" style="display:inline-block;margin-left:5px") span(v-if="lastLocation.playerList.size > 0" style="margin-left:5px") | {{ lastLocation.playerList.size }} | #[template(v-if="lastLocation.friendList.size > 0") ({{ lastLocation.friendList.size }})] template(v-if="photonLobbyBots.length > 0") |   el-tooltip(placement="bottom") template(#content) span Photon Bots: div(v-for="id in photonLobbyBots" :key="id" placement="top") span.x-link(v-text="getDisplayNameFromPhotonId(id)" @click="showUserFromPhotonId(id)" style="margin-right:5px") span(v-text="photonLobbyBots.length" style="color:red") |  #[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.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="openExternalLink(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") 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 !== undefined") 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="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)") div.photon-event-table(v-if="photonLoggingEnabled") div(style="position:absolute;margin-left:195px;z-index:1") el-select(v-model="photonEventTableTypeFilter" @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") el-input(v-model="photonEventTableFilter" @input="photonEventTableFilterChange" placeholder="Search" clearable style="width:150px;margin-left:10px") 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="Name" 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="Event" prop="text") template(v-once #default="scope") template(v-if="scope.row.type === 'AvatarChange'") span ChangeAvatar span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)") |   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'") span 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)" style="margin-left:10px") 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:10px") span.x-link(v-else-if="scope.row.type === 'PortalSpawn'" @click="showWorldDialog(scope.row.location, scope.row.shortName)") | PortalSpawn #[location(:location="scope.row.location" :hint="scope.row.worldName" :link="false")] span(v-else-if="scope.row.type === 'ChatBoxMessage'") | ChatBox #[span(v-text="scope.row.text")] span(v-else-if="scope.row.type === 'OnPlayerJoined'") | has joined - #[span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)")]  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="Name" 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="Event" prop="text") template(v-once #default="scope") span(v-if="scope.row.type === 'AvatarChange'") span ChangeAvatar span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)") |   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'") span 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)" style="margin-left:10px") 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:10px") span.x-link(v-else-if="scope.row.type === 'PortalSpawn'" @click="showWorldDialog(scope.row.location, scope.row.shortName)") | PortalSpawn #[location(:location="scope.row.location" :hint="scope.row.worldName" :link="false")] span(v-else-if="scope.row.type === 'ChatBoxMessage'") | ChatBox #[span(v-text="scope.row.text")] span(v-else-if="scope.row.type === 'OnPlayerJoined'") | has joined - #[span.x-link(v-text="scope.row.avatar.name" @click="showAvatarDialog(scope.row.avatar.id)")]  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") //- 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']" :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") template(v-else-if="scope.row.type === 'Offline'") template(v-if="scope.row.location") location(:location="scope.row.location" :hint="scope.row.worldName") 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") 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") 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") 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") 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") //- 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") location(v-else-if="scope.row.type === 'PortalSpawn'" :location="scope.row.instanceId" :hint="scope.row.worldName") 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" :class="user.trustClass") span.extra(v-text="user.username" style="font-family:monospace") 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'" v-if="$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()" size="small" icon="el-icon-refresh" circle style="position:relative;float:right;z-index:1") el-tabs(type="card" v-loading="API.isFavoriteLoading") el-tab-pane(label="Friends") el-collapse(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(style="border:0") el-button(size="small" @click="showWorldExportDialog") Export el-button(size="small" @click="showWorldImportDialog") Import 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") el-tab-pane(label="Avatars") el-collapse(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', 'hideAvatar', 'showAvatar', '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']" :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="150") template(v-once #default="scope") el-tooltip(placement="top" v-if="scope.row.type === 'invite'") template(#content) location(v-if="scope.row.details" :location="scope.row.details.worldId" :hint="scope.row.details.worldName" :link="false") span.x-link(v-text="scope.row.type" @click="showWorldDialog(scope.row.details.worldId)") 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="openExternalLink(scope.row.details.imageUrl)") el-table-column(label="Message" prop="message") template(v-once #default="scope") span(v-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-if="scope.row.type !== 'requestInviteResponse' && scope.row.type !== 'inviteResponse' && scope.row.type !== 'message'") 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'") 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" v-if="item !== 'sdk2'" 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") 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(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="openExternalLink(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="User Name" min-width="120" prop="username" sortable :sort-method="(a, b) => sortAlphabetically(a, b, 'username')") 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()") Check for update 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(style="margin-top:45px;border-top:1px solid #eee;padding-top:30px") span.header Legal Notice div.options-container-item p © 2019-2022 #[a(href="https://github.com/pypy-vrc" target="_blank") pypy] (mina#5656) 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 is not 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="saveOpenVROption") 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(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 Hide Private Worlds el-switch(v-model="hidePrivateFromFeed" @change="saveOpenVROption") div.options-container-item span.name(style="min-width:137px") Overlay Button el-switch(v-model="overlaybutton" @change="saveOpenVROption" inactive-text="Grip" active-text="Menu" :disabled="!openVR || !overlayWrist") 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.header Application div.options-container-item span.name(style="min-width:236px") Encrypt password (disables auto login) el-switch(v-model="enablePrimaryPassword" @change="enablePrimaryPasswordChange" :disabled="!loginForm.savedCredentials[API.currentUser.username]") 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 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 Show Join/Leave el-switch(v-model="photonEventOverlayJoinLeave" @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-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") 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 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}") location.extra(: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="openExternalLink(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="openExternalLink(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") el-popover(placement="top" trigger="click") span(slot="reference" v-text="userDialog.ref.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") {{ userDialog.ref.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="openExternalLink(userDialog.ref.userIcon)") div(style="flex:none") 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) ? '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-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(v-if="userDialog.isHideAvatar" icon="el-icon-user-solid" command="Show Avatar" style="color:#F56C6C") Show Avatar el-dropdown-item(v-else icon="el-icon-user" command="Hide Avatar") 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) 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 Bio pre.extra(style="font-family:inherit;font-size:12px;white-space:pre-wrap;margin:0 0.5em 0 0") {{ userDialog.ref.bio || '-' }} 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="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 }}/100 .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="openExternalLink(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="Remove from favorites" :disabled="hideTooltips") el-button(type="warning" icon="el-icon-star-on" circle @click="worldDialogCommand('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="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") span.x-link(@click="showLaunchDialog(room.$location.tag, room.$location.shortName)") i.el-icon-unlock(v-if="(room.$location.shortName && worldDialog.$location.shortName === room.$location.shortName) || API.currentUser.id === room.$location.userId" style="display:inline-block;margin-right:5px") span \#{{ room.$location.instanceName }} {{ room.$location.accessType }} span.flags(v-if="room.$location.region" :class="room.$location.region" style="display:inline-block;margin-left:5px") span.flags(v-else class="us" style="display:inline-block;margin-left:5px") i.el-icon-lock(v-if="room.$location.strict" style="display:inline-block;margin-left:5px") 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="openExternalLink(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="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-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.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: 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") el-button(v-for="group in favoriteDialog.groups" :key="group.name" style="display:block;width:100%;margin:10px 0" @click="addFavorite(group)") {{ group.displayName }} ({{ group.count }} / {{ group.capacity }}) //- 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="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") 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="friendsGroup2.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="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 Portal Spawn el-tooltip(placement="top" style="margin-left:5px" content="Requires '--enable-sdk-log-levels' steam launch option (click for more info)") i.el-icon-warning(style="cursor:pointer" @click="openExternalLink(recommendedSteamParams)") 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 Portal Spawn el-tooltip(placement="top" style="margin-left:5px" content="Requires '--enable-sdk-log-levels' steam launch option (click for more info)") i.el-icon-warning(style="cursor:pointer" @click="openExternalLink(recommendedSteamParams)") 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="openExternalLink(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-for="image in galleryTable" :key="image.id" style="display:inline-block;margin-top:10px;width:unset;cursor:default") .vrcplus-icon(v-if="image.versions[1].file.url" @click="setProfilePicOverride(image.id)" :class="{ 'current-vrcplus-icon': compareCurrentProfilePic(image.id) }") img.avatar(v-lazy="image.versions[1].file.url") div(style="float:right;margin-top:5px") el-button(type="default" @click="openExternalLink(image.versions[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-for="image in VRCPlusIconsTable" :key="image.id" style="display:inline-block;margin-top:10px;width:unset;cursor:default") .vrcplus-icon(v-if="image.versions[1].file.url" @click="setVRCPlusIcon(image.id)" :class="{ 'current-vrcplus-icon': compareCurrentVRCPlusIcon(image.id) }") img.avatar(v-lazy="image.versions[1].file.url") div(style="float:right;margin-top:5px") el-button(type="default" @click="openExternalLink(image.versions[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.name") 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") span.x-link(@click="showLaunchDialog(scope.row.location)") span \#{{ scope.row.$location.instanceName }} {{ scope.row.$location.accessType }} span.flags(v-if="scope.row.$location.region" :class="scope.row.$location.region" style="display:inline-block;margin-left:5px") span.flags(v-else class="us" style="display:inline-block;margin-left:5px") i.el-icon-lock(v-if="scope.row.$location.strict" style="display:inline-block;margin-left:5px") 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) 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="selectWorldExportGroup(null)") All Favorites template(v-for="groupAPI in API.favoriteWorldGroups" :key="groupAPI.name") el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldExportGroup(groupAPI)" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }}) 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") 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-button(size="small" @click="importWorldImportTable" style="margin:5px" :disabled="worldImportTable.data.length === 0 || !worldImportDialog.worldImportFavoriteGroup") 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="openExternalLink(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)" :disabled="groupAPI.count >= groupAPI.capacity") {{ 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="openExternalLink(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)" :disabled="groupAPI.count >= groupAPI.capacity") {{ 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="openExternalLink(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="openExternalLink(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: 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")