mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
[feat-216] refactored sorting services to classes and const
This commit is contained in:
@@ -6,7 +6,7 @@ import { FilterPanel } from "./maps/filter-panel.component";
|
||||
import { MapFilter, MapSort } from "shared/models/maps/beat-saver.model";
|
||||
import { MapsManagerService } from "renderer/services/maps-manager.service";
|
||||
import { MapsDownloaderService } from "renderer/services/maps-downloader.service";
|
||||
import { useTranslation } from "renderer/hooks/use-translation.hook";
|
||||
import { useTranslationV2 } from "renderer/hooks/use-translation.hook";
|
||||
import { FolderLinkState } from "renderer/services/version-folder-linker.service";
|
||||
import { useService } from "renderer/hooks/use-service.hook";
|
||||
import { BsContentTabPanel } from "../shared/bs-content-tab-panel/bs-content-tab-panel.component";
|
||||
@@ -25,9 +25,9 @@ import { noop } from "shared/helpers/function.helpers";
|
||||
import { Dropzone } from "../shared/dropzone.component";
|
||||
import { logRenderError } from "renderer";
|
||||
import { BsmSelect, BsmSelectOption } from "../shared/bsm-select.component";
|
||||
import { MapsSorterService } from "renderer/services/maps/sorter.service";
|
||||
import { BsmButton } from "../shared/bsm-button.component";
|
||||
import { PlaylistsSorterService } from "renderer/services/playlists/sorter.service";
|
||||
import { mapSorter } from "shared/models/maps/sorter";
|
||||
import { playlistSorter } from "shared/models/playlists/sorter";
|
||||
|
||||
type Props = {
|
||||
readonly version?: BSVersion;
|
||||
@@ -48,12 +48,10 @@ export function MapsPlaylistsPanel({ version, isActive }: Props) {
|
||||
|
||||
const mapsManager = useService(MapsManagerService);
|
||||
const mapsDownloader = useService(MapsDownloaderService);
|
||||
const mapsSorter = useService(MapsSorterService);
|
||||
const playlistsManager = useService(PlaylistsManagerService);
|
||||
const playlistsDownloader = useService(PlaylistDownloaderService);
|
||||
const playlistsSorter = useService(PlaylistsSorterService);
|
||||
|
||||
const t = useTranslation();
|
||||
const { text: t } = useTranslationV2();
|
||||
const [tabIndex, setTabIndex] = useState(0);
|
||||
|
||||
const [mapsDropZoneOpen, setMapsDropZoneOpen] = useState(false);
|
||||
@@ -74,18 +72,18 @@ export function MapsPlaylistsPanel({ version, isActive }: Props) {
|
||||
|
||||
const [mapFilter, setMapFilter] = useState<MapFilter>({});
|
||||
const [mapSort, setMapSort] = useState<MapSort>({
|
||||
compare: mapsSorter.getDefaultComparator(),
|
||||
compare: mapSorter.getDefaultComparator(),
|
||||
ascending: true,
|
||||
});
|
||||
const [playlistFilter, setPlaylistFilter] = useState<LocalPlaylistFilter>({});
|
||||
const [playlistSort, setPlaylistSort] = useState<LocalPlaylistSort>({
|
||||
compare: playlistsSorter.getDefaultComparator(),
|
||||
compare: playlistSorter.getDefaultComparator(),
|
||||
ascending: true,
|
||||
});
|
||||
const [selectedSort, setSelectedSort] = useState<string>("name");
|
||||
|
||||
const [sortOptions, setSortOptions] = useState<BsmSelectOption<string>[]>(
|
||||
() => mapsSorter.getComparatorKeys().map(key => ({
|
||||
() => mapSorter.getComparatorKeys().map(key => ({
|
||||
text: `pages.version-viewer.maps.tabs.maps.sort.${key}`,
|
||||
value: key,
|
||||
}))
|
||||
@@ -126,29 +124,32 @@ export function MapsPlaylistsPanel({ version, isActive }: Props) {
|
||||
};
|
||||
|
||||
const handleTabChange = (index: number) => {
|
||||
if (tabIndex === index) {
|
||||
return;
|
||||
}
|
||||
setTabIndex(index);
|
||||
|
||||
switch (index) {
|
||||
case MAP_TAB:
|
||||
setSortOptions(() => mapsSorter.getComparatorKeys().map(key => ({
|
||||
setSortOptions(() => mapSorter.getComparatorKeys().map(key => ({
|
||||
text: `pages.version-viewer.maps.tabs.maps.sort.${key}`,
|
||||
value: key,
|
||||
})));
|
||||
setSelectedSort(mapsSorter.getDefaultComparatorKey());
|
||||
setSelectedSort(mapSorter.defaultKey);
|
||||
setMapSort({
|
||||
compare: mapsSorter.getDefaultComparator(),
|
||||
compare: mapSorter.getDefaultComparator(),
|
||||
ascending: playlistSort.ascending,
|
||||
});
|
||||
break;
|
||||
|
||||
case PLAYLIST_TAB:
|
||||
setSortOptions(() => playlistsSorter.getComparatorKeys().map(key => ({
|
||||
setSortOptions(() => playlistSorter.getComparatorKeys().map(key => ({
|
||||
text: `pages.version-viewer.maps.tabs.playlists.sort.${key}`,
|
||||
value: key,
|
||||
})));
|
||||
setSelectedSort(playlistsSorter.getDefaultComparatorKey());
|
||||
setSelectedSort(playlistSorter.defaultKey);
|
||||
setPlaylistSort({
|
||||
compare: playlistsSorter.getDefaultComparator(),
|
||||
compare: playlistSorter.getDefaultComparator(),
|
||||
ascending: mapSort.ascending,
|
||||
});
|
||||
break;
|
||||
@@ -197,14 +198,14 @@ export function MapsPlaylistsPanel({ version, isActive }: Props) {
|
||||
switch (tabIndex) {
|
||||
case MAP_TAB:
|
||||
setMapSort({
|
||||
compare: mapsSorter.getComparator(key),
|
||||
compare: mapSorter.getComparator(key),
|
||||
ascending: mapSort.ascending,
|
||||
});
|
||||
break;
|
||||
|
||||
case PLAYLIST_TAB:
|
||||
setPlaylistSort({
|
||||
compare: playlistsSorter.getComparator(key),
|
||||
compare: playlistSorter.getComparator(key),
|
||||
ascending: playlistSort.ascending,
|
||||
});
|
||||
break;
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import { Comparator, Comparison } from "shared/models/comparator.type";
|
||||
import { LocalBPListsDetails } from "shared/models/playlists/local-playlist.models";
|
||||
|
||||
export class PlaylistsSorterService {
|
||||
private static instance: PlaylistsSorterService;
|
||||
|
||||
public static getInstance() {
|
||||
if (!PlaylistsSorterService.instance) {
|
||||
PlaylistsSorterService.instance = new PlaylistsSorterService();
|
||||
}
|
||||
return PlaylistsSorterService.instance;
|
||||
}
|
||||
|
||||
private readonly comparators: {
|
||||
[key: string]: Comparator<LocalBPListsDetails>;
|
||||
} = {
|
||||
title: (playlist1, playlist2) => playlist1.playlistTitle.localeCompare(playlist2.playlistTitle),
|
||||
author: (playlist1, playlist2) => playlist1.playlistAuthor.localeCompare(playlist2.playlistAuthor),
|
||||
"number-of-maps": (playlist1, playlist2) => playlist1.nbMaps - playlist2.nbMaps,
|
||||
duration: (playlist1, playlist2) => {
|
||||
if (!playlist1.duration) {
|
||||
return playlist2.duration ? Comparison.LESSER : Comparison.EQUAL;
|
||||
}
|
||||
|
||||
return !playlist2.duration ? Comparison.GREATER : playlist1.duration - playlist2.duration;
|
||||
},
|
||||
"notes-per-second": (playlist1, playlist2) => {
|
||||
if (!playlist1.maxNps) {
|
||||
return playlist2.maxNps ? Comparison.LESSER : Comparison.EQUAL;
|
||||
}
|
||||
|
||||
return !playlist2.maxNps ? Comparison.GREATER : playlist1.maxNps - playlist2.maxNps;
|
||||
},
|
||||
};
|
||||
|
||||
private addTiebreak(comparator: Comparator<LocalBPListsDetails>): Comparator<LocalBPListsDetails> {
|
||||
return (playlist1, playlist2) => comparator(playlist1, playlist2) || this.getDefaultComparator()(playlist1, playlist2);
|
||||
}
|
||||
|
||||
public getComparatorKeys(): string[] {
|
||||
return Object.keys(this.comparators);
|
||||
}
|
||||
|
||||
public getDefaultComparatorKey(): string {
|
||||
return "title";
|
||||
}
|
||||
|
||||
public getDefaultComparator(): Comparator<LocalBPListsDetails> {
|
||||
return this.comparators.title;
|
||||
}
|
||||
|
||||
public getComparator(key: string): Comparator<LocalBPListsDetails> {
|
||||
const comparator = this.comparators[key];
|
||||
return comparator ? this.addTiebreak(comparator) : this.getDefaultComparator();
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,12 @@
|
||||
import { Comparator, Comparison } from "shared/models/comparator.type";
|
||||
import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface";
|
||||
import { Comparison } from "../comparator.type";
|
||||
import { Sorter } from "../sorter.model";
|
||||
import { BsmLocalMap } from "./bsm-local-map.interface";
|
||||
|
||||
export class MapsSorterService {
|
||||
private static instance: MapsSorterService;
|
||||
const sortName = (map1: BsmLocalMap, map2: BsmLocalMap) => map1.mapInfo.songName.localeCompare(map2.mapInfo.songName);
|
||||
|
||||
public static getInstance() {
|
||||
if (!MapsSorterService.instance) {
|
||||
MapsSorterService.instance = new MapsSorterService();
|
||||
}
|
||||
return MapsSorterService.instance;
|
||||
}
|
||||
|
||||
private readonly comparators: {
|
||||
[key: string]: Comparator<BsmLocalMap>;
|
||||
} = {
|
||||
name: (map1, map2) => map1.mapInfo.songName.localeCompare(map2.mapInfo.songName),
|
||||
export const mapSorter = new Sorter<BsmLocalMap>({
|
||||
comparators: {
|
||||
name: sortName,
|
||||
"song-author": (map1, map2) => map1.mapInfo.songAuthorName.localeCompare(map2.mapInfo.songAuthorName),
|
||||
"map-author": (map1, map2) => {
|
||||
// Compare the number of mappers, else compare the first mapper
|
||||
@@ -43,26 +35,8 @@ export class MapsSorterService {
|
||||
|
||||
return !map2.songDetails ? Comparison.GREATER : map1.songDetails.uploadedAt - map2.songDetails.uploadedAt;
|
||||
},
|
||||
};
|
||||
},
|
||||
tiebreak: sortName,
|
||||
defaultKey: "name"
|
||||
});
|
||||
|
||||
private addTiebreak(comparator: Comparator<BsmLocalMap>): Comparator<BsmLocalMap> {
|
||||
return (map1, map2) => comparator(map1, map2) || this.getDefaultComparator()(map1, map2);
|
||||
}
|
||||
|
||||
public getComparatorKeys(): string[] {
|
||||
return Object.keys(this.comparators);
|
||||
}
|
||||
|
||||
public getDefaultComparatorKey(): string {
|
||||
return "name";
|
||||
}
|
||||
|
||||
public getDefaultComparator(): Comparator<BsmLocalMap> {
|
||||
return this.comparators.name;
|
||||
}
|
||||
|
||||
public getComparator(key: string): Comparator<BsmLocalMap> {
|
||||
const comparator = this.comparators[key];
|
||||
return comparator ? this.addTiebreak(comparator) : this.getDefaultComparator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Comparison } from "../comparator.type";
|
||||
import { Sorter } from "../sorter.model";
|
||||
import { LocalBPListsDetails } from "./local-playlist.models";
|
||||
|
||||
const sortTitle = (playlist1: LocalBPListsDetails, playlist2: LocalBPListsDetails) =>
|
||||
playlist1.playlistTitle.localeCompare(playlist2.playlistTitle);
|
||||
|
||||
export const playlistSorter = new Sorter({
|
||||
comparators: {
|
||||
title: sortTitle,
|
||||
author: (playlist1, playlist2) => playlist1.playlistAuthor.localeCompare(playlist2.playlistAuthor),
|
||||
"number-of-maps": (playlist1, playlist2) => playlist1.nbMaps - playlist2.nbMaps,
|
||||
duration: (playlist1, playlist2) => {
|
||||
if (!playlist1.duration) {
|
||||
return playlist2.duration ? Comparison.LESSER : Comparison.EQUAL;
|
||||
}
|
||||
|
||||
return !playlist2.duration ? Comparison.GREATER : playlist1.duration - playlist2.duration;
|
||||
},
|
||||
"notes-per-second": (playlist1, playlist2) => {
|
||||
if (!playlist1.maxNps) {
|
||||
return playlist2.maxNps ? Comparison.LESSER : Comparison.EQUAL;
|
||||
}
|
||||
|
||||
return !playlist2.maxNps ? Comparison.GREATER : playlist1.maxNps - playlist2.maxNps;
|
||||
},
|
||||
},
|
||||
tiebreak: sortTitle,
|
||||
defaultKey: "title",
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Comparator } from "./comparator.type";
|
||||
|
||||
export type SorterOptions<T> = {
|
||||
defaultKey: string;
|
||||
comparators: Record<string, Comparator<T>>;
|
||||
tiebreak: Comparator<T>;
|
||||
}
|
||||
|
||||
export class Sorter<T> {
|
||||
public readonly defaultKey: string;
|
||||
|
||||
private readonly comparators: Record<string, Comparator<T>>;
|
||||
private readonly tiebreak: Comparator<T>;
|
||||
|
||||
constructor(options: SorterOptions<T>) {
|
||||
this.defaultKey = options.defaultKey;
|
||||
this.comparators = options.comparators;
|
||||
this.tiebreak = options.tiebreak;
|
||||
}
|
||||
|
||||
public getComparatorKeys(): string[] {
|
||||
return Object.keys(this.comparators);
|
||||
}
|
||||
|
||||
public getDefaultComparator(): Comparator<T> {
|
||||
return this.comparators[this.defaultKey];
|
||||
}
|
||||
|
||||
public getComparator(key: string): Comparator<T> {
|
||||
const comparator = this.comparators[key] || this.comparators[this.defaultKey];
|
||||
return this.tiebreak === comparator
|
||||
? comparator
|
||||
: (object1, object2) => comparator(object1, object2) || this.tiebreak(object1, object2);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user