A music player that connects to your cloud/distributed storage.
at main 8.3 kB view raw
1module Tracks.Collection.Internal.Arrange exposing (arrange) 2 3import Conditional exposing (ifThenElse) 4import Dict exposing (Dict) 5import List.Extra as List 6import Maybe.Extra as Maybe 7import Playlists exposing (..) 8import Playlists.Matching 9import String.Ext as String 10import Time 11import Time.Ext as Time 12import Tracks exposing (..) 13import Tracks.Sorting as Sorting 14 15 16 17-- 🍯 18 19 20arrange : Parcel -> Parcel 21arrange ( deps, collection ) = 22 case deps.selectedPlaylist of 23 Just playlist -> 24 if playlist.collection then 25 case playlist.autoGenerated of 26 Just _ -> 27 arrangeByGroup ( deps, collection ) 28 29 Nothing -> 30 arrangeByCollection ( deps, collection ) playlist 31 32 else 33 arrangeByPlaylist ( deps, collection ) playlist 34 35 Nothing -> 36 arrangeByGroup ( deps, collection ) 37 38 39 40-- GROUPING 41 42 43arrangeByGroup : Parcel -> Parcel 44arrangeByGroup ( deps, collection ) = 45 case deps.grouping of 46 Just AddedOn -> 47 ( deps, groupByInsertedAt deps collection ) 48 49 Just Directory -> 50 ( deps, groupByDirectory deps collection ) 51 52 Just FirstAlphaCharacter -> 53 ( deps, groupByFirstAlphaCharacter deps collection ) 54 55 Just TrackYear -> 56 ( deps, groupByYear deps collection ) 57 58 Nothing -> 59 collection.identified 60 |> Sorting.sort deps.sortBy deps.sortDirection 61 |> (\x -> { collection | arranged = x }) 62 |> (\x -> ( deps, x )) 63 64 65addToList : a -> Maybe (List a) -> Maybe (List a) 66addToList item maybeList = 67 case maybeList of 68 Just list -> 69 Just (item :: list) 70 71 Nothing -> 72 Just [ item ] 73 74 75groupBy : { reversed : Bool } -> (IdentifiedTrack -> Dict a (List IdentifiedTrack) -> Dict a (List IdentifiedTrack)) -> CollectionDependencies -> Collection -> Collection 76groupBy { reversed } folder deps collection = 77 collection.identified 78 |> List.foldl folder Dict.empty 79 |> Dict.values 80 |> ifThenElse reversed List.reverse identity 81 |> List.concatMap (Sorting.sort deps.sortBy deps.sortDirection) 82 |> (\arranged -> { collection | arranged = arranged }) 83 84 85 86-- GROUPING ░░ ADDED ON 87 88 89groupByInsertedAt : CollectionDependencies -> Collection -> Collection 90groupByInsertedAt = 91 groupBy { reversed = True } groupByInsertedAtFolder 92 93 94groupByInsertedAtFolder : IdentifiedTrack -> Dict Int (List IdentifiedTrack) -> Dict Int (List IdentifiedTrack) 95groupByInsertedAtFolder ( i, t ) = 96 let 97 ( year, month ) = 98 ( Time.toYear Time.utc t.insertedAt 99 , Time.toMonth Time.utc t.insertedAt 100 ) 101 102 group = 103 { name = insertedAtGroupName year month 104 , firstInGroup = False 105 } 106 107 item = 108 ( { i | group = Just group } 109 , t 110 ) 111 in 112 Dict.update 113 (year * 1000 + Time.monthNumber month) 114 (addToList item) 115 116 117insertedAtGroupName : Int -> Time.Month -> String 118insertedAtGroupName year month = 119 if year == 1970 then 120 "MANY MOONS AGO" 121 122 else 123 Time.monthName month ++ " " ++ String.fromInt year 124 125 126 127-- GROUPING ░░ DIRECTORY 128 129 130groupByDirectory : CollectionDependencies -> Collection -> Collection 131groupByDirectory deps = 132 groupBy { reversed = False } (groupByDirectoryFolder deps) deps 133 134 135groupByDirectoryFolder : CollectionDependencies -> IdentifiedTrack -> Dict String (List IdentifiedTrack) -> Dict String (List IdentifiedTrack) 136groupByDirectoryFolder deps ( i, t ) = 137 let 138 directory = 139 t.path 140 |> String.chopStart "/" 141 |> String.split "/" 142 |> (case Maybe.andThen .autoGenerated deps.selectedPlaylist of 143 Just { level } -> 144 List.drop (max 0 (level - 1) + 1) 145 146 Nothing -> 147 identity 148 ) 149 |> List.init 150 |> Maybe.map (String.join " / ") 151 |> Maybe.withDefault t.path 152 153 group = 154 { name = directory 155 , firstInGroup = False 156 } 157 158 item = 159 ( { i | group = Just group } 160 , t 161 ) 162 in 163 Dict.update 164 directory 165 (addToList item) 166 167 168 169-- GROUPING ░░ FIRST LETTER 170 171 172groupByFirstAlphaCharacter : CollectionDependencies -> Collection -> Collection 173groupByFirstAlphaCharacter deps = 174 groupBy { reversed = False } (groupByFirstAlphaCharacterFolder deps) deps 175 176 177groupByFirstAlphaCharacterFolder : CollectionDependencies -> IdentifiedTrack -> Dict String (List IdentifiedTrack) -> Dict String (List IdentifiedTrack) 178groupByFirstAlphaCharacterFolder deps ( i, t ) = 179 let 180 tag = 181 case deps.sortBy of 182 Artist -> 183 Maybe.withDefault fallbackArtist t.tags.artist 184 185 Album -> 186 Maybe.withDefault fallbackAlbum t.tags.album 187 188 PlaylistIndex -> 189 "" 190 191 Title -> 192 t.tags.title 193 194 group = 195 { name = 196 tag 197 |> String.toList 198 |> List.head 199 |> Maybe.andThen 200 (\char -> 201 if Char.isAlpha char then 202 Just (String.fromList [ Char.toUpper char ]) 203 204 else 205 Nothing 206 ) 207 |> Maybe.withDefault "#" 208 , firstInGroup = False 209 } 210 211 item = 212 ( { i | group = Just group } 213 , t 214 ) 215 in 216 Dict.update 217 group.name 218 (addToList item) 219 220 221 222-- GROUPING ░░ YEAR 223 224 225groupByYear : CollectionDependencies -> Collection -> Collection 226groupByYear = 227 groupBy { reversed = True } groupByYearFolder 228 229 230groupByYearFolder : IdentifiedTrack -> Dict Int (List IdentifiedTrack) -> Dict Int (List IdentifiedTrack) 231groupByYearFolder ( i, t ) = 232 let 233 group = 234 { name = Maybe.unwrap "0000 - Unknown" String.fromInt t.tags.year 235 , firstInGroup = False 236 } 237 238 item = 239 ( { i | group = Just group } 240 , t 241 ) 242 in 243 Dict.update 244 (Maybe.withDefault 0 t.tags.year) 245 (addToList item) 246 247 248 249-- PLAYLISTS 250 251 252arrangeByCollection : Parcel -> Playlist -> Parcel 253arrangeByCollection ( deps, collection ) playlist = 254 collection.identified 255 |> Playlists.Matching.match playlist 256 |> dealWithMissingPlaylistTracks 257 |> Sorting.sort deps.sortBy deps.sortDirection 258 |> (\x -> { collection | arranged = x }) 259 |> (\x -> ( deps, x )) 260 261 262arrangeByPlaylist : Parcel -> Playlist -> Parcel 263arrangeByPlaylist ( deps, collection ) playlist = 264 collection.identified 265 |> Playlists.Matching.match playlist 266 |> dealWithMissingPlaylistTracks 267 |> Sorting.sort PlaylistIndex Asc 268 |> (\x -> { collection | arranged = x }) 269 |> (\x -> ( deps, x )) 270 271 272dealWithMissingPlaylistTracks : ( List IdentifiedTrack, List IdentifiedPlaylistTrack ) -> List IdentifiedTrack 273dealWithMissingPlaylistTracks ( identifiedTracks, remainingPlaylistTracks ) = 274 identifiedTracks ++ List.map makeMissingPlaylistTrack remainingPlaylistTracks 275 276 277makeMissingPlaylistTrack : IdentifiedPlaylistTrack -> IdentifiedTrack 278makeMissingPlaylistTrack ( identifiers, playlistTrack ) = 279 let 280 tags = 281 { disc = 1 282 , nr = 0 283 , artist = playlistTrack.artist 284 , title = playlistTrack.title 285 , album = playlistTrack.album 286 , genre = Nothing 287 , picture = Nothing 288 , year = Nothing 289 } 290 in 291 Tuple.pair 292 { filename = "" 293 , group = Nothing 294 , indexInList = 0 295 , indexInPlaylist = Just identifiers.index 296 , isFavourite = False 297 , isMissing = True 298 , parentDirectory = "" 299 } 300 { tags = tags 301 , id = missingId 302 , insertedAt = Time.default 303 , path = missingId 304 , sourceId = missingId 305 }