fix rerendering AND fix downloader map folder name

This commit is contained in:
MathieuG-P
2022-12-07 01:33:24 +01:00
parent f038ae79fb
commit 57e0c73a31
8 changed files with 50 additions and 39 deletions
+1 -4
View File
@@ -12111,7 +12111,6 @@
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz",
"integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
"dev": true,
"requires": {
"truncate-utf8-bytes": "^1.0.0"
}
@@ -13207,7 +13206,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
"integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==",
"dev": true,
"requires": {
"utf8-byte-length": "^1.0.1"
}
@@ -13567,8 +13565,7 @@
"utf8-byte-length": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
"integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==",
"dev": true
"integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA=="
},
"util-deprecate": {
"version": "1.0.2",
+1
View File
@@ -248,6 +248,7 @@
"react-visibility-sensor": "^5.1.1",
"regedit": "^5.1.1",
"rxjs": "^7.5.6",
"sanitize-filename": "^1.6.3",
"semver": "^7.3.8",
"tailwind-scrollbar-hide": "^1.1.7",
"tailwindcss-scoped-groups": "^2.0.0",
+3 -2
View File
@@ -4,6 +4,7 @@ import { UtilsService } from "../services/utils.service";
import { BSVersion } from "shared/bs-version.interface";
import { IpcRequest } from "shared/models/ipc";
import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface";
import { BsvMapDetail } from "shared/models/maps";
ipcMain.on('get-version-maps', (event, request: IpcRequest<BSVersion>) => {
const utilsService = UtilsService.getInstance();
@@ -60,11 +61,11 @@ ipcMain.on("delete-maps", async (event, request: IpcRequest<{version: BSVersion,
});
});
ipcMain.on("download-map", async (event, request: IpcRequest<{zipUrl: string, version: BSVersion}>) => {
ipcMain.on("download-map", async (event, request: IpcRequest<{map: BsvMapDetail, version: BSVersion}>) => {
const utils = UtilsService.getInstance();
const maps = LocalMapsManagerService.getInstance();
maps.downloadMap(request.args.zipUrl, request.args.version).then(() => {
maps.downloadMap(request.args.map, request.args.version).then(() => {
utils.ipcSend(request.responceChannel, {success: true});
}).catch(err => {
console.log(err);
@@ -1,6 +1,6 @@
import path from "path";
import { BSVersion } from "shared/bs-version.interface";
import { RawMapInfoData } from "shared/models/maps";
import { BsvMapDetail, RawMapInfoData } from "shared/models/maps";
import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface";
import { BSLocalVersionService } from "../bs-local-version.service";
import { InstallationLocationService } from "../installation-location.service";
@@ -10,6 +10,7 @@ import { lstatSync, symlinkSync, unlinkSync, readdirSync } from "fs";
import { copySync } from "fs-extra";
import StreamZip from "node-stream-zip";
import { RequestService } from "../request.service";
import sanitize from "sanitize-filename";
export class LocalMapsManagerService {
@@ -162,16 +163,19 @@ export class LocalMapsManagerService {
}
public async downloadMap(zipUrl: string, version?: BSVersion){
public async downloadMap(map: BsvMapDetail, version?: BSVersion){
console.log(zipUrl, version);
if(!map.versions.at(0).hash){ throw "Cannot download map, no hash found"; }
const zipUrl = `https://r2cdn.beatsaver.com/${map.versions.at(0).hash}.zip`
const mapsFolder = await this.getMapsFolderPath(version);
const {zip, zipPath} = await this.downloadMapZip(zipUrl);
const zipName = path.parse(zipPath).name;
const mapPath = path.join(mapsFolder, zipName);
const mapFolderName = sanitize(`${map.id}-${map.name}`);
const mapPath = path.join(mapsFolder, mapFolderName);
if(!zip){ throw `Cannot download ${zipUrl}`; }
@@ -1,6 +1,6 @@
import { MapsManagerService } from "renderer/services/maps-manager.service"
import { BSVersion } from "shared/bs-version.interface"
import { useEffect, useRef, useState } from "react"
import { useCallback, useEffect, useRef, useState } from "react"
import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface"
import { Subscription } from "rxjs"
import { MapItem, ParsedMapDiff } from "./map-item.component"
@@ -46,9 +46,11 @@ export function LocalMapsListPanel({version, className, filter, search} : Props)
subs.push(mapsManager.getMaps(version).subscribe(localMaps => setMaps(() => [...localMaps])));
}
const handleDelete = (map: BsmLocalMap) => {
const handleDelete = useCallback((hash: string) => {
const map = maps.find(map => map.hash === hash);
console.log(maps);
mapsManager.deleteMaps([map], version).then(res => res && loadMaps())
}
}, [maps]);
const extractMapDiffs = (map: BsmLocalMap): Map<BsvMapCharacteristic, ParsedMapDiff[]> => {
const res = new Map<BsvMapCharacteristic, ParsedMapDiff[]>();
@@ -73,7 +75,7 @@ export function LocalMapsListPanel({version, className, filter, search} : Props)
return res;
}
const onMapSelected = (hash: string) => {
const onMapSelected = useCallback((hash: string) => {
const hashs = [...selectedMaps];
if(hashs.some(selectedHash => selectedHash === hash)){
const i = hashs.findIndex(selectedHash => selectedHash === hash);
@@ -83,7 +85,7 @@ export function LocalMapsListPanel({version, className, filter, search} : Props)
hashs.push(hash);
}
setSelectedMaps(() => hashs);
}
}, [selectedMaps]);
const isMapFitFilter = (map: BsmLocalMap): boolean => {
@@ -199,8 +201,9 @@ export function LocalMapsListPanel({version, className, filter, search} : Props)
duration={map.bsaverInfo?.metadata?.duration}
selected={selectedMaps.some(hash => hash === map.hash)}
diffs={extractMapDiffs(map)} mapId={map.bsaverInfo?.id} qualified={null} ranked={map.bsaverInfo?.ranked} autorId={map.bsaverInfo?.uploader?.id} likes={map.bsaverInfo?.stats?.upvotes} createdAt={map.bsaverInfo?.createdAt}
onDelete={() => handleDelete(map)}
onDelete={handleDelete}
onSelected={onMapSelected}
callBackParam={map.hash}
/>;
}
@@ -19,7 +19,7 @@ import { BsmBasicSpinner } from "../shared/bsm-basic-spinner/bsm-basic-spinner.c
export type ParsedMapDiff = {type: BsvMapDifficultyType, name: string, stars: number}
export type MapItemProps = {
export type MapItemProps<T = any> = {
hash: string,
title: string,
autor: string,
@@ -37,19 +37,18 @@ export type MapItemProps = {
createdAt: string,
selected?: boolean,
downloading?: boolean,
onDelete?: (hash: string) => void,
onDownload?: (zipUrl: string) => void,
onSelected?: (hash: string) => void,
onCancelDownload?: (zipUrl: string) => void
callBackParam: T
onDelete?: (param: T) => void,
onDownload?: (param: T) => void,
onSelected?: (param: T) => void,
onCancelDownload?: (param: T) => void
}
export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl, autorId, mapId, diffs, qualified, ranked, bpm, duration, likes, createdAt, selected, downloading, onDelete, onDownload, onSelected, onCancelDownload}: MapItemProps) => {
export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl, autorId, mapId, diffs, qualified, ranked, bpm, duration, likes, createdAt, selected, downloading, callBackParam, onDelete, onDownload, onSelected, onCancelDownload}: MapItemProps) => {
const linkOpener = LinkOpenerService.getInstance();
const audioPlayer = AudioPlayerService.getInstance();
const color = useThemeColor("first-color");
const [hovered, setHovered] = useState(false);
@@ -132,7 +131,7 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
}
return (
<motion.li className="relative h-[100px] min-w-[370px] shrink-0 grow basis-0 text-white group cursor-pointer" onHoverStart={() => setHovered(true)} onHoverEnd={() => setHovered(false)} style={{zIndex: hovered && 5, transform: "translateZ(0) scale(1.0, 1.0)", backfaceVisibility: "hidden"}} onClick={e => {onSelected?.(hash)}}>
<motion.li className="relative h-[100px] min-w-[370px] shrink-0 grow basis-0 text-white group cursor-pointer" onHoverStart={() => setHovered(true)} onHoverEnd={() => setHovered(false)} style={{zIndex: hovered && 5, transform: "translateZ(0) scale(1.0, 1.0)", backfaceVisibility: "hidden"}} onClick={e => {onSelected?.(callBackParam)}}>
{(hovered || selected) && onSelected && <motion.span className="glow-on-hover !transition-none" animate={{opacity: 1}} transition={{duration: .2, ease: "linear"}}/>}
<AnimatePresence>
{(diffsPanelHovered || bottomBarHovered) && (
@@ -209,9 +208,9 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
<span className="absolute w-[10px] h-[10px] bottom-0 right-full bg-inherit" style={{clipPath: 'path("M11 11 L11 0 L10 0 A10 10 0 0 1 0 10 L 0 11 Z")'}}/>
<div className="flex flex-col justify-center items-center gap-1 w-full h-full overflow-hidden opacity-0 group-hover:opacity-100">
{onDelete && !downloading && <BsmButton className="w-6 h-6 p-[2px] rounded-md !bg-inherit hover:!bg-main-color-2" iconClassName="w-full h-full brightness-150" iconColor={color} icon="trash" withBar={false} onClick={e => {e.stopPropagation(); onDelete(hash)}}/>}
{onDownload && !downloading && <BsmButton className="w-6 h-6 p-[2px] rounded-md !bg-inherit hover:!bg-main-color-2" iconClassName="w-full h-full brightness-150" iconColor={color} icon="download" withBar={false} onClick={e => {e.stopPropagation(); onDownload(zipUrl)}}/>}
{onCancelDownload && !downloading && <BsmButton className="w-6 h-6 p-1 rounded-md !bg-inherit hover:!bg-main-color-2" iconClassName="w-full h-full brightness-150" iconColor={"red"} icon="cross" withBar={false} onClick={e => {e.stopPropagation(); onCancelDownload(zipUrl)}}/>}
{onDelete && !downloading && <BsmButton className="w-6 h-6 p-[2px] rounded-md !bg-inherit hover:!bg-main-color-2" iconClassName="w-full h-full brightness-150" iconColor={color} icon="trash" withBar={false} onClick={e => {e.stopPropagation(); onDelete(callBackParam)}}/>}
{onDownload && !downloading && <BsmButton className="w-6 h-6 p-[2px] rounded-md !bg-inherit hover:!bg-main-color-2" iconClassName="w-full h-full brightness-150" iconColor={color} icon="download" withBar={false} onClick={e => {e.stopPropagation(); onDownload(callBackParam)}}/>}
{onCancelDownload && !downloading && <BsmButton className="w-6 h-6 p-1 rounded-md !bg-inherit hover:!bg-main-color-2" iconClassName="w-full h-full brightness-150" iconColor={"red"} icon="cross" withBar={false} onClick={e => {e.stopPropagation(); onCancelDownload(callBackParam)}}/>}
{downloading && <BsmBasicSpinner className="w-6 h-6 p-1 rounded-md !bg-inherit hover:!bg-main-color-2 flex items-center justify-center" spinnerClassName="brightness-150" style={{color}} thikness="3px"/>}
{previewUrl && <BsmButton className="w-6 h-6 p-[2px] rounded-md !bg-inherit hover:!bg-main-color-2" iconClassName="w-full h-full brightness-150" iconColor={color} icon="eye" withBar={false} onClick={e => {e.stopPropagation(); openPreview()}}/>}
{mapId && <BsmButton className="w-6 h-6 p-1 rounded-md !bg-inherit hover:!bg-main-color-2" iconClassName="w-full h-full brightness-150" iconColor={color} icon="twitch" withBar={false} onClick={e => {e.stopPropagation(); copyBsr()}}/>}
@@ -223,6 +222,11 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl,
}, areEqual)
function areEqual(prevProps: MapItemProps, nextProps: MapItemProps): boolean {
Array.from(Object.entries(prevProps)).forEach(v => {
if(!equal(prevProps[v[0]], nextProps[v[0]])){
console.log(v[0]);
}
});
return equal(prevProps, nextProps);
}
@@ -1,5 +1,5 @@
import { motion } from "framer-motion";
import { useEffect, useRef, useState } from "react";
import { Fragment, useCallback, useEffect, useRef, useState } from "react";
import { FilterPanel } from "renderer/components/maps-mangement-components/filter-panel.component";
import { MapItem, ParsedMapDiff } from "renderer/components/maps-mangement-components/map-item.component";
import { BsmButton } from "renderer/components/shared/bsm-button.component";
@@ -92,7 +92,7 @@ export const DownloadMapsModal: ModalComponent<void, BSVersion> = ({data}) => {
const inQueue = mapsInQueue.some(toDownload => equal(toDownload.version, data) && toDownload.map.id === map.id);
return (
<MapItem
<MapItem
autor={map.metadata.levelAuthorName}
autorId={map.uploader.id}
bpm={map.metadata.bpm}
@@ -109,20 +109,21 @@ export const DownloadMapsModal: ModalComponent<void, BSVersion> = ({data}) => {
diffs={extractMapDiffs(map)}
songUrl={map.versions.at(0).previewURL}
key={map.id}
onDownload={(!isMapOwned && !inQueue) && (() => {handleDownloadMap(map)})}
onCancelDownload={(inQueue && !isDownloading) && (() => {handleCancelDownload(map)})}
onDownload={(!isMapOwned && !inQueue) && (handleDownloadMap)}
onCancelDownload={(inQueue && !isDownloading) && (handleCancelDownload)}
downloading={isDownloading}
callBackParam={map}
/>
)
}
const handleDownloadMap = (map: BsvMapDetail) => {
mapsDownloader.addMapToDownload({map, version: data});
}
const handleDownloadMap = useCallback((map: BsvMapDetail) => {
mapsDownloader.addMapToDownload({map, version: data})
}, []);
const handleCancelDownload = (map: BsvMapDetail) => {
const handleCancelDownload = useCallback((map: BsvMapDetail) => {
mapsDownloader.removeMapToDownload({map, version: data});
}
}, []);
const handleSearch = () => {
const searchParams: SearchParams = {
@@ -72,7 +72,7 @@ export class MapsDownloaderService {
private async downloadMap(map: BsvMapDetail, version: BSVersion): Promise<boolean>{
if(this.os.isOffline){ return false }
const res = await this.ipc.send("download-map", {args: {zipUrl: getMapZipUrlFromMapDetails(map), version}});
const res = await this.ipc.send<void, {map: BsvMapDetail, version: BSVersion}>("download-map", {args: {map, version}});
return res.success;
}