diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index 75f6b551..377a4ea7 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -737,7 +737,8 @@ "nps" : "Notes Per Second", "tags": "tags", "specificities": "general", - "requirements": "requirements" + "requirements": "requirements", + "exclude": "exclude" }, "map-types": { "accuracy": "accuracy", @@ -793,6 +794,9 @@ "verified": "verified", "fullSpread": "full spread" }, + "map-excludes": { + "installed": "installed" + }, "difficulties": { "Easy": "easy", "Normal": "normal", diff --git a/src/renderer/components/maps-mangement-components/filter-panel.component.tsx b/src/renderer/components/maps-mangement-components/filter-panel.component.tsx index 7962b23e..c975ca0f 100644 --- a/src/renderer/components/maps-mangement-components/filter-panel.component.tsx +++ b/src/renderer/components/maps-mangement-components/filter-panel.component.tsx @@ -11,6 +11,7 @@ import { useTranslation } from "renderer/hooks/use-translation.hook"; import { MAP_SPECIFICITIES } from "renderer/partials/maps/map-general/map-specificity"; import { MAP_REQUIREMENTS } from "renderer/partials/maps/map-requirements/map-requirements"; import { MAP_DIFFICULTIES_COLORS } from "renderer/partials/maps/map-difficulties/map-difficulties-colors"; +import { MapExclude, MAP_EXCLUDES } from "renderer/partials/maps/map-excludes/map-excludes"; import { BsmButton } from "../shared/bsm-button.component"; import equal from "fast-deep-equal/es6"; import clone from "rfdc"; @@ -147,6 +148,10 @@ export function FilterPanel({ className, ref, playlist = false, filter, onChange return t(`maps.map-specificities.${specificity}`); }; + const translateMapExclude = (exclude: MapExclude): string => { + return t(`maps.map-excludes.${exclude}`); + }; + type BooleanKeys = { [k in keyof T]: T[k] extends boolean ? k : never }[keyof T]; const handleCheckbox = (key: BooleanKeys) => { @@ -189,6 +194,13 @@ export function FilterPanel({ className, ref, playlist = false, filter, onChange {requirement} ))} +

{t("maps.map-filter-panel.exclude")}

+ {MAP_EXCLUDES.map(exclude => ( +
handleCheckbox(exclude)}> + handleCheckbox(exclude)} /> + {translateMapExclude(exclude)} +
+ ))}

{t("maps.map-filter-panel.tags")}

diff --git a/src/renderer/components/modal/modal-types/download-maps-modal.component.tsx b/src/renderer/components/modal/modal-types/download-maps-modal.component.tsx index 04fa513b..de413fd2 100644 --- a/src/renderer/components/modal/modal-types/download-maps-modal.component.tsx +++ b/src/renderer/components/modal/modal-types/download-maps-modal.component.tsx @@ -76,12 +76,48 @@ export const DownloadMapsModal: ModalComponent { + const applyInstalledFilter = (maps: BsvMapDetail[]): BsvMapDetail[] => { + return maps.filter(map => { + if (!filter.installed) { + return true; + } + + return !map.versions.some(version => ownedMapHashs.includes(version.hash)); + }); + } + + const loadMaps = (params: SearchParams, tryToLoad = 5) => { setLoading(() => true); - beatSaver - .searchMaps(params) - .then(maps => setMaps(prev => [...prev, ...maps])) - .finally(() => setLoading(() => false)); + + const searchResult = beatSaver.searchMaps(params); + + if (!filter.installed) { + searchResult + .then(maps => setMaps(prev => [...prev, ...maps])) + .finally(() => setLoading(() => false)); + + return; + } + + searchResult + .then(maps => { + if (!maps.length) { + setLoading(() => false); + + return; + } + + maps = applyInstalledFilter(maps); + setMaps(prev => [...prev, ...maps]) + + if (maps.length < tryToLoad) { + handleLoadMore(); + + return; + } + + setLoading(() => false); + }) }; const extractMapDiffs = (map: BsvMapDetail): Map => { diff --git a/src/renderer/partials/maps/map-excludes/map-excludes.ts b/src/renderer/partials/maps/map-excludes/map-excludes.ts new file mode 100644 index 00000000..8244cc6a --- /dev/null +++ b/src/renderer/partials/maps/map-excludes/map-excludes.ts @@ -0,0 +1,3 @@ +export type MapExclude = "installed"; + +export const MAP_EXCLUDES: MapExclude[] = ["installed"]; diff --git a/src/shared/models/maps/beat-saver.model.ts b/src/shared/models/maps/beat-saver.model.ts index aec24b93..e40939fa 100644 --- a/src/shared/models/maps/beat-saver.model.ts +++ b/src/shared/models/maps/beat-saver.model.ts @@ -162,6 +162,7 @@ export interface MapFilter { to?: number; fullSpread?: boolean; ranked?: boolean; + installed?: boolean; minDuration?: number; maxDuration?: number; minNps?: number;