From b5133ee70cbc43d09baea0756871534288f6acfd Mon Sep 17 00:00:00 2001 From: Steven Vandevelde Date: Sat, 10 Sep 2022 17:22:47 +0200 Subject: [PATCH] Closes #305 --- CHANGELOG.md | 1 + Justfile | 7 +-- flake.lock | 6 +-- src/Applications/UI.elm | 1 + src/Applications/UI/Authentication/State.elm | 1 + src/Applications/UI/Queue/State.elm | 25 ++++++++++- src/Applications/UI/Settings.elm | 9 ++++ src/Applications/UI/Tracks/Covers.elm | 32 ------------- src/Applications/UI/Tracks/State.elm | 45 +++++++++++++++---- src/Applications/UI/Tracks/Types.elm | 1 + src/Applications/UI/Types.elm | 1 + src/Applications/UI/User/State/Export.elm | 3 +- src/Applications/UI/User/State/Import.elm | 2 + src/Applications/UI/View.elm | 1 + src/Library/Settings.elm | 5 +++ src/Library/Tracks.elm | 32 +++++++++++++ .../Tracks/Collection/Internal/Harvest.elm | 4 ++ stack.yaml | 5 +-- 18 files changed, 126 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2182c808..327be0b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Add support for non-standard `audio/x-flac` mimetype. - Fixes a playback issue with Google Drive on Safari/iOS. - Improves Google Drive support, access tokens are now refreshed when needed (before it only refreshed on source processing) +- Reduces the track pool when selecting a cover. In other words, when you're using the album art mode and select an image, only those tracks will be in the "automatic" queue (automatic queue, as in, not manually added queue items). This behaviour can be disabled on the settings page if you prefer the old behaviour. - Shift + Click actions for the top-right nav items on the tracks page. - Several playlist improvements: add to queue, add options to autogenerated playlists, convert autogenerated playlist into regular playlist, etc. diff --git a/Justfile b/Justfile index 9ced5392..6c9c833d 100644 --- a/Justfile +++ b/Justfile @@ -175,7 +175,7 @@ js-prod: vendor-js # @dev: build - just watch-wo-build & just server + just watch & just server @doc-tests: @@ -229,10 +229,7 @@ js-prod: vendor-js @test: doc-tests -@watch: build watch-wo-build - - -@watch-wo-build: +@watch: echo "> Watching" just watch-css & just watch-elm & just watch-js & just watch-system diff --git a/flake.lock b/flake.lock index dbfccea6..a8cf4f59 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1662173844, - "narHash": "sha256-+ZgW98Y8fZkgFSylE+Mzalumw+kw3SVivZznbJqQaj8=", + "lastModified": 1662778811, + "narHash": "sha256-lpkekAbs8FNoqpbxuMpkdNMiRnWxDyvAyR+pWxW2PTs=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "8ac6d40380dc4ec86f1ff591d5c14c8ae1d77a18", + "rev": "70d8df25fbe9cc5c74900b11d06ef120200f3948", "type": "github" }, "original": { diff --git a/src/Applications/UI.elm b/src/Applications/UI.elm index de5a79d7..41a6d42b 100644 --- a/src/Applications/UI.elm +++ b/src/Applications/UI.elm @@ -196,6 +196,7 @@ init flags url key = , cachedTracksOnly = False , cachingTracksInProgress = [] , covers = { arranged = [], harvested = [] } + , coverSelectionReducesPool = True , favourites = [] , favouritesOnly = False , grouping = Nothing diff --git a/src/Applications/UI/Authentication/State.elm b/src/Applications/UI/Authentication/State.elm index cd804c37..06a73ccc 100644 --- a/src/Applications/UI/Authentication/State.elm +++ b/src/Applications/UI/Authentication/State.elm @@ -520,6 +520,7 @@ signOut model = -- Tracks --------- + , coverSelectionReducesPool = True , favourites = [] , hideDuplicates = False , searchResults = Nothing diff --git a/src/Applications/UI/Queue/State.elm b/src/Applications/UI/Queue/State.elm index 069e01b5..df676c65 100644 --- a/src/Applications/UI/Queue/State.elm +++ b/src/Applications/UI/Queue/State.elm @@ -111,7 +111,13 @@ fill : Manager fill model = let ( availableTracks, timestamp ) = - ( model.tracks.harvested + ( case ( model.selectedCover, model.coverSelectionReducesPool ) of + ( Just cover, True ) -> + Tuple.first <| List.foldl coverTracksHarvester ( [], cover.trackIds ) model.tracks.harvested + + _ -> + model.tracks.harvested + -- , model.currentTime ) @@ -421,6 +427,23 @@ removeItem { index, item } model = -- ⚗️ +coverTracksHarvester : + IdentifiedTrack + -> ( List IdentifiedTrack, List String ) + -> ( List IdentifiedTrack, List String ) +coverTracksHarvester ( i, t ) ( acc, coverTrackIds ) = + case List.findIndex ((==) t.id) coverTrackIds of + Just idx -> + ( acc ++ [ ( i, t ) ] + , List.removeAt idx coverTrackIds + ) + + Nothing -> + ( acc + , coverTrackIds + ) + + moveItem : { from : Int, to : Int, shuffle : Bool } -> List Item -> List Item moveItem { from, to, shuffle } collection = let diff --git a/src/Applications/UI/Settings.elm b/src/Applications/UI/Settings.elm index 64297e58..70da9beb 100644 --- a/src/Applications/UI/Settings.elm +++ b/src/Applications/UI/Settings.elm @@ -35,6 +35,7 @@ type alias Dependencies = { authenticationMethod : Maybe User.Layer.Method , buildTimestamp : Int , chosenBackgroundImage : Maybe String + , coverSelectionReducesPool : Bool , currentTimeZone : Time.Zone , extractedBackdropColor : Maybe Color , hideDuplicateTracks : Bool @@ -347,6 +348,14 @@ content deps = , toggleMsg = ToggleRememberProgress } ] + , chunk + [ "w-full", "md:w-1/2" ] + [ label "Cover selection reduces track pool" + , UI.Kit.checkbox + { checked = deps.coverSelectionReducesPool + , toggleMsg = TracksMsg Tracks.ToggleCoverSelectionReducesPool + } + ] ] ] diff --git a/src/Applications/UI/Tracks/Covers.elm b/src/Applications/UI/Tracks/Covers.elm index 8e032e8e..82a29e40 100644 --- a/src/Applications/UI/Tracks/Covers.elm +++ b/src/Applications/UI/Tracks/Covers.elm @@ -246,38 +246,6 @@ harvest previouslySelectedCover sortBy tracks covers = -- ⚗️ -coverGroup : SortBy -> IdentifiedTrack -> String -coverGroup sort ( identifiers, { tags } as track ) = - (case sort of - Artist -> - tags.artist - - Album -> - -- There is the possibility of albums with the same name, - -- such as "Greatests Hits". - -- To make sure we treat those as different albums, - -- we prefix the album by its parent directory. - identifiers.parentDirectory ++ tags.album - - PlaylistIndex -> - "" - - Title -> - tags.title - ) - |> String.trim - |> String.toLower - - -coverKey : Bool -> Track -> String -coverKey isVariousArtists { tags } = - if isVariousArtists then - tags.album - - else - tags.artist ++ " --- " ++ tags.album - - makeCover sortBy_ gathering collection = let closedGathering = diff --git a/src/Applications/UI/Tracks/State.elm b/src/Applications/UI/Tracks/State.elm index 9eeedfe8..6105bdc7 100644 --- a/src/Applications/UI/Tracks/State.elm +++ b/src/Applications/UI/Tracks/State.elm @@ -67,6 +67,9 @@ update msg = ToggleCachedOnly -> toggleCachedOnly + ToggleCoverSelectionReducesPool -> + toggleCoverSelectionReducesPool + ToggleFavouritesOnly -> toggleFavouritesOnly @@ -212,6 +215,13 @@ changeScene scene model = Cmd.none ) |> return { model | scene = scene, selectedCover = Nothing } + |> andThen + (if model.coverSelectionReducesPool then + Queue.reset + + else + Return.singleton + ) |> andThen Common.forceTracksRerender |> andThen User.saveEnclosedUserData @@ -241,7 +251,13 @@ clearSearch model = deselectCover : Manager deselectCover model = - Return.singleton { model | selectedCover = Nothing } + (if model.coverSelectionReducesPool then + Queue.reset + + else + Return.singleton + ) + { model | selectedCover = Nothing } download : String -> List Track -> Manager @@ -575,9 +591,14 @@ search model = selectCover : Cover -> Manager selectCover cover model = - return - { model | selectedCover = Just cover } - (Ports.loadAlbumCovers { list = False, coverView = True }) + { model | selectedCover = Just cover } + |> (if model.coverSelectionReducesPool then + Queue.reset + + else + Return.singleton + ) + |> Return.command (Ports.loadAlbumCovers { list = False, coverView = True }) setSearchResults : Json.Value -> Manager @@ -844,6 +865,13 @@ toggleCachedOnly model = |> andThen Common.forceTracksRerender +toggleCoverSelectionReducesPool : Manager +toggleCoverSelectionReducesPool model = + { model | coverSelectionReducesPool = not model.coverSelectionReducesPool } + |> Queue.reset + |> andThen User.saveSettings + + toggleFavourite : Int -> Manager toggleFavourite index model = case List.getAt index model.tracks.harvested of @@ -958,11 +986,11 @@ resolveParcel ( deps, newCollection ) model = model.tracks.harvested newCollection.harvested - searchChanged = + scrollContextChanged = newScrollContext /= model.tracks.scrollContext modelWithNewCollection = - (if model.scene == List && searchChanged then + (if model.scene == List && scrollContextChanged then \m -> { m | infiniteList = InfiniteList.updateScroll scrollEvent m.infiniteList } else @@ -995,7 +1023,7 @@ resolveParcel ( deps, newCollection ) model = ----------------------------------------- -- Command ----------------------------------------- - , if searchChanged then + , if scrollContextChanged then case model.scene of Covers -> UI.Tracks.Scene.Covers.scrollToTop @@ -1009,7 +1037,7 @@ resolveParcel ( deps, newCollection ) model = whenHarvestChanges = - andThen Queue.reset >> andThen harvestCovers + andThen harvestCovers >> andThen Queue.reset whenArrangementChanges = @@ -1036,7 +1064,6 @@ importHypaethral : HypaethralData -> Maybe Playlist -> Manager importHypaethral data selectedPlaylist model = { model | favourites = data.favourites - , hideDuplicates = Maybe.unwrap False .hideDuplicates data.settings , selectedPlaylist = selectedPlaylist , tracks = { emptyCollection | untouched = data.tracks } } diff --git a/src/Applications/UI/Tracks/Types.elm b/src/Applications/UI/Tracks/Types.elm index e820d909..6da70d70 100644 --- a/src/Applications/UI/Tracks/Types.elm +++ b/src/Applications/UI/Tracks/Types.elm @@ -44,6 +44,7 @@ type Msg | RemoveFavourites (List IdentifiedTrack) | SortBy SortBy | ToggleFavourite Int + | ToggleCoverSelectionReducesPool ----------------------------------------- -- Groups ----------------------------------------- diff --git a/src/Applications/UI/Types.elm b/src/Applications/UI/Types.elm index 51cbf6d3..c25d50f8 100644 --- a/src/Applications/UI/Types.elm +++ b/src/Applications/UI/Types.elm @@ -160,6 +160,7 @@ type alias Model = , cachedTracksOnly : Bool , cachingTracksInProgress : List String , covers : { arranged : List Tracks.Cover, harvested : List Tracks.Cover } + , coverSelectionReducesPool : Bool , favourites : List Favourite , favouritesOnly : Bool , grouping : Maybe Grouping diff --git a/src/Applications/UI/User/State/Export.elm b/src/Applications/UI/User/State/Export.elm index 253c40e3..ca81f00d 100644 --- a/src/Applications/UI/User/State/Export.elm +++ b/src/Applications/UI/User/State/Export.elm @@ -33,8 +33,9 @@ export model = gatherSettings : Model -> Settings -gatherSettings { chosenBackdrop, hideDuplicates, lastFm, processAutomatically, rememberProgress } = +gatherSettings { chosenBackdrop, coverSelectionReducesPool, hideDuplicates, lastFm, processAutomatically, rememberProgress } = { backgroundImage = chosenBackdrop + , coverSelectionReducesPool = coverSelectionReducesPool , hideDuplicates = hideDuplicates , lastFm = lastFm.sessionKey , processAutomatically = processAutomatically diff --git a/src/Applications/UI/User/State/Import.elm b/src/Applications/UI/User/State/Import.elm index 0e30ec1a..a7db4806 100644 --- a/src/Applications/UI/User/State/Import.elm +++ b/src/Applications/UI/User/State/Import.elm @@ -176,6 +176,8 @@ importHypaethral value model = selectedPlaylist { model | chosenBackdrop = chosenBackdrop + , coverSelectionReducesPool = Maybe.unwrap True .coverSelectionReducesPool data.settings + , hideDuplicates = Maybe.unwrap False .hideDuplicates data.settings , lastFm = { lastFmModel | sessionKey = Maybe.andThen .lastFm data.settings } , playlists = newPlaylistsCollection , playlistToActivate = Nothing diff --git a/src/Applications/UI/View.elm b/src/Applications/UI/View.elm index fb7faa99..5d089b00 100644 --- a/src/Applications/UI/View.elm +++ b/src/Applications/UI/View.elm @@ -178,6 +178,7 @@ defaultScreen model = { authenticationMethod = Authentication.extractMethod model.authentication , buildTimestamp = model.buildTimestamp , chosenBackgroundImage = model.chosenBackdrop + , coverSelectionReducesPool = model.coverSelectionReducesPool , currentTimeZone = model.currentTimeZone , extractedBackdropColor = model.extractedBackdropColor , hideDuplicateTracks = model.hideDuplicates diff --git a/src/Library/Settings.elm b/src/Library/Settings.elm index 9fc30b1d..73199a09 100644 --- a/src/Library/Settings.elm +++ b/src/Library/Settings.elm @@ -12,6 +12,7 @@ import Maybe.Extra as Maybe type alias Settings = { backgroundImage : Maybe String + , coverSelectionReducesPool : Bool , hideDuplicates : Bool , lastFm : Maybe String , processAutomatically : Bool @@ -29,6 +30,9 @@ encode settings = [ ( "backgroundImage" , Maybe.unwrap Json.Encode.null Json.Encode.string settings.backgroundImage ) + , ( "coverSelectionReducesPool" + , Json.Encode.bool settings.coverSelectionReducesPool + ) , ( "hideDuplicates" , Json.Encode.bool settings.hideDuplicates ) @@ -52,6 +56,7 @@ decoder : Json.Decoder Settings decoder = Json.succeed Settings |> optional "backgroundImage" (Json.maybe Json.string) Nothing + |> optional "coverSelectionReducesPool" Json.bool True |> optional "hideDuplicates" Json.bool False |> optional "lastFm" (Json.maybe Json.string) Nothing |> optional "processAutomatically" Json.bool True diff --git a/src/Library/Tracks.elm b/src/Library/Tracks.elm index a64bd5df..bd36a744 100644 --- a/src/Library/Tracks.elm +++ b/src/Library/Tracks.elm @@ -224,6 +224,38 @@ emptyCollection = -- MORE STUFF +coverGroup : SortBy -> IdentifiedTrack -> String +coverGroup sort ( identifiers, { tags } as track ) = + (case sort of + Artist -> + tags.artist + + Album -> + -- There is the possibility of albums with the same name, + -- such as "Greatests Hits". + -- To make sure we treat those as different albums, + -- we prefix the album by its parent directory. + identifiers.parentDirectory ++ tags.album + + PlaylistIndex -> + "" + + Title -> + tags.title + ) + |> String.trim + |> String.toLower + + +coverKey : Bool -> Track -> String +coverKey isVariousArtists { tags } = + if isVariousArtists then + tags.album + + else + tags.artist ++ " --- " ++ tags.album + + isNowPlaying : IdentifiedTrack -> IdentifiedTrack -> Bool isNowPlaying ( a, b ) ( x, y ) = a.indexInPlaylist == x.indexInPlaylist && b.id == y.id diff --git a/src/Library/Tracks/Collection/Internal/Harvest.elm b/src/Library/Tracks/Collection/Internal/Harvest.elm index 36ee8fcc..f3b2e16e 100644 --- a/src/Library/Tracks/Collection/Internal/Harvest.elm +++ b/src/Library/Tracks/Collection/Internal/Harvest.elm @@ -120,6 +120,10 @@ harvest ( deps, collection ) = |> (\c -> ( deps, c )) + +-- 🛠 + + harvester : IdentifiedTrack -> ( List IdentifiedTrack, List String ) diff --git a/stack.yaml b/stack.yaml index 4a84cda3..86cd94a5 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,6 +1,3 @@ -resolver: lts-19.16 +resolver: nightly-2022-09-10 recommend-stack-upgrade: false allow-newer: true - -extra-deps: - - protolude-0.3.2 -- 2.51.2