Species search
This commit is contained in:
parent
73528dd51d
commit
326e1b9445
|
@ -11,6 +11,11 @@
|
|||
v-model="data[item]" :placeholder="l('filter')" :title="l('characterSearch.' + item)" :options="options[item]" :key="item">
|
||||
</filterable-select>
|
||||
|
||||
<filterable-select v-model="data.species" :multiple="true" :placeholder="l('filter')"
|
||||
:title="l('characterSearch.species')" :options="options.species">
|
||||
<template slot-scope="s">{{s.option.name}}</template>
|
||||
</filterable-select>
|
||||
|
||||
<div v-if="searchString" class="search-string">
|
||||
Searching for <span>{{searchString}}</span>
|
||||
</div>
|
||||
|
@ -49,12 +54,13 @@
|
|||
import Modal from '../components/Modal.vue';
|
||||
import {characterImage} from './common';
|
||||
import core from './core';
|
||||
import { Character, Connection, SearchData, SearchKink } from './interfaces';
|
||||
import { Character, Connection, ExtendedSearchData, SearchData, SearchKink, SearchSpecies } from './interfaces';
|
||||
import l from './localize';
|
||||
import UserView from './UserView.vue';
|
||||
import * as _ from 'lodash';
|
||||
import {EventBus} from './preview/event-bus';
|
||||
import CharacterSearchHistory from './CharacterSearchHistory.vue';
|
||||
import { Matcher, Species, speciesNames } from '../learn/matcher';
|
||||
|
||||
type Options = {
|
||||
kinks: SearchKink[],
|
||||
|
@ -102,9 +108,9 @@
|
|||
results: Character[] | undefined;
|
||||
resultsComplete = false;
|
||||
characterImage = characterImage;
|
||||
options!: SearchData;
|
||||
data: SearchData = {kinks: [], genders: [], orientations: [], languages: [], furryprefs: [], roles: [], positions: []};
|
||||
listItems: ReadonlyArray<keyof SearchData> = ['genders', 'orientations', 'languages', 'furryprefs', 'roles', 'positions'];
|
||||
options!: ExtendedSearchData;
|
||||
data: ExtendedSearchData = {kinks: [], genders: [], orientations: [], languages: [], furryprefs: [], roles: [], positions: [], species: []};
|
||||
listItems: ReadonlyArray<keyof SearchData> = ['genders', 'orientations', 'languages', 'furryprefs', 'roles', 'positions']; // SearchData is correct
|
||||
|
||||
searchString = '';
|
||||
|
||||
|
@ -124,7 +130,8 @@
|
|||
languages: options.listitems.filter((x) => x.name === 'languagepreference').map((x) => x.value),
|
||||
furryprefs: options.listitems.filter((x) => x.name === 'furrypref').map((x) => x.value),
|
||||
roles: options.listitems.filter((x) => x.name === 'subdom').map((x) => x.value),
|
||||
positions: options.listitems.filter((x) => x.name === 'position').map((x) => x.value)
|
||||
positions: options.listitems.filter((x) => x.name === 'position').map((x) => x.value),
|
||||
species: this.getSpeciesOptions()
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -144,7 +151,9 @@
|
|||
});
|
||||
core.connection.onMessage('FKS', (data) => {
|
||||
this.results = data.characters.map((x) => core.characters.get(x))
|
||||
.filter((x) => core.state.hiddenUsers.indexOf(x.name) === -1 && !x.isIgnored).sort(sort);
|
||||
.filter((x) => core.state.hiddenUsers.indexOf(x.name) === -1 && !x.isIgnored)
|
||||
.filter((x) => this.isSpeciesMatch(x))
|
||||
.sort(sort);
|
||||
|
||||
this.resultsComplete = this.checkResultCompletion();
|
||||
});
|
||||
|
@ -164,7 +173,11 @@
|
|||
// tslint:disable-next-line no-unsafe-any no-any
|
||||
&& (_.find(this.results, (c: Character) => c.name === event.character.character.name))
|
||||
) {
|
||||
this.results = this.results.sort(sort);
|
||||
this.results = (_.filter(
|
||||
this.results,
|
||||
(x) => this.isSpeciesMatch(x)
|
||||
) as Character[]).sort(sort);
|
||||
|
||||
this.resultsComplete = this.checkResultCompletion();
|
||||
}
|
||||
};
|
||||
|
@ -203,6 +216,51 @@
|
|||
}
|
||||
|
||||
|
||||
isSpeciesMatch(c: Character): boolean {
|
||||
if (this.data.species.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const knownCharacter = core.cache.profileCache.getSync(c.name);
|
||||
|
||||
if (!knownCharacter) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const species = Matcher.species(knownCharacter.character.character);
|
||||
|
||||
if (!species) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!_.find(this.data.species, (s) => (s.id === species));
|
||||
}
|
||||
|
||||
|
||||
getSpeciesOptions(): SearchSpecies[] {
|
||||
const species = _.map(
|
||||
_.filter(Species, (s) => (_.isString(s))) as unknown[] as string[],
|
||||
(speciesName: string) => {
|
||||
const speciesId = (Species as any)[speciesName];
|
||||
|
||||
if (speciesId in speciesNames) {
|
||||
return {
|
||||
name: `${speciesNames[speciesId].substr(0, 1).toUpperCase()}${speciesNames[speciesId].substr(1)} (species)`,
|
||||
id: speciesId
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: `${speciesName}s (species)`,
|
||||
id: speciesId
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
return _.sortBy(species, 'name');
|
||||
}
|
||||
|
||||
|
||||
checkResultCompletion(): boolean {
|
||||
return _.every(
|
||||
this.results,
|
||||
|
@ -223,11 +281,11 @@
|
|||
|
||||
|
||||
reset(): void {
|
||||
this.data = {kinks: [], genders: [], orientations: [], languages: [], furryprefs: [], roles: [], positions: []};
|
||||
this.data = {kinks: [], genders: [], orientations: [], languages: [], furryprefs: [], roles: [], positions: [], species: []};
|
||||
}
|
||||
|
||||
|
||||
updateSearch(data?: SearchData): void {
|
||||
updateSearch(data?: ExtendedSearchData): void {
|
||||
if (data) {
|
||||
// this.data = {kinks: [], genders: [], orientations: [], languages: [], furryprefs: [], roles: [], positions: []};
|
||||
// this.data = data;
|
||||
|
@ -245,7 +303,7 @@
|
|||
}
|
||||
)
|
||||
)
|
||||
) as SearchData;
|
||||
) as ExtendedSearchData;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,7 +316,7 @@
|
|||
this.error = '';
|
||||
const data: Connection.ClientCommands['FKS'] & {[key: string]: (string | number)[]} = {kinks: []};
|
||||
for(const key in this.data) {
|
||||
const item = this.data[<keyof SearchData>key];
|
||||
const item = this.data[<keyof SearchData>key]; // SearchData is correct
|
||||
if(item.length > 0)
|
||||
data[key] = key === 'kinks' ? (<SearchKink[]>item).map((x) => x.id) : (<string[]>item);
|
||||
}
|
||||
|
@ -274,11 +332,16 @@
|
|||
}
|
||||
|
||||
|
||||
async updateSearchHistory(data: SearchData): Promise<void> {
|
||||
async updateSearchHistory(data: ExtendedSearchData): Promise<void> {
|
||||
const history = (await core.settingsStore.get('searchHistory')) || [];
|
||||
const dataStr = JSON.stringify(data, null, 0);
|
||||
const filteredHistory = _.reject(history, (h: SearchData) => (JSON.stringify(h, null, 0) === dataStr));
|
||||
const newHistory: SearchData[] = _.take(_.concat([data], filteredHistory), 15);
|
||||
|
||||
const filteredHistory = _.map(
|
||||
_.reject(history, (h: SearchData) => (JSON.stringify(h, null, 0) === dataStr)),
|
||||
(h) => _.merge({ species: [] }, h)
|
||||
) as ExtendedSearchData[];
|
||||
|
||||
const newHistory: ExtendedSearchData[] = _.take(_.concat([data], filteredHistory), 15);
|
||||
|
||||
await core.settingsStore.set('searchHistory', newHistory);
|
||||
}
|
||||
|
|
|
@ -26,19 +26,19 @@
|
|||
import core from './core';
|
||||
import { BBCodeView } from '../bbcode/view';
|
||||
import * as _ from 'lodash';
|
||||
import { SearchData } from './interfaces';
|
||||
import { ExtendedSearchData, SearchData } from './interfaces';
|
||||
|
||||
@Component({
|
||||
components: {modal: Modal, dropdown: Dropdown, bbcode: BBCodeView(core.bbCodeParser)}
|
||||
})
|
||||
export default class CharacterSearchHistory extends CustomDialog {
|
||||
@Prop({required: true})
|
||||
readonly callback!: (searchData: SearchData) => void;
|
||||
readonly callback!: (searchData: ExtendedSearchData) => void;
|
||||
|
||||
@Prop({required: true})
|
||||
readonly curSearch!: SearchData | undefined;
|
||||
readonly curSearch!: ExtendedSearchData | undefined;
|
||||
|
||||
history: SearchData[] = [];
|
||||
history: (ExtendedSearchData|SearchData)[] = [];
|
||||
|
||||
selectedSearch: number | null = null;
|
||||
|
||||
|
@ -64,7 +64,7 @@
|
|||
|
||||
selectStatus(): void {
|
||||
if (this.selectedSearch !== null) {
|
||||
this.callback(this.history[this.selectedSearch]);
|
||||
this.callback(_.merge({species: []}, this.history[this.selectedSearch]) as ExtendedSearchData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@
|
|||
}
|
||||
|
||||
|
||||
describeSearch(searchData: SearchData): string {
|
||||
describeSearch(searchData: SearchData | ExtendedSearchData): string {
|
||||
return _.join(
|
||||
_.map(
|
||||
// tslint:disable-next-line no-unsafe-any no-any
|
||||
|
|
|
@ -144,6 +144,7 @@ export interface Logs {
|
|||
}
|
||||
|
||||
export type SearchKink = {id: number, name: string, description: string};
|
||||
export type SearchSpecies = {id: number, name: string};
|
||||
|
||||
export interface SearchData {
|
||||
kinks: SearchKink[]
|
||||
|
@ -155,6 +156,9 @@ export interface SearchData {
|
|||
positions: string[]
|
||||
}
|
||||
|
||||
export interface ExtendedSearchData extends SearchData {
|
||||
species: SearchSpecies[];
|
||||
}
|
||||
|
||||
export namespace Settings {
|
||||
export type Keys = {
|
||||
|
@ -166,7 +170,7 @@ export namespace Settings {
|
|||
recentChannels: Conversation.RecentChannelConversation[]
|
||||
hiddenUsers: string[]
|
||||
statusHistory: string[]
|
||||
searchHistory: SearchData[]
|
||||
searchHistory: (ExtendedSearchData | SearchData)[]
|
||||
};
|
||||
|
||||
export interface Store {
|
||||
|
|
|
@ -229,6 +229,7 @@ Once this process has started, do not interrupt it or your logs will get corrupt
|
|||
'characterSearch.furryprefs': 'Furry preferences',
|
||||
'characterSearch.roles': 'Dom/sub roles',
|
||||
'characterSearch.positions': 'Positions',
|
||||
'characterSearch.species': 'Species (beta)',
|
||||
'characterSearch.error.noResults': 'There were no search results.',
|
||||
'characterSearch.error.throttle': 'You must wait five seconds between searches.',
|
||||
'characterSearch.error.tooManyResults': 'There are too many search results, please narrow your search.',
|
||||
|
|
|
@ -180,7 +180,7 @@ interface SpeciesStrMap {
|
|||
[key: number]: string;
|
||||
}
|
||||
|
||||
const speciesNames: SpeciesStrMap = {
|
||||
export const speciesNames: SpeciesStrMap = {
|
||||
[Species.MarineMammal]: 'marine mammals',
|
||||
[Species.Elf]: 'elves',
|
||||
[Species.Fish]: 'fishes',
|
||||
|
@ -195,7 +195,7 @@ const speciesMapping: SpeciesMap = {
|
|||
'appaloosa', 'friesian', 'draft', 'draught', 'alicorn', 'amazon', 'amazonian', 'horsie', 'hoss', 'pegasus', 'colt', 'filly'],
|
||||
[Species.Feline]: ['cat', 'kitten', 'catgirl', 'neko', 'tiger', 'puma', 'lion', 'lioness',
|
||||
'tigress', 'feline', 'jaguar', 'cheetah', 'lynx', 'leopard', 'cougar', 'kitty', 'migote', 'miqo\'te', 'miqote', 'ocelot',
|
||||
'sabertooth', 'saber tooth', 'tabby'],
|
||||
'sabertooth', 'saber tooth', 'tabby', 'liger'],
|
||||
[Species.Canine]: ['dog', 'wolf', 'dingo', 'coyote', 'jackal', 'canine', 'doberman', 'husky', 'hound', 'akita', 'pitbull', 'pit bull', 'terrier',
|
||||
'bull terrier', 'australian shepherd', 'australian shepard', 'german shepherd', 'german shepard', 'malinois', 'woof', 'labrador', 'collie',
|
||||
'canis', 'canid', 'chihuahua', 'poodle', 'chinchilla', 'chowchow', 'corgi', 'anubis', 'anubian', 'dalmatian', 'inumimi', 'lupine', 'malamute', 'mastiff',
|
||||
|
|
|
@ -44,6 +44,7 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
|
|||
* Display match score in search results
|
||||
* Current search filters are listed in the search dialog
|
||||
* Search filters can be reset
|
||||
* Search results can be filtered by species
|
||||
* Last 15 searches are stored and can be accessed from the 'Search' dialog
|
||||
* Character status
|
||||
* Last 10 status messages are stored and can be accessed from the 'Set status' dialog
|
||||
|
|
Loading…
Reference in New Issue