[feat-930] added added date sorting for maps/songs (#931)

* [feat-930] added added date sorting for maps/songs

* [feat-930] add translations

* [feat-930] fixed date format issue

---------

Co-authored-by: Zagrios <40181755+Zagrios@users.noreply.github.com>
This commit is contained in:
silentrald
2025-11-02 22:45:49 +08:00
committed by GitHub
parent c9c24479d3
commit 2073d8ffa4
16 changed files with 68 additions and 19 deletions
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "Dauer",
"likes": "Likes",
"date-uploaded": "Hochladedatum"
"date-uploaded": "Hochladedatum",
"added-date": "Hinzugefügt am"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "Duration",
"likes": "Likes",
"date-uploaded": "Date Uploaded"
"date-uploaded": "Date Uploaded",
"added-date": "Added Date"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "Duración",
"likes": "Me gusta",
"date-uploaded": "Fecha de subida"
"date-uploaded": "Fecha de subida",
"added-date": "Fecha de adición"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "Durée",
"likes": "J'aime",
"date-uploaded": "Date de publication"
"date-uploaded": "Date de publication",
"added-date": "Date d'ajout"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "Durata",
"likes": "Mi piace",
"date-uploaded": "Data di caricamento"
"date-uploaded": "Data di caricamento",
"added-date": "Data di aggiunta"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "持続時間",
"likes": "いいね",
"date-uploaded": "アップロード日"
"date-uploaded": "アップロード日",
"added-date": "追加日"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "지속 시간",
"likes": "좋아요",
"date-uploaded": "업로드 날짜"
"date-uploaded": "업로드 날짜",
"added-date": "추가 날짜"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "Duração",
"likes": "Gostei",
"date-uploaded": "Data de envio"
"date-uploaded": "Data de envio",
"added-date": "Data de adição"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "Длительность",
"likes": "Лайки",
"date-uploaded": "Дата загрузки"
"date-uploaded": "Дата загрузки",
"added-date": "Дата добавления"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "Haba",
"likes": "Likes",
"date-uploaded": "Petsa ng Pagka-upload"
"date-uploaded": "Petsa ng Pagka-upload",
"added-date": "Petsa ng Pagdaragdag"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "Довжина",
"likes": "Лайки",
"date-uploaded": "Дата завантаження"
"date-uploaded": "Дата завантаження",
"added-date": "Дата додавання"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "持續時間",
"likes": "喜歡",
"date-uploaded": "上傳日期"
"date-uploaded": "上傳日期",
"added-date": "新增日期"
}
},
"playlists": {
+2 -1
View File
@@ -111,7 +111,8 @@
"bpm": "BPM",
"duration": "持续时间",
"likes": "喜欢",
"date-uploaded": "上传日期"
"date-uploaded": "上传日期",
"added-date": "添加日期"
}
},
"playlists": {
@@ -1,13 +1,13 @@
import path from "path";
import { BSVersion } from "shared/bs-version.interface";
import { BsvMapDetail } from "shared/models/maps";
import { BsmLocalMap, BsmLocalMapsProgress, DeleteMapsProgress } from "shared/models/maps/bsm-local-map.interface";
import { BsmLocalMap, BsmLocalMapMetadata, BsmLocalMapsProgress, DeleteMapsProgress } from "shared/models/maps/bsm-local-map.interface";
import { BSLocalVersionService } from "../../bs-local-version.service";
import { InstallationLocationService } from "../../installation-location.service";
import { UtilsService } from "../../utils.service";
import crypto, { BinaryLike } from "crypto";
import { lstatSync } from "fs";
import { copy, createReadStream, ensureDir, pathExists, pathExistsSync, realpath } from "fs-extra";
import { copy, createReadStream, ensureDir, existsSync, pathExists, pathExistsSync, readJson, realpath, writeJson } from "fs-extra";
import { RequestService } from "../../request.service";
import sanitize from "sanitize-filename";
import { DeepLinkService } from "../../deep-link.service";
@@ -31,6 +31,7 @@ import { CustomError } from "shared/models/exceptions/custom-error.class";
import { tryit } from "shared/helpers/error.helpers";
import { BsmZipExtractor } from "main/models/bsm-zip-extractor.class";
import { escapeRegExp } from "../../../../shared/helpers/string.helpers";
import dateFormat from "dateformat";
export class LocalMapsManagerService {
private static instance: LocalMapsManagerService;
@@ -46,6 +47,7 @@ export class LocalMapsManagerService {
public static readonly CUSTOM_LEVELS_FOLDER = "CustomLevels";
public static readonly RELATIVE_MAPS_FOLDER = path.join(LocalMapsManagerService.LEVELS_ROOT_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER);
public static readonly SHARED_MAPS_FOLDER = "SharedMaps";
public static readonly METADATA_FILE = "metadata.json";
private readonly DEEP_LINKS = {
BeatSaver: "beatsaver",
@@ -138,16 +140,21 @@ export class LocalMapsManagerService {
public async loadMapInfoFromPath(mapPath: string): Promise<BsmLocalMap> {
const getUrlsAndReturn = (mapInfo: MapInfo, hash: string, mapPath: string): BsmLocalMap => {
const getUrlsAndReturn = (mapInfo: MapInfo, hash: string, mapPath: string, metadata: BsmLocalMapMetadata): BsmLocalMap => {
const coverUrl = pathToFileURL(path.join(mapPath, mapInfo.coverImageFilename)).href;
const songUrl = pathToFileURL(path.join(mapPath, mapInfo.songFilename)).href;
return { mapInfo, coverUrl, songUrl, hash, path: mapPath, songDetails: this.songDetailsCache.getSongDetails(hash) };
return {
mapInfo, coverUrl, songUrl, hash, path: mapPath,
songDetails: this.songDetailsCache.getSongDetails(hash),
metadata,
};
};
const cachedMapInfos = this.songCache.getMapInfoFromDirname(path.basename(mapPath));
if (cachedMapInfos) {
return getUrlsAndReturn(cachedMapInfos.mapInfo, cachedMapInfos.hash, mapPath);
const metadata = await this.getMetadata(mapPath);
return getUrlsAndReturn(cachedMapInfos.mapInfo, cachedMapInfos.hash, mapPath, metadata);
}
const files = await getFilesInFolder(mapPath);
@@ -166,8 +173,9 @@ export class LocalMapsManagerService {
}
const hash = await this.computeMapHash(mapPath, rawInfoString);
const metadata = await this.getMetadata(mapPath);
return getUrlsAndReturn(mapInfo, hash, mapPath);
return getUrlsAndReturn(mapInfo, hash, mapPath, metadata);
}
private async downloadMapZip(zipUrl: string): Promise<string> {
@@ -462,6 +470,21 @@ export class LocalMapsManagerService {
return localMap;
}
private async getMetadata(mapPath: string): Promise<BsmLocalMapMetadata> {
const metadataPath = path.join(mapPath, LocalMapsManagerService.METADATA_FILE);
if (existsSync(metadataPath)) {
return await readJson(metadataPath) as BsmLocalMapMetadata;
}
// Create the metadata then return it to the user
const metadata: BsmLocalMapMetadata = {
addedDate: dateFormat(new Date(), "yyyy-mm-dd'T'HH:MM:ss.l"),
};
await writeJson(metadataPath, metadata);
return metadata;
}
public async exportMaps(version: BSVersion, maps: BsmLocalMap[], outPath: string): Promise<Observable<Progression>> {
const archive = new Archive(outPath);
@@ -8,6 +8,12 @@ export interface BsmLocalMap {
mapInfo: MapInfo;
songDetails?: SongDetails;
path: string;
metadata?: BsmLocalMapMetadata;
}
export interface BsmLocalMapMetadata {
// Date of download or import
addedDate: string;
}
export interface BsmLocalMapsProgress {
+7
View File
@@ -35,6 +35,13 @@ export const mapSorter = new Sorter<BsmLocalMap>({
return !map2.songDetails ? Comparison.GREATER : map1.songDetails.uploadedAt - map2.songDetails.uploadedAt;
},
"added-date": (map1, map2) => {
if (!map1.metadata) {
return map2.metadata ? Comparison.LESSER : Comparison.EQUAL;
}
return !map2.metadata ? Comparison.GREATER : map1.metadata.addedDate.localeCompare(map2.metadata.addedDate);
}
},
tiebreak: sortName,
defaultKey: "name"