fchat-rising/chat/UserList.vue

210 lines
6.4 KiB
Vue
Raw Normal View History

2017-09-02 01:50:31 +00:00
<template>
2018-01-06 16:14:21 +00:00
<sidebar id="user-list" :label="l('users.title')" icon="fa-users" :right="true" :open="expanded">
<tabs style="flex-shrink:0" :tabs="channel ? [l('users.friends'), l('users.members')] : [l('users.friends')]" v-model="tab"></tabs>
2019-01-03 17:38:17 +00:00
<div class="users" style="padding-left:10px" v-show="tab === '0'">
2018-01-06 16:14:21 +00:00
<h4>{{l('users.friends')}}</h4>
<div v-for="character in friends" :key="character.name">
2018-04-11 19:17:58 +00:00
<user :character="character" :showStatus="true" :bookmark="false"></user>
2017-09-02 01:50:31 +00:00
</div>
2018-01-06 16:14:21 +00:00
<h4>{{l('users.bookmarks')}}</h4>
<div v-for="character in bookmarks" :key="character.name">
2018-04-11 19:17:58 +00:00
<user :character="character" :showStatus="true" :bookmark="false"></user>
2017-09-02 01:50:31 +00:00
</div>
</div>
2019-01-03 17:38:17 +00:00
<div v-if="channel" style="padding-left:5px;flex:1;display:flex;flex-direction:column" v-show="tab === '1'">
<div class="users" style="flex:1;padding-left:5px">
2022-08-09 04:13:18 +00:00
<h4>{{l('users.memberCount', channel.sortedMembers.length)}} <a class="btn sort" @click="switchSort"><i class="fa fa-sort"></i></a></h4>
<div v-for="member in filteredMembers" :key="member.character.name">
<user :character="member.character" :channel="channel" :showStatus="true"></user>
</div>
</div>
<div class="input-group" style="margin-top:5px;flex-shrink:0">
<div class="input-group-prepend">
<div class="input-group-text"><span class="fas fa-search"></span></div>
</div>
<input class="form-control" v-model="filter" :placeholder="l('filter')" type="text"/>
2018-01-06 16:14:21 +00:00
</div>
</div>
</sidebar>
2017-09-02 01:50:31 +00:00
</template>
<script lang="ts">
2019-01-03 17:38:17 +00:00
import {Component} from '@f-list/vue-ts';
2017-09-02 01:50:31 +00:00
import Vue from 'vue';
import Tabs from '../components/tabs';
2017-09-02 01:50:31 +00:00
import core from './core';
2022-08-09 04:13:18 +00:00
import { Channel, Character, Conversation } from './interfaces';
2017-09-02 01:50:31 +00:00
import l from './localize';
2018-01-06 16:14:21 +00:00
import Sidebar from './Sidebar.vue';
2019-07-15 16:59:16 +00:00
import UserView from './UserView.vue';
2022-08-09 04:13:18 +00:00
import _ from 'lodash';
type StatusSort = {
[key in Character.Status]: number;
};
type GenderSort = {
[key in Character.Gender]: number;
};
const statusSort: StatusSort = {
'crown': 0,
'looking': 1,
'online': 2,
'idle': 3,
'away': 4,
'busy': 5,
'dnd': 6,
'offline': 7
};
const genderSort: GenderSort = {
'Female': 0,
'Male': 1,
'Herm': 2,
'Shemale': 3,
'Cunt-boy': 4,
'Transgender': 5,
'Male-Herm': 6,
'None': 7
};
const availableSorts = ['normal', 'status', 'gender'] as const;
2017-09-02 01:50:31 +00:00
@Component({
components: {user: UserView, sidebar: Sidebar, tabs: Tabs}
2017-09-02 01:50:31 +00:00
})
export default class UserList extends Vue {
tab = '0';
expanded = window.innerWidth >= 992;
filter = '';
2017-09-02 01:50:31 +00:00
l = l;
sorter = (x: Character, y: Character) => (x.name < y.name ? -1 : (x.name > y.name ? 1 : 0));
2022-08-09 04:13:18 +00:00
sortType: typeof availableSorts[number] = 'normal';
2017-09-02 01:50:31 +00:00
get friends(): Character[] {
return core.characters.friends.slice().sort(this.sorter);
}
get bookmarks(): Character[] {
return core.characters.bookmarks.slice().filter((x) => core.characters.friends.indexOf(x) === -1).sort(this.sorter);
}
get channel(): Channel {
return (<Conversation.ChannelConversation>core.conversations.selectedConversation).channel;
}
get filteredMembers(): ReadonlyArray<Channel.Member> {
2022-08-09 04:13:18 +00:00
const members = this.getFilteredMembers();
if (this.sortType === 'normal') {
return members;
}
const sorted = [...members];
switch (this.sortType) {
case 'status':
sorted.sort((a, b) => {
const aVal = statusSort[a.character.status];
const bVal = statusSort[b.character.status];
if (aVal - bVal === 0) {
return a.character.name.localeCompare(b.character.name);
}
return aVal - bVal;
});
break;
case 'gender':
sorted.sort((a, b) => {
const aVal = genderSort[(a.character.gender || 'None')];
const bVal = genderSort[(b.character.gender || 'None')];
if (aVal - bVal === 0) {
return a.character.name.localeCompare(b.character.name);
}
return aVal - bVal;
});
break;
}
return sorted;
}
getFilteredMembers() {
2022-01-01 00:06:08 +00:00
const members = this.prefilterMembers();
if (!core.state.settings.risingFilter.hideChannelMembers) {
return members;
}
return members.filter((m) => {
const p = core.cache.profileCache.getSync(m.character.name);
return !p || !p.match.isFiltered;
});
}
prefilterMembers(): ReadonlyArray<Channel.Member> {
2022-08-09 04:13:18 +00:00
const sorted = this.channel.sortedMembers;
2022-01-01 00:06:08 +00:00
if(this.filter.length === 0)
2022-08-09 04:13:18 +00:00
return sorted;
2022-01-01 00:06:08 +00:00
const filter = new RegExp(this.filter.replace(/[^\w]/gi, '\\$&'), 'i');
2022-08-09 04:13:18 +00:00
return sorted.filter((member) => filter.test(member.character.name));
}
switchSort() {
const nextSortIndex = _.indexOf(availableSorts, this.sortType) + 1;
this.sortType = availableSorts[nextSortIndex % availableSorts.length];
}
2017-09-02 01:50:31 +00:00
}
</script>
<style lang="scss">
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins/breakpoints";
2017-09-02 01:50:31 +00:00
#user-list {
flex-direction: column;
h4 {
margin: 5px 0 0 -5px;
font-size: 17px;
}
.users {
overflow: auto;
}
.nav li:first-child a {
border-left: 0;
border-top-left-radius: 0;
}
@media (min-width: breakpoint-min(md)) {
2018-01-06 16:14:21 +00:00
.sidebar {
position: static;
margin: 0;
padding: 0;
height: 100%;
}
.modal-backdrop {
display: none;
}
}
&.open .body {
display: flex;
2017-09-02 01:50:31 +00:00
}
}
2022-01-01 00:06:08 +00:00
</style>