A music player that connects to your cloud/distributed storage.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 539 lines 17 kB view raw
1module UI.Playlists.State exposing (..) 2 3import Conditional exposing (ifThenElse) 4import Coordinates 5import Html.Events.Extra.Mouse as Mouse 6import List.Ext as List 7import List.Extra as List 8import Maybe.Extra as Maybe 9import Notifications 10import Playlists exposing (..) 11import Return exposing (andThen) 12import Tracks exposing (IdentifiedTrack) 13import Tracks.Collection 14import UI.Alfred.State as Alfred 15import UI.Common.State as Common 16import UI.Page as Page 17import UI.Playlists.Alfred 18import UI.Playlists.ContextMenu as Playlists 19import UI.Playlists.Page exposing (..) 20import UI.Tracks.State as Tracks 21import UI.Types exposing (..) 22import UI.User.State.Export as User 23 24 25 26-- 🔱 27 28 29activate : Playlist -> Manager 30activate playlist model = 31 model 32 |> select playlist 33 |> andThen (Common.changeUrlUsingPage Page.Index) 34 35 36addTracksToPlaylist : { collection : Bool, playlistName : String, tracks : List PlaylistTrackWithoutMetadata } -> Manager 37addTracksToPlaylist { collection, playlistName, tracks } model = 38 let 39 properPlaylistName = 40 String.trim playlistName 41 42 playlistIndex = 43 List.findIndex 44 (\p -> Maybe.isNothing p.autoGenerated && p.name == properPlaylistName) 45 model.playlists 46 47 ( tracksAlreadyInPlaylist, newTracks ) = 48 playlistIndex 49 |> Maybe.andThen 50 (\a -> 51 if collection then 52 Just a 53 54 else 55 Nothing 56 ) 57 |> Maybe.andThen (\idx -> List.getAt idx model.playlists) 58 |> Maybe.map 59 (\p -> 60 List.foldl 61 (\track ( a, b, c ) -> 62 case 63 List.findIndex 64 (\x -> 65 track.title == x.title && track.album == x.album && track.artist == x.artist 66 ) 67 c 68 of 69 Just idx -> 70 ( track :: a, b, List.removeAt idx c ) 71 72 Nothing -> 73 ( a, track :: b, c ) 74 ) 75 ( [], [], p.tracks ) 76 tracks 77 ) 78 |> Maybe.map (\( a, b, _ ) -> ( a, b )) 79 |> Maybe.withDefault ( [], tracks ) 80 |> Tuple.mapSecond 81 (List.map 82 (\track -> 83 let 84 newTrack : PlaylistTrack 85 newTrack = 86 { album = track.album 87 , artist = track.artist 88 , title = track.title 89 90 -- 91 , insertedAt = model.currentTime 92 } 93 in 94 newTrack 95 ) 96 ) 97 98 newInventory = 99 case playlistIndex of 100 Just idx -> 101 List.updateAt 102 idx 103 (\p -> { p | tracks = p.tracks ++ newTracks }) 104 model.playlists 105 106 Nothing -> 107 { autoGenerated = Nothing 108 , collection = collection 109 , name = properPlaylistName 110 , public = False 111 , tracks = newTracks 112 } 113 :: model.playlists 114 115 newModel = 116 { model 117 | playlists = newInventory 118 , lastModifiedPlaylist = 119 Just 120 { collection = collection 121 , name = properPlaylistName 122 } 123 } 124 125 subject = 126 ifThenElse collection "collection" "playlist" 127 in 128 case newTracks of 129 [] -> 130 if collection then 131 (case tracksAlreadyInPlaylist of 132 [ t ] -> 133 "__" ++ t.title ++ "__ was" 134 135 l -> 136 "__" ++ String.fromInt (List.length l) ++ " tracks__ were" 137 ) 138 |> (\s -> s ++ " already added to the __" ++ properPlaylistName ++ "__ collection") 139 |> Notifications.casual 140 |> Common.showNotificationWithModel model 141 142 else 143 Return.singleton model 144 145 _ -> 146 (case newTracks of 147 [ t ] -> 148 "Added __" ++ t.title ++ "__" 149 150 l -> 151 "Added __" ++ String.fromInt (List.length l) ++ " tracks__" 152 ) 153 |> (\s -> s ++ " to the __" ++ properPlaylistName ++ "__ " ++ subject) 154 |> Notifications.success 155 |> Common.showNotificationWithModel newModel 156 |> andThen User.savePlaylists 157 158 159assistWithAddingTracksToCollection : List IdentifiedTrack -> Manager 160assistWithAddingTracksToCollection tracks model = 161 model.playlists 162 |> List.filter (\p -> p.autoGenerated == Nothing && p.collection == True) 163 |> UI.Playlists.Alfred.create { collectionMode = True } tracks 164 |> (\a -> Alfred.assign a model) 165 166 167assistWithAddingTracksToPlaylist : List IdentifiedTrack -> Manager 168assistWithAddingTracksToPlaylist tracks model = 169 model.playlists 170 |> List.filter (\p -> p.autoGenerated == Nothing && p.collection == False) 171 |> UI.Playlists.Alfred.create { collectionMode = False } tracks 172 |> (\a -> Alfred.assign a model) 173 174 175assistWithSelectingPlaylist : Manager 176assistWithSelectingPlaylist model = 177 model.playlists 178 |> UI.Playlists.Alfred.select 179 |> (\a -> Alfred.assign a model) 180 181 182convertCollectionToPlaylist : { name : String } -> Manager 183convertCollectionToPlaylist { name } model = 184 case 185 List.findIndex 186 (\p -> Maybe.isNothing p.autoGenerated && p.name == name) 187 model.playlists 188 of 189 Just playlistIndex -> 190 model.playlists 191 |> List.updateAt 192 playlistIndex 193 (\p -> { p | collection = False }) 194 |> (\newInventory -> 195 { model 196 | playlists = newInventory 197 , selectedPlaylist = 198 Maybe.map 199 (\p -> 200 if p.name == name then 201 { p | collection = False } 202 203 else 204 p 205 ) 206 model.selectedPlaylist 207 } 208 ) 209 |> Return.singleton 210 |> andThen User.savePlaylists 211 212 Nothing -> 213 Return.singleton model 214 215 216convertPlaylistToCollection : { name : String } -> Manager 217convertPlaylistToCollection { name } model = 218 case 219 List.findIndex 220 (\p -> Maybe.isNothing p.autoGenerated && p.name == name) 221 model.playlists 222 of 223 Just playlistIndex -> 224 model.playlists 225 |> List.updateAt 226 playlistIndex 227 (\p -> { p | collection = True }) 228 |> (\newInventory -> 229 { model 230 | playlists = newInventory 231 , selectedPlaylist = 232 Maybe.map 233 (\p -> 234 if p.name == name then 235 { p | collection = True } 236 237 else 238 p 239 ) 240 model.selectedPlaylist 241 } 242 ) 243 |> Return.singleton 244 |> andThen User.savePlaylists 245 246 Nothing -> 247 Return.singleton model 248 249 250create : { collection : Bool } -> Manager 251create { collection } model = 252 case model.newPlaylistContext of 253 Just playlistName -> 254 let 255 alreadyExists = 256 List.find 257 (.name >> (==) playlistName) 258 (List.filterNot (.autoGenerated >> Maybe.isJust) model.playlists) 259 260 playlist = 261 { autoGenerated = Nothing 262 , collection = collection 263 , name = playlistName 264 , public = False 265 , tracks = [] 266 } 267 in 268 case alreadyExists of 269 Just existingPlaylist -> 270 (if existingPlaylist.collection then 271 "There's already a collection using this name" 272 273 else 274 "There's already a playlist using this name" 275 ) 276 |> Notifications.error 277 |> Common.showNotificationWithModel model 278 279 Nothing -> 280 { model 281 | lastModifiedPlaylist = 282 Just 283 { collection = playlist.collection 284 , name = playlist.name 285 } 286 , newPlaylistContext = Nothing 287 , playlists = playlist :: model.playlists 288 } 289 |> User.savePlaylists 290 |> andThen redirectToPlaylistIndexPage 291 292 Nothing -> 293 Return.singleton model 294 295 296createCollection : Manager 297createCollection = 298 create { collection = True } 299 300 301createPlaylist : Manager 302createPlaylist = 303 create { collection = False } 304 305 306deactivate : Manager 307deactivate = 308 deselect 309 310 311deselect : Manager 312deselect model = 313 { model | selectedPlaylist = Nothing } 314 |> Tracks.reviseCollection Tracks.Collection.arrange 315 |> andThen User.saveEnclosedUserData 316 317 318delete : { playlistName : String } -> Manager 319delete { playlistName } model = 320 let 321 selectedPlaylist = 322 Maybe.map 323 (\p -> ( p.autoGenerated, p.name )) 324 model.selectedPlaylist 325 326 ( selectedPlaylistChanged, newSelectedPlaylist ) = 327 if selectedPlaylist == Just ( Nothing, playlistName ) then 328 ( True, Nothing ) 329 330 else 331 ( False, model.selectedPlaylist ) 332 in 333 model.playlists 334 |> List.filter 335 (\p -> 336 if Maybe.isJust p.autoGenerated then 337 True 338 339 else 340 p.name /= playlistName 341 ) 342 |> (\col -> 343 { model 344 | playlists = col 345 , selectedPlaylist = newSelectedPlaylist 346 } 347 ) 348 |> (if selectedPlaylistChanged then 349 Tracks.reviseCollection Tracks.Collection.arrange 350 351 else 352 Return.singleton 353 ) 354 |> andThen User.savePlaylists 355 356 357modify : Manager 358modify model = 359 case model.editPlaylistContext of 360 Just { oldName, newName } -> 361 let 362 properName = 363 String.trim newName 364 365 validName = 366 String.isEmpty properName == False 367 368 ( autoGenerated, notAutoGenerated ) = 369 List.partition (.autoGenerated >> Maybe.isJust) model.playlists 370 371 alreadyExists = 372 List.find 373 (.name >> (==) properName) 374 notAutoGenerated 375 376 newCollection = 377 List.map 378 (\p -> ifThenElse (p.name == oldName) { p | name = properName } p) 379 notAutoGenerated 380 in 381 case alreadyExists of 382 Just existingPlaylist -> 383 (if existingPlaylist.collection then 384 "There's already a collection using this name" 385 386 else 387 "There's already a playlist using this name" 388 ) 389 |> Notifications.error 390 |> Common.showNotificationWithModel 391 { model | editPlaylistContext = Nothing } 392 393 Nothing -> 394 if validName then 395 { model 396 | editPlaylistContext = Nothing 397 , lastModifiedPlaylist = 398 case model.lastModifiedPlaylist of 399 Just l -> 400 if l.name == oldName then 401 Just { l | name = newName } 402 403 else 404 Just l 405 406 Nothing -> 407 Nothing 408 , playlists = newCollection ++ autoGenerated 409 } 410 |> User.savePlaylists 411 |> andThen redirectToPlaylistIndexPage 412 413 else 414 redirectToPlaylistIndexPage model 415 416 Nothing -> 417 redirectToPlaylistIndexPage model 418 419 420moveTrackInSelected : { to : Int } -> Manager 421moveTrackInSelected { to } model = 422 case model.selectedPlaylist of 423 Just playlist -> 424 let 425 moveParams = 426 { from = Maybe.withDefault 0 (List.head model.selectedTrackIndexes) 427 , to = to 428 , amount = List.length model.selectedTrackIndexes 429 } 430 431 updatedPlaylist = 432 { playlist | tracks = List.move moveParams playlist.tracks } 433 434 updatedPlaylistCollection = 435 List.map 436 (\p -> 437 ifThenElse 438 (p.autoGenerated == Nothing && p.name == updatedPlaylist.name) 439 updatedPlaylist 440 p 441 ) 442 model.playlists 443 in 444 { model 445 | playlists = updatedPlaylistCollection 446 , selectedPlaylist = Just updatedPlaylist 447 } 448 |> Tracks.reviseCollection Tracks.Collection.arrange 449 |> andThen User.savePlaylists 450 451 Nothing -> 452 Return.singleton model 453 454 455removeTracks : Playlist -> List IdentifiedTrack -> Manager 456removeTracks playlist tracks model = 457 let 458 updatedPlaylist = 459 Tracks.removeFromPlaylist tracks playlist 460 in 461 model.playlists 462 |> List.map 463 (\p -> 464 if p.name == playlist.name then 465 updatedPlaylist 466 467 else 468 p 469 ) 470 |> (\c -> { model | playlists = c }) 471 |> select updatedPlaylist 472 |> andThen User.savePlaylists 473 474 475select : Playlist -> Manager 476select playlist model = 477 { model | page = Page.Index, selectedPlaylist = Just playlist } 478 |> Tracks.reviseCollection Tracks.Collection.arrange 479 |> andThen User.saveEnclosedUserData 480 481 482setCreationContext : String -> Manager 483setCreationContext playlistName model = 484 Return.singleton { model | newPlaylistContext = Just playlistName } 485 486 487setModificationContext : String -> String -> Manager 488setModificationContext oldName newName model = 489 let 490 context = 491 { oldName = oldName 492 , newName = newName 493 } 494 in 495 Return.singleton { model | editPlaylistContext = Just context } 496 497 498showListMenu : Playlist -> Mouse.Event -> Manager 499showListMenu playlist mouseEvent model = 500 let 501 coordinates = 502 Coordinates.fromTuple mouseEvent.clientPos 503 504 contextMenu = 505 Playlists.listMenu 506 playlist 507 model.tracks.identified 508 model.confirmation 509 coordinates 510 in 511 Return.singleton { model | contextMenu = Just contextMenu } 512 513 514toggleVisibility : Playlist -> Manager 515toggleVisibility playlist model = 516 let 517 updatedPlaylist = 518 { playlist | public = not playlist.public } 519 in 520 model.playlists 521 |> List.map 522 (\p -> 523 if p.name == playlist.name then 524 updatedPlaylist 525 526 else 527 p 528 ) 529 |> (\c -> { model | playlists = c }) 530 |> User.savePlaylists 531 532 533 534-- ㊙️ 535 536 537redirectToPlaylistIndexPage : Manager 538redirectToPlaylistIndexPage = 539 Common.changeUrlUsingPage (Page.Playlists Index)