diff --git a/src/renderer/components/maps-mangement-components/local-maps-list-panel.component.tsx b/src/renderer/components/maps-mangement-components/local-maps-list-panel.component.tsx
index e48061df..fedbb615 100644
--- a/src/renderer/components/maps-mangement-components/local-maps-list-panel.component.tsx
+++ b/src/renderer/components/maps-mangement-components/local-maps-list-panel.component.tsx
@@ -24,7 +24,7 @@ export function LocalMapsListPanel({version, className} : Props) {
const subs: Subscription[] = [];
if(isVisible && !maps?.length){
- subs.push(mapsManager.getMaps(version).subscribe(localMaps => setMaps(() => localMaps)));
+ subs.push(mapsManager.getMaps(version).subscribe(localMaps => setMaps(() => [...localMaps])));
}
return () => { subs.forEach(s => s.unsubscribe()); }
@@ -53,7 +53,7 @@ export function LocalMapsListPanel({version, className} : Props) {
autor={map.rawInfo._levelAuthorName}
bpm={map.rawInfo._beatsPerMinute}
duration={null}
- diffs={extractMapDiffs(map)} mapId={null} qualified={null} ranked={null} autorLink={null}
+ diffs={extractMapDiffs(map)} mapId={map.bsaverInfo?.id} qualified={null} ranked={null} autorLink={null}
/>;
}
diff --git a/src/renderer/components/maps-mangement-components/map-item.component.tsx b/src/renderer/components/maps-mangement-components/map-item.component.tsx
index 1f293db6..67977f7a 100644
--- a/src/renderer/components/maps-mangement-components/map-item.component.tsx
+++ b/src/renderer/components/maps-mangement-components/map-item.component.tsx
@@ -1,12 +1,9 @@
-import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface"
import { BsmImage } from "../shared/bsm-image.component";
import { BsvMapCharacteristic, BsvMapDifficultyType } from "shared/models/maps/beat-saver.model"
import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
-import { LinkOpenerService } from "renderer/services/link-opener.service";
import { BsmLink } from "../shared/bsm-link.component";
import { BsmIcon } from "../svgs/bsm-icon.component";
import { BsmButton } from "../shared/bsm-button.component";
-import { MouseEventHandler } from "react";
export type MapItemProps = {
hash: string,
@@ -29,10 +26,10 @@ export function MapItem({hash, title, autor, coverUrl, songUrl, autorLink, mapId
const color = useThemeColor("first-color");
- const zipUrl = `https://r2cdn.beatsaver.com/${hash}.zip`
- const previewUrl = `https://skystudioapps.com/bs-viewer/?url=${zipUrl}`
+ const zipUrl = `https://r2cdn.beatsaver.com/${hash}.zip`;
+ const previewUrl = `https://skystudioapps.com/bs-viewer/?url=${zipUrl}`;
+ const mapUrl = mapId ? `https://beatsaver.com/maps/${mapId}` : null;
- console.log(diffs)
const renderAutor = () => {
if(!autor){ null; }
@@ -47,7 +44,7 @@ export function MapItem({hash, title, autor, coverUrl, songUrl, autorLink, mapId
const colorPill = diffColors[diff] ?? "";
return (
-
+
{diff === "ExpertPlus" ? "Expert+" : diff}
@@ -76,7 +73,7 @@ export function MapItem({hash, title, autor, coverUrl, songUrl, autorLink, mapId
-
{title}
+
{title}
{renderAutor()}
{Array.from(diffs.entries()).map(([charac, diffs]) => diffs.map(diff => renderDiff(charac, diff)))}
diff --git a/src/renderer/components/shared/bsm-link.component.tsx b/src/renderer/components/shared/bsm-link.component.tsx
index f91617ef..896fde52 100644
--- a/src/renderer/components/shared/bsm-link.component.tsx
+++ b/src/renderer/components/shared/bsm-link.component.tsx
@@ -1,6 +1,4 @@
import { LinkOpenerService } from "renderer/services/link-opener.service"
-import { ModalService } from "renderer/services/modale.service";
-import { IframeModal } from "../modal/modal-types/iframe-modal.component";
type Props = {
className?: string,
@@ -15,6 +13,7 @@ export function BsmLink({className, href, children, style, internal}: Props) {
const linkOpener = LinkOpenerService.getInstance();
const openLink = () => {
+ if(!href){ return; }
linkOpener.open(href, internal);
}
diff --git a/src/renderer/models/api/api.model.ts b/src/renderer/models/api/api.model.ts
new file mode 100644
index 00000000..ee82bba6
--- /dev/null
+++ b/src/renderer/models/api/api.model.ts
@@ -0,0 +1,4 @@
+export interface ApiResult{
+ status: number,
+ data: T
+}
\ No newline at end of file
diff --git a/src/renderer/services/beat-saver.service.ts b/src/renderer/services/beat-saver.service.ts
deleted file mode 100644
index f3c7a217..00000000
--- a/src/renderer/services/beat-saver.service.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { BsvMapDetail } from "shared/models/maps";
-
-export class BeatSaverService {
-
- private static instance: BeatSaverService;
-
- public static getInstance(): BeatSaverService{
- if(!BeatSaverService.instance){ BeatSaverService.instance = new BeatSaverService(); }
- return BeatSaverService.instance;
- }
-
- private constructor(){}
-
- public getMapDetailsFromHashs(hashs: string[]): BsvMapDetail{
- return null;
- }
-
-}
\ No newline at end of file
diff --git a/src/renderer/services/beat-saver/beat-saver-api.service.ts b/src/renderer/services/beat-saver/beat-saver-api.service.ts
new file mode 100644
index 00000000..0eeb32be
--- /dev/null
+++ b/src/renderer/services/beat-saver/beat-saver-api.service.ts
@@ -0,0 +1,31 @@
+import { ApiResult } from "renderer/models/api/api.model";
+import { BsvMapDetail } from "shared/models/maps";
+
+export class BeatSaverApiService {
+
+ private static instance: BeatSaverApiService;
+
+ public static getInstance(): BeatSaverApiService{
+ if(!BeatSaverApiService.instance){ BeatSaverApiService.instance = new BeatSaverApiService(); }
+ return BeatSaverApiService.instance;
+ }
+
+ private readonly bsaverApiUrl = "https://beatsaver.com/api"
+
+ private constructor(){}
+
+ public async getMapsDetailsByHashs(hashs: T[]): Promise, BsvMapDetail>>>{
+
+ if(hashs.length > 50){ throw "too musch map hashs"; }
+
+ const paramsHashs = hashs.join(",");
+
+ const resp = await fetch(`${this.bsaverApiUrl}/maps/hash/${paramsHashs}`);
+
+ const data = await resp.json() as Record, BsvMapDetail>;
+
+ return {status: resp.status, data: data};
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/renderer/services/beat-saver/beat-saver.service.ts b/src/renderer/services/beat-saver/beat-saver.service.ts
new file mode 100644
index 00000000..482f8e5a
--- /dev/null
+++ b/src/renderer/services/beat-saver/beat-saver.service.ts
@@ -0,0 +1,44 @@
+import { splitIntoChunk } from "renderer/helpers/array-tools";
+import { Observable } from "rxjs";
+import { BsvMapDetail } from "shared/models/maps";
+import { BeatSaverApiService } from "./beat-saver-api.service";
+
+export class BeatSaverService {
+
+ private static instance: BeatSaverService;
+
+ public static getInstance(): BeatSaverService{
+ if(!BeatSaverService.instance){ BeatSaverService.instance = new BeatSaverService(); }
+ return BeatSaverService.instance;
+ }
+
+ private readonly bsaverApi: BeatSaverApiService;
+
+ private constructor(){
+ this.bsaverApi = BeatSaverApiService.getInstance();
+ }
+
+ public getMapDetailsFromHashs(hashs: string[]): Observable{
+ const chunkHash = splitIntoChunk(hashs, 50);
+
+ return new Observable(observer => {
+ (async () => {
+
+ const mapDetails: BsvMapDetail[] = [];
+
+ for(const hashs of chunkHash){
+ const res = await this.bsaverApi.getMapsDetailsByHashs(hashs);
+ if(res.status === 200){
+ mapDetails.push(...Object.values(res.data));
+ observer.next(mapDetails);
+ }
+
+ }
+
+ observer.complete();
+ })()
+ })
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/renderer/services/maps-manager.service.ts b/src/renderer/services/maps-manager.service.ts
index f263ef95..145c3866 100644
--- a/src/renderer/services/maps-manager.service.ts
+++ b/src/renderer/services/maps-manager.service.ts
@@ -1,6 +1,7 @@
import { Observable } from "rxjs";
import { BSVersion } from "shared/bs-version.interface";
import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface";
+import { BeatSaverService } from "./beat-saver/beat-saver.service";
import { IpcService } from "./ipc.service";
export class MapsManagerService {
@@ -13,9 +14,11 @@ export class MapsManagerService {
}
private readonly ipcService: IpcService;
+ private readonly bsaver: BeatSaverService;
private constructor(){
this.ipcService = IpcService.getInstance();
+ this.bsaver = BeatSaverService.getInstance();
}
public getMaps(version?: BSVersion): Observable{
@@ -24,6 +27,13 @@ export class MapsManagerService {
this.ipcService.send("get-version-maps", {args: version}).then(res => {
if(!res.success){ return obs.next(null);}
obs.next(res.data);
+
+ this.bsaver.getMapDetailsFromHashs(res.data.map(localMap => localMap.hash)).subscribe(mapsDetails => {
+ mapsDetails.forEach(details => {
+ res.data.find(localMap => localMap.hash === details.versions.find(details => details?.hash === localMap.hash)?.hash).bsaverInfo = details
+ });
+ obs.next(res.data);
+ })
});
});
}