1- import { capitalize , deburr , uniqBy } from ' lodash' ;
2- import type { MouseEvent } from ' react' ;
1+ import { capitalize , deburr , uniqBy } from " lodash" ;
2+ import type { MouseEvent } from " react" ;
33import type {
44 ReleaseType ,
55 Release ,
@@ -14,33 +14,51 @@ import type {
1414 ArtistWithReleases ,
1515 GroupWithArtists ,
1616 WithAdditionalArtists ,
17-
1817} from "@/types/types" ;
19- import { getCover } from './links' ;
20-
21- const releaseTypes : ReleaseType [ ] =
22- [ 'Album' , 'Compilation' , 'EP' , 'Single' , 'Bootleg' , 'Various' , 'Tribute' , 'Soundtrack' ] ;
23-
24- export const VARIOUS_ARTISTS_FOLDER = '[V:A]' ;
25- export const VARIOUS_ARTISTS_NAME = '_VV_AA_' ;
26-
27- export function getReleaseTitle ( { title, subReleases = [ ] } :
28- Pick < ReleaseWithArtistAndSubreleases , 'title' | 'subReleases' > ) : string {
18+ import { getCover } from "./links" ;
19+
20+ const releaseTypes : ReleaseType [ ] = [
21+ "Album" ,
22+ "Compilation" ,
23+ "EP" ,
24+ "Single" ,
25+ "Bootleg" ,
26+ "Various" ,
27+ "Tribute" ,
28+ "Soundtrack" ,
29+ ] ;
30+
31+ export const VARIOUS_ARTISTS_FOLDER = "[V:A]" ;
32+ export const VARIOUS_ARTISTS_NAME = "_VV_AA_" ;
33+
34+ export function getReleaseTitle ( {
35+ title,
36+ subReleases = [ ] ,
37+ } : Pick < ReleaseWithArtistAndSubreleases , "title" | "subReleases" > ) : string {
2938 if ( ! subReleases . length ) {
3039 return title ;
3140 }
3241 const match = title . match ( / ( .* ) C D ( \d + ) / ) ;
3342 return match ? match [ 1 ] : title ;
3443}
3544
36- export function getReleaseArtist (
37- { artist, additionalArtists } : Pick < ReleaseWithArtist & WithAdditionalArtists , 'artist' | 'additionalArtists' >
38- ) {
39- return [ artist , ...additionalArtists ] . map ( x => normalizeArtistName ( x . name ) ) . join ( ', ' ) ;
45+ export function getReleaseArtist ( {
46+ artist,
47+ additionalArtists,
48+ } : Pick <
49+ ReleaseWithArtist & WithAdditionalArtists ,
50+ "artist" | "additionalArtists"
51+ > ) {
52+ return [ artist , ...additionalArtists ]
53+ . map ( ( x ) => normalizeArtistName ( x . name ) )
54+ . join ( ", " ) ;
4055}
4156
4257export function getUniqueArtists ( releases : ReleaseWithArtist [ ] ) : Artist [ ] {
43- return uniqBy ( releases . map ( x => x . artist ) , ( x => x . id ) ) ;
58+ return uniqBy (
59+ releases . map ( ( x ) => x . artist ) ,
60+ ( x ) => x . id
61+ ) ;
4462}
4563
4664export function getMainReleaseTitle ( release : ReleaseWithArtist ) {
@@ -52,12 +70,15 @@ export function getMainReleaseTitle(release: ReleaseWithArtist) {
5270}
5371
5472export function countReleasesByType ( releases : Release [ ] ) : ReleaseCountByType {
55- return releases . reduce ( ( memo , { type } ) => ( { ...memo , [ type ] : memo [ type ] ? memo [ type ] + 1 : 1 } ) , { } as ReleaseCountByType ) ;
73+ return releases . reduce (
74+ ( memo , { type } ) => ( { ...memo , [ type ] : memo [ type ] ? memo [ type ] + 1 : 1 } ) ,
75+ { } as ReleaseCountByType
76+ ) ;
5677}
5778
5879export function estimateListCardSize ( ) {
5980 return {
60- width : ' 100%' ,
81+ width : " 100%" ,
6182 height : 6 * 16 ,
6283 } ;
6384}
@@ -66,7 +87,7 @@ export function normalizeTitle(title: string) {
6687 return title
6788 . replace ( / C D ( \d + ) / , "" )
6889 . replaceAll ( / \( \w : ( .* ) \) / g, "" )
69- . replaceAll ( ' : ' , ' / ' )
90+ . replaceAll ( " : " , " / " )
7091 . trim ( ) ;
7192}
7293
@@ -78,25 +99,29 @@ export function normalizeArtistName(name: string) {
7899}
79100
80101export function normalizeArtistDisplayName ( name : string ) {
81- return name === VARIOUS_ARTISTS_NAME ? ' Various Artists' : name ;
102+ return name === VARIOUS_ARTISTS_NAME ? " Various Artists" : name ;
82103}
83104
84105export function getDiscInfo ( { subReleases } : ReleaseWithArtistAndSubreleases ) {
85- return subReleases . length
86- ? `(${ subReleases . length + 1 } discs)`
87- : null ;
106+ return subReleases . length ? `(${ subReleases . length + 1 } discs)` : null ;
88107}
89108
90- export function getReleaseDuration ( release : ReleaseWithArtistAndTracksAndSubreleases ) {
109+ export function getReleaseDuration (
110+ release : ReleaseWithArtistAndTracksAndSubreleases
111+ ) {
91112 const allTracks = [
92113 ...release . tracks ,
93- ...( release . subReleases . length ? release . subReleases . flatMap ( x => x . tracks ) : [ ] )
114+ ...( release . subReleases . length
115+ ? release . subReleases . flatMap ( ( x ) => x . tracks )
116+ : [ ] ) ,
94117 ] ;
95118
96119 return {
97120 trackCount : allTracks . length ,
98- duration : formatDuration ( allTracks . reduce ( ( memo , { duration } ) => memo += duration , 0 ) )
99- }
121+ duration : formatDuration (
122+ allTracks . reduce ( ( memo , { duration } ) => ( memo += duration ) , 0 )
123+ ) ,
124+ } ;
100125}
101126
102127export function formatDuration ( duration : number ) {
@@ -112,37 +137,52 @@ export function formatDuration(duration: number) {
112137 return formatted ;
113138}
114139
115-
116140export function isEmpty ( obj : object ) {
117141 return Object . keys ( obj ) . length === 0 ;
118142}
119143
120- export function sortReleasesByTypeAndYear ( releases : ReleaseWithArtist [ ] ) {
121- return releaseTypes
122- . flatMap ( type => releases
123- . filter ( x => x . type === type )
144+ type Sortable = number | string | boolean | Date ;
145+
146+ export function sortBy ( key : string , order : "asc" | "desc" = "asc" ) {
147+ return ( a : Record < string , Sortable > , b : Record < string , Sortable > ) =>
148+ ( a [ key ] > b [ key ] ? 1 : - 1 ) * ( order === "asc" ? 1 : - 1 ) ;
149+ }
150+
151+ export function sortReleasesByTypeAndYear (
152+ releases : Pick < Release , "type" | "year" | "title" > [ ]
153+ ) {
154+ return releaseTypes . flatMap ( ( type ) =>
155+ releases
156+ . filter ( ( x ) => x . type === type )
124157 . sort ( ( a , b ) => {
125158 if ( ! a . year || ! b . year ) {
126159 return 0 ;
127160 }
128161 if ( a . year === b . year ) {
129162 return a . title . toLowerCase ( ) > b . title . toLowerCase ( ) ? 1 : - 1 ;
130163 }
131- return Math . sign ( a . year - b . year )
164+ return Math . sign ( a . year - b . year ) ;
132165 } )
133- )
166+ ) ;
134167}
135168
136- export function getReleaseWithTracklistHeight ( release : ReleaseWithArtistAndTracksAndSubreleases ) : number {
137- const maxTracks = Math . max ( ...[
138- release ,
139- ...release . subReleases
140- ] . map ( x => x . tracks ?. length ) ) ;
169+ export function getReleaseWithTracklistHeight (
170+ release : ReleaseWithArtistAndTracksAndSubreleases
171+ ) : number {
172+ const maxTracks = Math . max (
173+ ...[ release , ...release . subReleases ] . map ( ( x ) => x . tracks ?. length )
174+ ) ;
141175 // cover height + margin + gap + tracks
142- return 128 + 16 + 4 + ( release . subReleases . length ? 32 : 0 ) + ( maxTracks * ( 40 + 4 ) ) ;
176+ return (
177+ 128 + 16 + 4 + ( release . subReleases . length ? 32 : 0 ) + maxTracks * ( 40 + 4 )
178+ ) ;
143179}
144180
145- export async function mapSeries < T , U > ( array : T [ ] , callback : ( item : T , index : number ) => Promise < U > , interval = 0 ) : Promise < U [ ] > {
181+ export async function mapSeries < T , U > (
182+ array : T [ ] ,
183+ callback : ( item : T , index : number ) => Promise < U > ,
184+ interval = 0
185+ ) : Promise < U [ ] > {
146186 if ( ! array . length ) {
147187 return [ ] ;
148188 }
@@ -162,16 +202,19 @@ export async function mapSeries<T, U>(array: T[], callback: (item: T, index: num
162202 } ) ;
163203}
164204
165- export function sortByQueryPosition < K extends string , T extends {
166- [ Property in K ] : string ;
167- } > ( query : string , key : keyof T , a : T , b : T ) {
205+ export function sortByQueryPosition <
206+ K extends string ,
207+ T extends {
208+ [ Property in K ] : string ;
209+ } ,
210+ > ( query : string , key : keyof T , a : T , b : T ) {
168211 const posA = a [ key ] . toLowerCase ( ) . indexOf ( query . toLowerCase ( ) ) ;
169212 const posB = b [ key ] . toLowerCase ( ) . indexOf ( query . toLowerCase ( ) ) ;
170213 return Math . sign ( posA - posB ) ;
171214}
172215
173216export function wait ( ms = 100 ) {
174- return new Promise ( resolve => setTimeout ( resolve , ms ) ) ;
217+ return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
175218}
176219
177220export function getReleaseContextMenuParams ( {
@@ -202,7 +245,7 @@ export function refreshCovers(releases: Release[]) {
202245 const seed = `${ Math . random ( ) * 100000 } ` . slice ( 0 , 5 ) ;
203246 element . src = `${ getCover ( hash ) } ?_=${ seed } ` ;
204247 } ) ;
205- } )
248+ } ) ;
206249}
207250
208251export function withStopPropagation ( handler : ( event : MouseEvent ) => void ) {
@@ -212,13 +255,19 @@ export function withStopPropagation(handler: (event: MouseEvent) => void) {
212255 } ;
213256}
214257
215- type Item = CollectionWithReleases | ArtistWithReleases | ReleaseWithArtistAndSubreleases | GroupWithArtists ;
258+ type Item =
259+ | CollectionWithReleases
260+ | ArtistWithReleases
261+ | ReleaseWithArtistAndSubreleases
262+ | GroupWithArtists ;
216263
217- export function getCoverRelease ( item : Item ) : ReleaseWithArtistAndSubreleases | null {
264+ export function getCoverRelease (
265+ item : Item
266+ ) : ReleaseWithArtistAndSubreleases | null {
218267 if ( item . _type === "release" ) {
219268 return item ;
220269 }
221- if ( item . _type === ' group' ) {
270+ if ( item . _type === " group" ) {
222271 const coverArtist = item . coverArtist || item . artists [ 0 ] ;
223272 return coverArtist ? getCoverRelease ( coverArtist ) : null ;
224273 }
@@ -231,24 +280,41 @@ type NewReleaseInfo = {
231280 newTitle : string ;
232281 newType : ReleaseType ;
233282 newYear : number ;
234- }
235-
236- type EditReleaseParam = (
237- Pick < Release , 'id' | 'path' | 'hash' | 'title' | 'artist_id' | 'year' | 'type' | 'discTitle' | 'discNumber' >
238- & NewReleaseInfo
239- ) ;
283+ } ;
240284
241- export function didReleaseInfoChange ( infos : EditReleaseParam [ ] , excludeDiscTitle ?: boolean ) {
242- return infos . some (
243- ( x : EditReleaseParam ) => [ 'path' , 'title' , 'type' , 'year' , 'discTitle' ] . slice ( 0 , excludeDiscTitle ? - 1 : undefined )
244- . some ( key => x [ key as keyof EditReleaseParam ] !== x [ `new${ capitalize ( key ) } ` as keyof NewReleaseInfo ] )
285+ type EditReleaseParam = Pick <
286+ Release ,
287+ | "id"
288+ | "path"
289+ | "hash"
290+ | "title"
291+ | "artist_id"
292+ | "year"
293+ | "type"
294+ | "discTitle"
295+ | "discNumber"
296+ > &
297+ NewReleaseInfo ;
298+
299+ export function didReleaseInfoChange (
300+ infos : EditReleaseParam [ ] ,
301+ excludeDiscTitle ?: boolean
302+ ) {
303+ return infos . some ( ( x : EditReleaseParam ) =>
304+ [ "path" , "title" , "type" , "year" , "discTitle" ]
305+ . slice ( 0 , excludeDiscTitle ? - 1 : undefined )
306+ . some (
307+ ( key ) =>
308+ x [ key as keyof EditReleaseParam ] !==
309+ x [ `new${ capitalize ( key ) } ` as keyof NewReleaseInfo ]
310+ )
245311 ) ;
246312}
247313
248314export function withCoverRelease ( artist : ArtistWithReleases ) {
249315 return {
250316 ...artist ,
251- coverRelease : artist . coverRelease || artist . releases [ 0 ]
317+ coverRelease : artist . coverRelease || artist . releases [ 0 ] ,
252318 } ;
253319}
254320
@@ -261,7 +327,7 @@ export function normalizeDiacritics(input: string) {
261327 input
262328 . normalize ( "NFD" )
263329 . replace ( / [ \u0300 - \u036f ] / g, "" )
264- . replace ( / \( ( \d + ) \) $ / , '' )
330+ . replace ( / \( ( \d + ) \) $ / , "" )
265331 . trim ( )
266332 ) ;
267- }
333+ }
0 commit comments