mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
can now link and unlink version maps
This commit is contained in:
+2
-1
@@ -32,7 +32,8 @@ module.exports = {
|
||||
"@typescript-eslint/no-throw-literal": "off",
|
||||
"@typescript-eslint/no-unused-expressions": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-useless-escape": "off"
|
||||
"no-useless-escape": "off",
|
||||
"jsx-a11y/no-noninteractive-element-interactions": "off"
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
|
||||
Generated
+14
-14
@@ -1876,7 +1876,7 @@
|
||||
},
|
||||
"@types/archiver": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://npm.zone51.tf/@types%2farchiver/-/archiver-5.3.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.1.tgz",
|
||||
"integrity": "sha512-wKYZaSXaDvTZuInAWjCeGG7BEAgTWG2zZW0/f7IYFcoHB2X2d9lkVFnrOlXl3W6NrvO6Ml3FLLu8Uksyymcpnw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -2396,7 +2396,7 @@
|
||||
},
|
||||
"@types/yargs": {
|
||||
"version": "17.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types%2fyargs/-/yargs-17.0.13.tgz",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz",
|
||||
"integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -2998,7 +2998,7 @@
|
||||
},
|
||||
"archiver": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://npm.zone51.tf/archiver/-/archiver-5.3.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz",
|
||||
"integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==",
|
||||
"requires": {
|
||||
"archiver-utils": "^2.1.0",
|
||||
@@ -3012,7 +3012,7 @@
|
||||
},
|
||||
"archiver-utils": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://npm.zone51.tf/archiver-utils/-/archiver-utils-2.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz",
|
||||
"integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
|
||||
"requires": {
|
||||
"glob": "^7.1.4",
|
||||
@@ -4053,7 +4053,7 @@
|
||||
},
|
||||
"compress-commons": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://npm.zone51.tf/compress-commons/-/compress-commons-4.1.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz",
|
||||
"integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==",
|
||||
"requires": {
|
||||
"buffer-crc32": "^0.2.13",
|
||||
@@ -4281,12 +4281,12 @@
|
||||
},
|
||||
"crc-32": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://npm.zone51.tf/crc-32/-/crc-32-1.2.2.tgz",
|
||||
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
||||
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
|
||||
},
|
||||
"crc32-stream": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://npm.zone51.tf/crc32-stream/-/crc32-stream-4.0.2.tgz",
|
||||
"resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz",
|
||||
"integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==",
|
||||
"requires": {
|
||||
"crc-32": "^1.2.0",
|
||||
@@ -6895,7 +6895,7 @@
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://npm.zone51.tf/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
||||
},
|
||||
"fs-extra": {
|
||||
@@ -9447,7 +9447,7 @@
|
||||
},
|
||||
"lazystream": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://npm.zone51.tf/lazystream/-/lazystream-1.0.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
|
||||
"integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
|
||||
"requires": {
|
||||
"readable-stream": "^2.0.5"
|
||||
@@ -11763,7 +11763,7 @@
|
||||
},
|
||||
"readdir-glob": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://npm.zone51.tf/readdir-glob/-/readdir-glob-1.1.2.tgz",
|
||||
"resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz",
|
||||
"integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==",
|
||||
"requires": {
|
||||
"minimatch": "^5.1.0"
|
||||
@@ -11771,7 +11771,7 @@
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://npm.zone51.tf/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0"
|
||||
@@ -11779,7 +11779,7 @@
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://npm.zone51.tf/minimatch/-/minimatch-5.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
|
||||
"integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
|
||||
"requires": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
@@ -12945,7 +12945,7 @@
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://npm.zone51.tf/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||
"requires": {
|
||||
"bl": "^4.0.3",
|
||||
@@ -14135,7 +14135,7 @@
|
||||
},
|
||||
"zip-stream": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://npm.zone51.tf/zip-stream/-/zip-stream-4.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz",
|
||||
"integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==",
|
||||
"requires": {
|
||||
"archiver-utils": "^2.1.0",
|
||||
|
||||
@@ -232,6 +232,7 @@
|
||||
"electron-store": "^8.1.0",
|
||||
"electron-updater": "^5.2.4",
|
||||
"framer-motion": "^7.2.1",
|
||||
"fs-extra": "^10.1.0",
|
||||
"history": "^5.3.0",
|
||||
"is-online": "^9.0.1",
|
||||
"md5-file": "^5.0.0",
|
||||
|
||||
@@ -21,7 +21,30 @@ ipcMain.on("verion-have-maps-linked", async (event, request: IpcRequest<BSVersio
|
||||
const utils = UtilsService.getInstance();
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
|
||||
console.log(request.args);
|
||||
utils.ipcSend<boolean>(request.responceChannel, {success: true, data: await maps.versionIsLinked(request.args)});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("link-version-maps", async (event, request: IpcRequest<{version: BSVersion, keepMaps: boolean}>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
|
||||
maps.linkVersionMaps(request.args.version, request.args.keepMaps).then(() => {
|
||||
utils.ipcSend<void>(request.responceChannel, {success: true});
|
||||
}).catch(err => {
|
||||
utils.ipcSend<void>(request.responceChannel, {success: true, error: err});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
ipcMain.on("unlink-version-maps", async (event, request: IpcRequest<{version: BSVersion, keepMaps: boolean}>) => {
|
||||
const utils = UtilsService.getInstance();
|
||||
const maps = LocalMapsManagerService.getInstance();
|
||||
|
||||
maps.unlinkVersionMaps(request.args.version, request.args.keepMaps).then(() => {
|
||||
utils.ipcSend<void>(request.responceChannel, {success: true});
|
||||
}).catch(err => {
|
||||
utils.ipcSend<void>(request.responceChannel, {success: true, error: err});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -6,7 +6,8 @@ import { BSLocalVersionService } from "../bs-local-version.service";
|
||||
import { InstallationLocationService } from "../installation-location.service";
|
||||
import { UtilsService } from "../utils.service";
|
||||
import crypto from "crypto";
|
||||
import { lstat, lstatSync, symlinkSync } from "fs";
|
||||
import { lstat, lstatSync, symlinkSync, readdir, fstat, unlinkSync } from "fs";
|
||||
import { copySync } from "fs-extra";
|
||||
|
||||
export class LocalMapsManagerService {
|
||||
|
||||
@@ -32,7 +33,11 @@ export class LocalMapsManagerService {
|
||||
|
||||
private async getMapsFolderPath(version?: BSVersion): Promise<string>{
|
||||
if(version){ return path.join(await this.localVersion.getVersionPath(version), this.LEVELS_ROOT_FOLDER, this.CUSTOM_LEVELS_FOLDER); }
|
||||
return path.join(this.installLocation.sharedMapsPath, this.CUSTOM_LEVELS_FOLDER);
|
||||
const sharedMapsPath = path.join(this.installLocation.sharedMapsPath, this.CUSTOM_LEVELS_FOLDER);
|
||||
if(!(await this.utils.pathExist(sharedMapsPath))){
|
||||
this.utils.createFolderIfNotExist(sharedMapsPath);
|
||||
}
|
||||
return sharedMapsPath;
|
||||
}
|
||||
|
||||
private async computeMapHash(mapPath: string, rawInfoString: string): Promise<string>{
|
||||
@@ -42,7 +47,7 @@ export class LocalMapsManagerService {
|
||||
for(const diff of set._difficultyBeatmaps){
|
||||
const diffFilePath = path.join(mapPath, diff._beatmapFilename);
|
||||
if(!await this.utils.pathExist(diffFilePath)){ continue; }
|
||||
const diffContent = (await this.utils.readFileAsync(diffFilePath)).toString()
|
||||
const diffContent = (await this.utils.readFileAsync(diffFilePath)).toString();
|
||||
content += diffContent;
|
||||
}
|
||||
}
|
||||
@@ -69,27 +74,19 @@ export class LocalMapsManagerService {
|
||||
}
|
||||
|
||||
public async getMaps(version?: BSVersion): Promise<BsmLocalMap[]>{
|
||||
const levelsFolder = await this.getMapsFolderPath(version)
|
||||
const levelsFolder = await this.getMapsFolderPath(version);
|
||||
|
||||
const levelsPath = (await this.utils.pathExist(levelsFolder)) ? this.utils.listDirsInDir(levelsFolder, true) : [];
|
||||
|
||||
const mapsInfo = await Promise.all(levelsPath.map(levelPath => this.loadMapInfoFromPath(levelPath)))
|
||||
|
||||
console.log(mapsInfo);
|
||||
const mapsInfo = await Promise.all(levelsPath.map(levelPath => this.loadMapInfoFromPath(levelPath)));
|
||||
|
||||
return mapsInfo.filter(info => !!info);
|
||||
}
|
||||
|
||||
public deleteMap(version?: BSVersion){
|
||||
|
||||
}
|
||||
|
||||
public async versionIsLinked(version: BSVersion): Promise<boolean>{
|
||||
|
||||
const levelsPath = await this.getMapsFolderPath(version);
|
||||
|
||||
console.log(levelsPath, version);
|
||||
|
||||
const isPathExist = await this.utils.pathExist(levelsPath);
|
||||
|
||||
if(!isPathExist){ return false; }
|
||||
@@ -97,13 +94,37 @@ export class LocalMapsManagerService {
|
||||
return lstatSync(levelsPath).isSymbolicLink()
|
||||
}
|
||||
|
||||
public async linkVersionMaps(verion: BSVersion, includeVersionMaps: boolean): Promise<void>{
|
||||
//TODO
|
||||
//Can use fs.symlink to create symlink
|
||||
public async linkVersionMaps(version: BSVersion, keepMaps: boolean): Promise<void>{
|
||||
|
||||
if(await this.versionIsLinked(version)){ return; }
|
||||
|
||||
const sharedMapsPath = await this.getMapsFolderPath();
|
||||
const versionMapsPath = await this.getMapsFolderPath(version);
|
||||
|
||||
if(keepMaps){
|
||||
await this.utils.moveDirContent(versionMapsPath, sharedMapsPath);
|
||||
}
|
||||
|
||||
await this.utils.deleteFolder(versionMapsPath);
|
||||
|
||||
symlinkSync(sharedMapsPath, versionMapsPath, "junction");
|
||||
}
|
||||
|
||||
public async unlinkVersionMaps(version: BSVersion, keepLinkedMaps: boolean): Promise<void>{
|
||||
//TODO
|
||||
public async unlinkVersionMaps(version: BSVersion, keepMaps: boolean): Promise<void>{
|
||||
|
||||
const sharedMapsPath = await this.getMapsFolderPath();
|
||||
const versionMapsPath = await this.getMapsFolderPath(version);
|
||||
|
||||
if(await this.versionIsLinked(version)){
|
||||
unlinkSync(versionMapsPath);
|
||||
}
|
||||
|
||||
this.utils.createFolderIfNotExist(versionMapsPath);
|
||||
|
||||
if(keepMaps){
|
||||
copySync(sharedMapsPath, versionMapsPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { existsSync, mkdirSync, readdirSync, readFile, unlinkSync } from "fs";
|
||||
import { moveSync } from "fs-extra"
|
||||
import { spawnSync } from "child_process";
|
||||
import { homedir } from "os";
|
||||
import path from "path";
|
||||
@@ -75,9 +76,23 @@ export class UtilsService{
|
||||
}
|
||||
|
||||
public deleteFolder(folderPath: string): Promise<void>{
|
||||
const folderExist = this.pathExist(folderPath);
|
||||
if(!folderExist){ return; }
|
||||
return rm(folderPath, {recursive: true});
|
||||
}
|
||||
|
||||
public async moveDirContent(src: string, dest: string, overwrite = false): Promise<void>{
|
||||
const [srcExist, destExist] = await Promise.all([this.pathExist(src), this.pathExist(dest)]);
|
||||
if(!srcExist){ return; }
|
||||
if(!destExist){ await this.createFolderIfNotExist(dest); }
|
||||
readdirSync(src, {encoding: "utf-8"}).forEach(file => {
|
||||
const srcFullPath = path.join(src, file);
|
||||
const destFullPath = path.join(dest, file);
|
||||
if(!overwrite && this.pathExist(destFullPath)){ return; }
|
||||
moveSync(srcFullPath, destFullPath, {overwrite});
|
||||
});
|
||||
}
|
||||
|
||||
public ipcSend<T = any>(channel: string, response: IpcResponse<T>): void{
|
||||
try {
|
||||
this.mainWindow.webContents.send(channel, response);
|
||||
|
||||
+8
-1
@@ -27,9 +27,16 @@ export function LocalMapsListPanel({version, className, filter, search} : Props)
|
||||
|
||||
const subs: Subscription[] = [];
|
||||
|
||||
if(isVisible){
|
||||
const loadMaps = () => {
|
||||
console.log("LOAD MAPS");
|
||||
subs.push(mapsManager.getMaps(version).subscribe(localMaps => setMaps(() => [...localMaps])));
|
||||
}
|
||||
|
||||
if(isVisible){
|
||||
loadMaps();
|
||||
subs.push(mapsManager.versionLinked$.subscribe(loadMaps));
|
||||
subs.push(mapsManager.versionUnlinked$.subscribe(loadMaps));
|
||||
}
|
||||
|
||||
return () => {
|
||||
setMaps(() => []);
|
||||
|
||||
+30
-6
@@ -8,7 +8,7 @@ import { MapFilter, MapTag } from "shared/models/maps/beat-saver.model"
|
||||
import { BsmButton } from "../shared/bsm-button.component"
|
||||
import { useThemeColor } from "renderer/hooks/use-theme-color.hook"
|
||||
import { MapsManagerService } from "renderer/services/maps-manager.service"
|
||||
import { motion } from "framer-motion";
|
||||
import { motion, Variants } from "framer-motion";
|
||||
|
||||
type Props = {
|
||||
oneBlock?: boolean,
|
||||
@@ -31,9 +31,12 @@ export function MapsPlaylistsPanel({version, oneBlock = false}: Props) {
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
loadMapIsLinked();
|
||||
}, [version]);
|
||||
|
||||
const loadMapIsLinked = () => {
|
||||
mapsService.versionHaveMapsLinked(version).then(setMapsLinked);
|
||||
}, [version])
|
||||
|
||||
}
|
||||
|
||||
const handleSearch = (value: string) => {
|
||||
if(tabIndex === 0){
|
||||
@@ -42,16 +45,37 @@ export function MapsPlaylistsPanel({version, oneBlock = false}: Props) {
|
||||
return setPlaylistSearch(() => value);
|
||||
}
|
||||
|
||||
const renderTab = (props: DetailedHTMLProps<React.HTMLAttributes<any>, any>, text: string): JSX.Element => {
|
||||
const handleMapsLinkClick = () => {
|
||||
if(!mapsLinked){
|
||||
return mapsService.linkVersion(version).then(loadMapIsLinked);
|
||||
}
|
||||
mapsService.unlinkVersion(version).then(loadMapIsLinked);
|
||||
}
|
||||
|
||||
const handlePlaylistLinkClick = () => {
|
||||
|
||||
}
|
||||
|
||||
const renderTab = (props: DetailedHTMLProps<React.HTMLAttributes<HTMLLIElement>, HTMLLIElement>, text: string, index: number): JSX.Element => {
|
||||
|
||||
const mainColor = mapsLinked ? color : "red";
|
||||
|
||||
const variants: Variants = {
|
||||
hover: {rotate: 22.5},
|
||||
tap: {rotate: 45}
|
||||
}
|
||||
|
||||
const onClickLink = (index: number) => {
|
||||
if(index === 0){ return handleMapsLinkClick() };
|
||||
handlePlaylistLinkClick();
|
||||
}
|
||||
|
||||
return (
|
||||
<li className="relative text-center text-lg font-bold hover:backdrop-brightness-75 flex justify-center items-center content-center" onClick={props.onClick}>
|
||||
<span>{text}</span>
|
||||
<motion.div whileHover={{rotate: [0, 20, 0]}} transition={{duration: .35}} className="absolute block p-1 right-3 h-[calc(100%-5px)] aspect-square blur-0 hover:brightness-75">
|
||||
<motion.div variants={variants} whileHover="hover" whileTap="tap" initial={{rotate: 0}} className="absolute block p-1 right-3 h-[calc(100%-5px)] aspect-square blur-0 hover:brightness-75">
|
||||
<span className="absolute top-0 left-0 h-full w-full rounded-full opacity-20" style={{backgroundColor: mainColor}}/>
|
||||
<BsmButton className="p-1 absolute top-0 left-0 h-full w-full !bg-transparent -rotate-45" iconClassName="" icon={mapsLinked ? "link" : "unlink"} withBar={false} style={{color: mainColor}}/>
|
||||
<BsmButton className="p-1 absolute top-0 left-0 h-full w-full !bg-transparent -rotate-45" iconClassName="" icon={mapsLinked ? "link" : "unlink"} withBar={false} style={{color: mainColor}} onClick={e => {e.stopPropagation(); onClickLink(index)}}/>
|
||||
</motion.div>
|
||||
</li>
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ type Props = {
|
||||
tabsText: string[],
|
||||
onTabChange: (index: number) => void,
|
||||
className?: string,
|
||||
renderTab?: (props: DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, text: string) => JSX.Element
|
||||
renderTab?: (props: DetailedHTMLProps<React.HTMLAttributes<any>, any>, text: string, index?: number) => JSX.Element
|
||||
}
|
||||
|
||||
export function TabNavBar(props: Props) {
|
||||
@@ -30,7 +30,7 @@ export function TabNavBar(props: Props) {
|
||||
{props.tabsText.map((text, index) => (
|
||||
props.renderTab ? (
|
||||
<Fragment key={text}>
|
||||
{props.renderTab({onClick: () => selectTab(index)}, t(text))}
|
||||
{props.renderTab({onClick: () => selectTab(index)}, t(text), index)}
|
||||
</Fragment>
|
||||
) : (
|
||||
<li className="px-4 h-full text-center text-gray-800 dark:text-gray-200 text-lg font-bold hover:backdrop-brightness-75" key={text} onClick={() => selectTab(index)}>{t(text)}</li>
|
||||
|
||||
@@ -22,9 +22,18 @@ export class BeatSaverApiService {
|
||||
|
||||
const resp = await fetch(`${this.bsaverApiUrl}/maps/hash/${paramsHashs}`);
|
||||
|
||||
const data = await resp.json() as Record<Lowercase<T>, BsvMapDetail>;
|
||||
const data = await resp.json() as Record<Lowercase<T>, BsvMapDetail> | BsvMapDetail;
|
||||
|
||||
return {status: resp.status, data: data};
|
||||
if((data as BsvMapDetail).id){
|
||||
const key = (data as BsvMapDetail).versions.at(0).hash.toLowerCase();
|
||||
const parsedData = {
|
||||
[key]: data as BsvMapDetail
|
||||
} as Record<Lowercase<T>, BsvMapDetail>;
|
||||
|
||||
return {status: resp.status, data: parsedData}
|
||||
}
|
||||
|
||||
return {status: resp.status, data: (data as Record<Lowercase<T>, BsvMapDetail>)};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Observable } from "rxjs";
|
||||
import { Subject, 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";
|
||||
@@ -16,6 +16,9 @@ export class MapsManagerService {
|
||||
private readonly ipcService: IpcService;
|
||||
private readonly bsaver: BeatSaverService;
|
||||
|
||||
private readonly lastLinkedVersion$: Subject<BSVersion> = new Subject();
|
||||
private readonly lastUnlinkedVersion$: Subject<BSVersion> = new Subject();
|
||||
|
||||
private constructor(){
|
||||
this.ipcService = IpcService.getInstance();
|
||||
this.bsaver = BeatSaverService.getInstance();
|
||||
@@ -44,14 +47,30 @@ export class MapsManagerService {
|
||||
})
|
||||
}
|
||||
|
||||
public downloadMap(map: any, version?: BSVersion){
|
||||
|
||||
public linkVersion(version: BSVersion): Promise<void>{
|
||||
return this.ipcService.send<void, {version: BSVersion, keepMaps: boolean}>("link-version-maps", {args: {version, keepMaps: true}}).then(res => {
|
||||
if(res.success){
|
||||
return this.lastLinkedVersion$.next(version);
|
||||
}
|
||||
throw res.error;
|
||||
});
|
||||
}
|
||||
|
||||
public deleteMaps(maps: any[], version?: BSVersion){
|
||||
|
||||
public unlinkVersion(version: BSVersion): Promise<void>{
|
||||
return this.ipcService.send<void, {version: BSVersion, keepMaps: boolean}>("unlink-version-maps", {args: {version, keepMaps: true}}).then(res => {
|
||||
if(res.success){
|
||||
return this.lastUnlinkedVersion$.next(version);
|
||||
}
|
||||
throw res.error;
|
||||
});
|
||||
}
|
||||
|
||||
public get versionLinked$(): Observable<BSVersion>{
|
||||
return this.lastLinkedVersion$.asObservable();
|
||||
}
|
||||
|
||||
public get versionUnlinked$(): Observable<BSVersion>{
|
||||
return this.lastUnlinkedVersion$.asObservable();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user