feat: groups sidebar collapsible (#1094)

* wip

* wip

* add prettier formatter config for pug files

* feat: groups sidebar collapsible (#1079)

* rm old code
This commit is contained in:
pa
2025-01-25 01:30:07 +09:00
committed by GitHub
parent 5c9840ca5e
commit 51a1897a76
7 changed files with 472 additions and 163 deletions
+311 -149
View File
@@ -1,181 +1,343 @@
mixin friendsListSidebar()
.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="$t('side_panel.search_placeholder')" 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")
mixin friendsListSidebar
#aside.x-aside-container(v-show='$refs.menu && $refs.menu.activeIndex !== \'friendsList\'')
div(style='display: flex; align-items: baseline')
el-select(
v-model='quickSearch'
clearable
:placeholder='$t("side_panel.search_placeholder")'
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")
template(v-if='item.ref')
.detail
span.name(v-text="item.ref.displayName" :style="{'color':item.ref.$userColour}")
span.extra(v-if="!item.ref.isFriend")
span.extra(v-else-if="item.ref.state === 'offline'") {{ $t('side_panel.search_result_active') }}
span.extra(v-else-if="item.ref.state === 'active'") {{ $t('side_panel.search_result_offline') }}
location.extra(v-else :location="item.ref.location" :traveling="item.ref.travelingToLocation" :link="false")
img.avatar(v-lazy="userImage(item.ref)")
span(v-else) {{ $t('side_panel.search_result_more') }} #[span(v-text="item.label" style="font-weight:bold")]
el-tooltip(placement="bottom" :content="$t('side_panel.direct_access_tooltip')" :disabled="hideTooltips")
el-button(type="default" @click="directAccessPaste" size="mini" icon="el-icon-discover" circle)
el-tooltip(placement="bottom" :content="$t('side_panel.refresh_tooltip')" :disabled="hideTooltips")
el-button(type="default" @click="refreshFriendsList" :loading="API.isRefreshFriendsLoading" size="mini" icon="el-icon-refresh" circle style="margin-right:10px")
el-tabs.zero-margin-tabs(stretch="true" style="height:calc(100% - 60px;margin-top:5px")
span.name(v-text='item.ref.displayName' :style='{ color: item.ref.$userColour }')
span.extra(v-if='!item.ref.isFriend')
span.extra(v-else-if='item.ref.state === "offline"') {{ $t('side_panel.search_result_active') }}
span.extra(v-else-if='item.ref.state === "active"') {{ $t('side_panel.search_result_offline') }}
location.extra(
v-else
:location='item.ref.location'
:traveling='item.ref.travelingToLocation'
:link='false')
img.avatar(v-lazy='userImage(item.ref)')
span(v-else) {{ $t('side_panel.search_result_more') }} #[span(v-text='item.label' style='font-weight: bold')]
el-tooltip(placement='bottom' :content='$t("side_panel.direct_access_tooltip")' :disabled='hideTooltips')
el-button(type='default' @click='directAccessPaste' size='mini' icon='el-icon-discover' circle)
el-tooltip(placement='bottom' :content='$t("side_panel.refresh_tooltip")' :disabled='hideTooltips')
el-button(
type='default'
@click='refreshFriendsList'
:loading='API.isRefreshFriendsLoading'
size='mini'
icon='el-icon-refresh'
circle
style='margin-right: 10px')
el-tabs.zero-margin-tabs(stretch='true' style='height: calc(100% - 60px); margin-top: 5px')
el-tab-pane
template(#label)
span {{ $t('side_panel.friends') }}
span(style="color:#909399;font-size:12px;margin-left:10px") ({{ onlineFriendCount }}/{{ friends.size }})
.x-friend-list(style="padding:10px 5px")
.x-friend-group.x-link(@click="isFriendsGroupMe = !isFriendsGroupMe; saveFriendsGroupStates()" style="padding:0px 0px 5px")
i.el-icon-arrow-right(:class="{ rotate: isFriendsGroupMe }")
span(style="margin-left:5px") {{ $t('side_panel.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)")
span(style='color: #909399; font-size: 12px; margin-left: 10px') ({{ onlineFriendCount }}/{{ friends.size }})
.x-friend-list(style='padding: 10px 5px')
.x-friend-group.x-link(
@click='isFriendsGroupMe = !isFriendsGroupMe; saveFriendsGroupStates()'
style='padding: 0px 0px 5px')
i.el-icon-arrow-right(:class='{ rotate: isFriendsGroupMe }')
span(style='margin-left: 5px') {{ $t('side_panel.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 && !gameLogDisabled" :location="lastLocation.location" :traveling="lastLocationDestination" :link="false")
location.extra(v-else-if="isRealInstance(API.currentUser.$locationTag) || isRealInstance(API.currentUser.$travelingToLocation)" :location="API.currentUser.$locationTag" :traveling="API.currentUser.$travelingToLocation" :link="false")
span.extra(v-else v-text="API.currentUser.statusDescription")
.x-friend-group.x-link(@click="isVIPFriends = !isVIPFriends; saveFriendsGroupStates()" v-show="vipFriends.length")
i.el-icon-arrow-right(:class="{ rotate: isVIPFriends }")
span(style="margin-left:5px") {{ $t('side_panel.favorite') }} ― {{ vipFriends.length }}
div(v-show="isVIPFriends")
span.name(
v-text='API.currentUser.displayName'
:style='{ color: API.currentUser.$userColour }')
location.extra(
v-if='isGameRunning && !gameLogDisabled'
:location='lastLocation.location'
:traveling='lastLocationDestination'
:link='false')
location.extra(
v-else-if='isRealInstance(API.currentUser.$locationTag) || isRealInstance(API.currentUser.$travelingToLocation)'
:location='API.currentUser.$locationTag'
:traveling='API.currentUser.$travelingToLocation'
:link='false')
span.extra(v-else v-text='API.currentUser.statusDescription')
.x-friend-group.x-link(
@click='isVIPFriends = !isVIPFriends; saveFriendsGroupStates()'
v-show='vipFriends.length')
i.el-icon-arrow-right(:class='{ rotate: isVIPFriends }')
span(style='margin-left: 5px') {{ $t('side_panel.favorite') }} ― {{ vipFriends.length }}
div(v-show='isVIPFriends')
template(v-if='isSidebarGroupByInstance')
div(v-for="(friendArr, idx) in vipFriendsInSameInstance" :key="friendArr[0].ref?.location.tag")
div(style="margin-bottom: 3px")
location.extra(:location="friendArr[0].ref?.location" style="color:#c7c7c7")
span(style="margin-left: 5px") {{ `(${friendArr.length})` }}
div(style="margin-bottom: 10px")
div.x-friend-item(v-if="friendArr && friendArr.length" v-for="friend in friendArr" :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)")
div(
v-for='(friendArr, idx) in vipFriendsInSameInstance'
:key='friendArr[0].ref?.location.tag')
div(style='margin-bottom: 3px')
location.extra(:location='friendArr[0].ref?.location' style='color: #c7c7c7')
span(style='margin-left: 5px') {{ `(${friendArr.length})` }}
div(style='margin-bottom: 10px')
.x-friend-item(
v-if='friendArr && friendArr.length'
v-for='friend in friendArr'
: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="!hideNicknames && 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] {{ $t('side_panel.pending_offline') }}
span.name(
v-if='!hideNicknames && 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] {{ $t('side_panel.pending_offline') }}
template(v-else)
i(v-if="friend.ref.travelingToLocation" class="el-icon el-icon-loading" style="display:inline-block;margin-right:5px")
timer(:epoch="friend.ref?.$location_at" style="color:#c7c7c7")
i.el-icon.el-icon-loading(
v-if='friend.ref.travelingToLocation'
style='display: inline-block; margin-right: 5px')
timer(:epoch='friend.ref?.$location_at' style='color: #c7c7c7')
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")
div(v-if="idx === vipFriendsInSameInstance.length - 1" style="color:#c7c7c7") {{ "Others" }}
.x-friend-item(v-for="friend in vipFriendsNotInSameInstance" :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)")
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')
div(v-if='idx === vipFriendsInSameInstance.length - 1' style='color: #c7c7c7') {{ 'Others' }}
.x-friend-item(
v-for='friend in vipFriendsNotInSameInstance'
: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="!hideNicknames && 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] {{ $t('side_panel.pending_offline') }}
location.extra(v-else :location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false")
span.name(
v-if='!hideNicknames && 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] {{ $t('side_panel.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")
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')
template(v-else)
.x-friend-item(v-for="friend in vipFriends" :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)")
.x-friend-item(
v-for='friend in vipFriends'
: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="!hideNicknames && 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] {{ $t('side_panel.pending_offline') }}
location.extra(v-else :location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false")
span.name(
v-if='!hideNicknames && 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] {{ $t('side_panel.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.x-link(@click="isOnlineFriends = !isOnlineFriends; saveFriendsGroupStates()" v-show="onlineFriends.length")
i.el-icon-arrow-right(:class="{ rotate: isOnlineFriends }")
span(style="margin-left:5px") {{ $t('side_panel.online') }} ― {{ onlineFriends.length }}
div(v-show="isOnlineFriends")
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.x-link(
@click='isOnlineFriends = !isOnlineFriends; saveFriendsGroupStates()'
v-show='onlineFriends.length')
i.el-icon-arrow-right(:class='{ rotate: isOnlineFriends }')
span(style='margin-left: 5px') {{ $t('side_panel.online') }} ― {{ onlineFriends.length }}
div(v-show='isOnlineFriends')
template(v-if='isSidebarGroupByInstance')
div(v-for="(friendArr, idx) in onlineFriendsInSameInstance" :key="friendArr[0].ref?.location.tag")
div(style="margin-bottom: 3px")
location.extra(:location="friendArr[0].ref?.location" style="color:#c7c7c7")
span(style="margin-left: 5px") {{ `(${friendArr.length})` }}
div(style="margin-bottom: 10px")
div.x-friend-item(v-if="friendArr && friendArr.length" v-for="friend in friendArr" :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)")
div(
v-for='(friendArr, idx) in onlineFriendsInSameInstance'
:key='friendArr[0].ref?.location.tag')
div(style='margin-bottom: 3px')
location.extra(:location='friendArr[0].ref?.location' style='color: #c7c7c7')
span(style='margin-left: 5px') {{ `(${friendArr.length})` }}
div(style='margin-bottom: 10px')
.x-friend-item(
v-if='friendArr && friendArr.length'
v-for='friend in friendArr'
: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="!hideNicknames && 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] {{ $t('side_panel.pending_offline') }}
span.name(
v-if='!hideNicknames && 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] {{ $t('side_panel.pending_offline') }}
template(v-else)
i(v-if="friend.ref.travelingToLocation" class="el-icon el-icon-loading" style="display:inline-block;margin-right:5px")
timer(:epoch="friend.ref?.$location_at" style="color:#c7c7c7")
i.el-icon.el-icon-loading(
v-if='friend.ref.travelingToLocation'
style='display: inline-block; margin-right: 5px')
timer(:epoch='friend.ref?.$location_at' style='color: #c7c7c7')
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")
div(v-if="idx === onlineFriendsInSameInstance.length - 1" style="color:#c7c7c7") {{ "Others" }}
.x-friend-item(v-for="friend in onlineFriendsNotInSameInstance" :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)")
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')
div(v-if='idx === onlineFriendsInSameInstance.length - 1' style='color: #c7c7c7') {{ 'Others' }}
.x-friend-item(
v-for='friend in onlineFriendsNotInSameInstance'
: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="!hideNicknames && 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] {{ $t('side_panel.pending_offline') }}
location.extra(v-else :location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false")
span.name(
v-if='!hideNicknames && 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] {{ $t('side_panel.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")
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')
template(v-else)
.x-friend-item(v-for="friend in onlineFriends" :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)")
.x-friend-item(
v-for='friend in onlineFriends'
: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="!hideNicknames && 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] {{ $t('side_panel.pending_offline') }}
location.extra(v-else :location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false")
span.name(
v-if='!hideNicknames && 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] {{ $t('side_panel.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.x-link(@click="isActiveFriends = !isActiveFriends; saveFriendsGroupStates()" v-show="activeFriends.length")
i.el-icon-arrow-right(:class="{ rotate: isActiveFriends }")
span(style="margin-left:5px") {{ $t('side_panel.active') }} ― {{ activeFriends.length }}
div(v-show="isActiveFriends")
.x-friend-item(v-for="friend in activeFriends" :key="friend.id" @click="showUserDialog(friend.id)")
template(v-if="friend.ref")
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.x-link(
@click='isActiveFriends = !isActiveFriends; saveFriendsGroupStates()'
v-show='activeFriends.length')
i.el-icon-arrow-right(:class='{ rotate: isActiveFriends }')
span(style='margin-left: 5px') {{ $t('side_panel.active') }} ― {{ activeFriends.length }}
div(v-show='isActiveFriends')
.x-friend-item(
v-for='friend in activeFriends'
:key='friend.id'
@click='showUserDialog(friend.id)')
template(v-if='friend.ref')
.avatar
img(v-lazy="userImage(friend.ref)")
img(v-lazy='userImage(friend.ref)')
.detail
span.name(v-if="!hideNicknames && 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")
span.name(
v-if='!hideNicknames && 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.x-link(@click="isOfflineFriends = !isOfflineFriends; saveFriendsGroupStates()" v-show="offlineFriends.length")
i.el-icon-arrow-right(:class="{ rotate: isOfflineFriends }")
span(style="margin-left:5px") {{ $t('side_panel.offline') }} ― {{ offlineFriends.length }}
div(v-show="isOfflineFriends")
.x-friend-item(v-for="friend in offlineFriends" :key="friend.id" @click="showUserDialog(friend.id)")
template(v-if="friend.ref")
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.x-link(
@click='isOfflineFriends = !isOfflineFriends; saveFriendsGroupStates()'
v-show='offlineFriends.length')
i.el-icon-arrow-right(:class='{ rotate: isOfflineFriends }')
span(style='margin-left: 5px') {{ $t('side_panel.offline') }} ― {{ offlineFriends.length }}
div(v-show='isOfflineFriends')
.x-friend-item(
v-for='friend in offlineFriends'
:key='friend.id'
@click='showUserDialog(friend.id)')
template(v-if='friend.ref')
.avatar
img(v-lazy="userImage(friend.ref)")
img(v-lazy='userImage(friend.ref)')
.detail
span.name(v-if="!hideNicknames && 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")
span.name(
v-if='!hideNicknames && 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")
el-tab-pane
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')
el-tab-pane(lazy)
template(#label)
span {{ $t('side_panel.groups') }}
span(style="color:#909399;font-size:12px;margin-left:10px") ({{ groupInstances.length }})
.x-friend-list(style="padding:10px 5px")
.x-friend-item(v-for="ref in groupInstances" :key="ref.instance.id" @click="showGroupDialog(ref.instance.ownerId)")
.avatar
img(v-lazy="ref.group.iconUrl")
.detail
span.name
span(v-text="ref.group.name")
span(style="font-weight:normal;margin-left:5px") ({{ ref.instance.userCount }}/{{ ref.instance.capacity }})
location.extra(:location="ref.instance.location" :link="false")
span(style='color: #909399; font-size: 12px; margin-left: 10px') ({{ groupInstances.length }})
groups-sidebar(:group-instances='groupInstances' @show-group-dialog='showGroupDialog')