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 344 lines 11 kB view raw
1module UI.Tracks.Covers exposing (..) 2 3import Base64 4import Conditional exposing (ifThenElse) 5import Dict 6import Maybe.Extra as Maybe 7import Tracks exposing (..) 8 9 10 11-- 🔱 12 13 14generate : 15 SortBy 16 -> Tracks.Collection 17 -> CoverCollection 18generate sortBy tracks = 19 let 20 groupFn = 21 coverGroup sortBy 22 23 makeCoverFn = 24 makeCover sortBy 25 in 26 tracks.arranged 27 |> List.foldr 28 (\identifiedTrack { covers, gathering } -> 29 let 30 group = 31 groupFn identifiedTrack 32 33 ( identifiers, track ) = 34 identifiedTrack 35 36 { artist, album } = 37 track.tags 38 in 39 if group /= gathering.previousGroup then 40 -- New group, make cover for previous group 41 let 42 collection = 43 makeCoverFn gathering covers 44 in 45 { gathering = 46 { acc = [ identifiedTrack ] 47 , accIds = [ track.id ] 48 , previousGroup = group 49 , previousTrack = track 50 51 -- 52 , currentAlbumSequence = Just ( identifiedTrack, 1 ) 53 , largestAlbumSequence = Nothing 54 55 -- 56 , currentAlbumFavsSequence = Just ( identifiedTrack, ifThenElse identifiers.isFavourite 1 0 ) 57 , largestAlbumFavsSequence = Nothing 58 59 -- 60 , currentArtistSequence = Just ( identifiedTrack, 1 ) 61 , largestArtistSequence = Nothing 62 } 63 , covers = 64 collection 65 } 66 67 else 68 -- Same group 69 { gathering = 70 { acc = identifiedTrack :: gathering.acc 71 , accIds = track.id :: gathering.accIds 72 , previousGroup = group 73 , previousTrack = track 74 75 -- Album sequence 76 ----------------- 77 , currentAlbumSequence = 78 if album /= gathering.previousTrack.tags.album then 79 Just ( identifiedTrack, 1 ) 80 81 else 82 increaseSequence gathering.currentAlbumSequence 83 84 -- 85 , largestAlbumSequence = 86 if album /= gathering.previousTrack.tags.album then 87 resolveLargestSequence 88 gathering.currentAlbumSequence 89 gathering.largestAlbumSequence 90 91 else 92 gathering.largestAlbumSequence 93 94 -- Album favourites sequence 95 ---------------------------- 96 , currentAlbumFavsSequence = 97 if album /= gathering.previousTrack.tags.album then 98 Just ( identifiedTrack, ifThenElse identifiers.isFavourite 1 0 ) 99 100 else if identifiers.isFavourite then 101 increaseSequence gathering.currentAlbumFavsSequence 102 103 else 104 gathering.currentAlbumFavsSequence 105 106 -- 107 , largestAlbumFavsSequence = 108 if album /= gathering.previousTrack.tags.album then 109 resolveLargestSequence 110 gathering.currentAlbumFavsSequence 111 gathering.largestAlbumFavsSequence 112 113 else 114 gathering.largestAlbumFavsSequence 115 116 -- Artist sequence 117 ------------------ 118 , currentArtistSequence = 119 if artist /= gathering.previousTrack.tags.artist then 120 Just ( identifiedTrack, 1 ) 121 122 else 123 increaseSequence gathering.currentArtistSequence 124 125 -- 126 , largestArtistSequence = 127 if artist /= gathering.previousTrack.tags.artist then 128 resolveLargestSequence 129 gathering.currentArtistSequence 130 gathering.largestArtistSequence 131 132 else 133 gathering.largestArtistSequence 134 } 135 , covers = 136 covers 137 } 138 ) 139 { covers = 140 [] 141 , gathering = 142 { acc = [] 143 , accIds = [] 144 , previousGroup = "" 145 , previousTrack = emptyTrack 146 147 -- 148 , currentAlbumSequence = Nothing 149 , largestAlbumSequence = Nothing 150 , currentAlbumFavsSequence = Nothing 151 , largestAlbumFavsSequence = Nothing 152 , currentArtistSequence = Nothing 153 , largestArtistSequence = Nothing 154 } 155 } 156 |> (\{ covers, gathering } -> 157 makeCoverFn gathering covers 158 ) 159 |> (\collection -> 160 { arranged = collection, harvested = [] } 161 ) 162 163 164harvest : 165 Maybe Cover 166 -> SortBy 167 -> Tracks.Collection 168 -> CoverCollection 169 -> ( CoverCollection, Maybe Cover ) 170harvest previouslySelectedCover sortBy tracks covers = 171 let 172 groupFn = 173 coverGroup sortBy 174 175 ( groups, tracksPerGroup ) = 176 List.foldr 177 (\identifiedTrack ( acc, dict ) -> 178 let 179 group = 180 groupFn identifiedTrack 181 in 182 ( if Dict.member group dict == False then 183 group :: acc 184 185 else 186 acc 187 -- 188 , Dict.update group 189 (Maybe.unwrap [ identifiedTrack ] ((::) identifiedTrack) >> Just) 190 dict 191 ) 192 ) 193 ( [], Dict.empty ) 194 tracks.harvested 195 in 196 covers.arranged 197 |> List.foldr 198 (\cover ( acc, sel ) -> 199 if List.member cover.group groups then 200 let 201 groupTracks = 202 Maybe.withDefault [] (Dict.get cover.group tracksPerGroup) 203 204 trackIds = 205 List.map (Tuple.second >> .id) groupTracks 206 207 harvestedCover = 208 { cover | tracks = groupTracks, trackIds = trackIds } 209 in 210 case ( previouslySelectedCover, sel ) of 211 ( Just pre, Nothing ) -> 212 ( harvestedCover :: acc 213 , if pre.key == harvestedCover.key then 214 Just harvestedCover 215 216 else 217 Nothing 218 ) 219 220 ( Just _, Just s ) -> 221 ( harvestedCover :: acc 222 , Just s 223 ) 224 225 ( Nothing, _ ) -> 226 ( harvestedCover :: acc 227 , Nothing 228 ) 229 230 else 231 ( acc 232 , sel 233 ) 234 ) 235 ( [] 236 , Nothing 237 ) 238 |> Tuple.mapFirst 239 (\h -> { covers | harvested = h }) 240 241 242 243-- ⚗️ 244 245 246makeCover sortBy_ gathering collection = 247 let 248 closedGathering = 249 { gathering 250 | largestAlbumSequence = 251 resolveLargestSequence 252 gathering.currentAlbumSequence 253 gathering.largestAlbumSequence 254 255 -- 256 , largestAlbumFavsSequence = 257 resolveLargestSequence 258 gathering.currentAlbumFavsSequence 259 gathering.largestAlbumFavsSequence 260 261 -- 262 , largestArtistSequence = 263 resolveLargestSequence 264 gathering.currentArtistSequence 265 gathering.largestArtistSequence 266 } 267 in 268 case closedGathering.acc of 269 [] -> 270 collection 271 272 fallback :: _ -> 273 makeCoverWithFallback sortBy_ closedGathering fallback :: collection 274 275 276makeCoverWithFallback _ gathering fallback = 277 let 278 amountOfTracks = 279 List.length gathering.accIds 280 281 group = 282 gathering.previousGroup 283 284 identifiedTrack : IdentifiedTrack 285 identifiedTrack = 286 gathering.largestAlbumFavsSequence 287 |> Maybe.orElse gathering.largestAlbumSequence 288 |> Maybe.map Tuple.first 289 |> Maybe.withDefault fallback 290 291 ( _, track ) = 292 identifiedTrack 293 294 ( largestAlbumSequence, largestArtistSequence ) = 295 ( Maybe.unwrap 0 Tuple.second gathering.largestAlbumSequence 296 , Maybe.unwrap 0 Tuple.second gathering.largestArtistSequence 297 ) 298 299 ( sameAlbum, sameArtist ) = 300 ( largestAlbumSequence == amountOfTracks 301 , largestArtistSequence == amountOfTracks 302 ) 303 304 isVariousArtists = 305 False 306 || (amountOfTracks > 4 && largestArtistSequence < 3) 307 || (Maybe.map String.toLower track.tags.artist == Just "va") 308 in 309 { key = Base64.encode (coverKey isVariousArtists track) 310 , identifiedTrackCover = identifiedTrack 311 312 -- 313 , group = group 314 , sameAlbum = sameAlbum 315 , sameArtist = sameArtist 316 317 -- 318 , trackIds = gathering.accIds 319 , tracks = gathering.acc 320 , variousArtists = isVariousArtists 321 } 322 323 324 325-- ⚗️ ░░ SEQUENCES 326 327 328increaseSequence = 329 Maybe.map (Tuple.mapSecond ((+) 1)) 330 331 332resolveLargestSequence curr state = 333 case ( curr, state ) of 334 ( Just ( _, c ), Just ( _, s ) ) -> 335 ifThenElse (c > s) curr state 336 337 ( Just _, Nothing ) -> 338 curr 339 340 ( Nothing, Just _ ) -> 341 state 342 343 ( Nothing, Nothing ) -> 344 Nothing