Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MOBILE-213: Implementation of CreatedForYou screen #535

Merged
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2d1e6fa
Playlist data classes added
hemang-mishra Jan 15, 2025
616e690
Added vectors
hemang-mishra Jan 17, 2025
8c59552
Added data classes of UIState and created playlist card
hemang-mishra Jan 17, 2025
a84bcdc
Updated payload data classes
hemang-mishra Jan 17, 2025
6769e25
assigned default values to data classes
hemang-mishra Jan 17, 2025
c517bb3
Added heading composable
hemang-mishra Jan 24, 2025
1726505
Added repositories and ui states
hemang-mishra Jan 24, 2025
414b8da
Fetching repository data into viewmodel
hemang-mishra Jan 24, 2025
11efd6e
Made UI for CreatedForYou screen
hemang-mishra Jan 25, 2025
243a40c
Added share playlist functionality
hemang-mishra Jan 25, 2025
1ec3ec2
Added play functionality and dropdown feature
hemang-mishra Jan 26, 2025
55e3f62
Dropdown click fixed
hemang-mishra Jan 26, 2025
61d470a
Duplicate playlist implemented
hemang-mishra Jan 26, 2025
96a5e2f
Ui improvements
hemang-mishra Jan 26, 2025
4558484
Added relevant comments
hemang-mishra Jan 26, 2025
98a52cc
Update PlaylistSelectionCards.kt
hemang-mishra Jan 26, 2025
cdc8839
Fixed some bugs
hemang-mishra Jan 26, 2025
318b28a
Added retry fetch
hemang-mishra Jan 26, 2025
f1f0be4
updated tests
hemang-mishra Jan 26, 2025
f3f96b2
added tests for playlist repository
hemang-mishra Jan 26, 2025
1ba9bd0
Merge remote-tracking branch 'upstream/main' into pr/535
07jasjeet Jan 26, 2025
eadef91
Hiding PlayAll Button
hemang-mishra Jan 26, 2025
f38385e
Merge branch 'feat-createdForYou-hemang_mishra' of github.com:hemang-…
hemang-mishra Jan 26, 2025
5ca1ccb
Removed PlaylistTrackComposable
hemang-mishra Jan 27, 2025
d1c2b8a
Moved some functions to Util package
hemang-mishra Jan 27, 2025
3507786
Added preview of Created For You Screen
hemang-mishra Jan 27, 2025
3c774e3
Merge remote-tracking branch 'upstream/main' into pr/535
07jasjeet Jan 27, 2025
2e2c6b3
Save state while navigating
07jasjeet Jan 27, 2025
91a0e04
Merge remote-tracking branch 'upstream/main' into pr/535
07jasjeet Jan 28, 2025
3c663c0
Changes
07jasjeet Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.listenbrainz.android.di

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.listenbrainz.android.repository.playlists.PlaylistDataRepository
import org.listenbrainz.android.repository.playlists.PlaylistDataRepositoryImpl

@Module
@InstallIn(SingletonComponent::class)
abstract class PlaylistRepositoryModule {

@Binds
abstract fun bindsPlaylistRepository(repository: PlaylistDataRepositoryImpl?): PlaylistDataRepository?
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.listenbrainz.android.service.CBService
import org.listenbrainz.android.service.FeedService
import org.listenbrainz.android.service.ListensService
import org.listenbrainz.android.service.MBService
import org.listenbrainz.android.service.PlaylistService
import org.listenbrainz.android.service.SocialService
import org.listenbrainz.android.service.UserService
import org.listenbrainz.android.service.Yim23Service
Expand Down Expand Up @@ -92,6 +93,12 @@ class ServiceModule {
constructRetrofit(appPreferences)
.create(UserService::class.java)

@Singleton
@Provides
fun providesPlaylistService(appPreferences: AppPreferences) : PlaylistService =
constructRetrofit(appPreferences)
.create(PlaylistService::class.java)

@Singleton
@Provides
fun providesArtistService(): ArtistService = Retrofit.Builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.listenbrainz.android.model.createdForYou


import com.google.gson.annotations.SerializedName

data class AdditionalMetadata(
@SerializedName("algorithm_metadata")
val algorithmMetadata: AlgorithmMetadata = AlgorithmMetadata(),
@SerializedName("expires_at")
val expiresAt: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.listenbrainz.android.model.createdForYou


import com.google.gson.annotations.SerializedName

data class AlgorithmMetadata(
@SerializedName("source_patch")
val sourcePatch: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.listenbrainz.android.model.createdForYou


import com.google.gson.annotations.SerializedName

data class CreatedForYouExtensionData(
@SerializedName("additional_metadata")
val additionalMetadata: AdditionalMetadata = AdditionalMetadata(),
@SerializedName("created_for")
val createdFor: String? = null,
@SerializedName("creator")
val creator: String? = null,
@SerializedName("last_modified_at")
val lastModifiedAt: String? = null,
@SerializedName("public")
val public: Boolean? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.listenbrainz.android.model.createdForYou


import com.google.gson.annotations.SerializedName

data class CreatedForYouPayload(
@SerializedName("count")
val count: Int? = null,
@SerializedName("offset")
val offset: Int? = null,
@SerializedName("playlist_count")
val playlistCount: Int? = null,
@SerializedName("playlists")
val playlists: List<CreatedForYouPlaylists> = listOf()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.listenbrainz.android.model.createdForYou


import com.google.gson.annotations.SerializedName

data class CreatedForYouPlaylist(
@SerializedName("annotation")
val annotation: String? = null,
@SerializedName("creator")
val creator: String? = null,
@SerializedName("date")
val date: String? = null,
@SerializedName("extension")
val extension: Extension = Extension(),
@SerializedName("identifier")
val identifier: String? = null,
@SerializedName("title")
val title: String? = null,
@SerializedName("track")
val track: List<Any> = listOf()
){
// Get the MBID of the playlist
fun getPlaylistMBID(): String? {
// Regex to extract the MBID from the identifier
val regex = """playlist/([a-f0-9\-]+)""".toRegex()
val matchResult = identifier?.let { regex.find(it) }
return matchResult?.groupValues?.get(1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.listenbrainz.android.model.createdForYou


import com.google.gson.annotations.SerializedName

data class CreatedForYouPlaylists(
@SerializedName("playlist")
val playlist: CreatedForYouPlaylist = CreatedForYouPlaylist()
){
fun getPlaylistMBID(): String? {
val url = playlist.identifier
val regex = """playlist/([a-f0-9\-]+)""".toRegex()
val matchResult = url?.let { regex.find(it) }
return matchResult?.groupValues?.get(1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.listenbrainz.android.model.createdForYou


import com.google.gson.annotations.SerializedName

data class Extension(
@SerializedName("https://musicbrainz.org/doc/jspf#playlist")
val createdForYouExtensionData: CreatedForYouExtensionData = CreatedForYouExtensionData()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class AdditionalMetadata(
@SerializedName("algorithm_metadata")
val algorithmMetadata: AlgorithmMetadata = AlgorithmMetadata(),
@SerializedName("expires_at")
val expiresAt: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class AdditionalMetadataTrack(
@SerializedName("artists")
val artists: List<PlaylistArtist> = listOf(),
@SerializedName("caa_id")
val caaId: Long? = null,
@SerializedName("caa_release_mbid")
val caaReleaseMbid: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class AlgorithmMetadata(
@SerializedName("source_patch")
val sourcePatch: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class CopyPlaylistResponse(
@SerializedName("playlist_mbid")
val playlistMbid: String,
@SerializedName("status")
val status: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class Extension(
@SerializedName("https://musicbrainz.org/doc/jspf#playlist")
val playlistExtensionData: PlaylistExtensionData = PlaylistExtensionData()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class PlaylistArtist(
@SerializedName("artist_credit_name")
val artistCreditName: String? = null,
@SerializedName("artist_mbid")
val artistMbid: String? = null,
@SerializedName("join_phrase")
val joinPhrase: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class PlaylistData(
@SerializedName("annotation")
val annotation: String? = null,
@SerializedName("creator")
val creator: String? = null,
@SerializedName("date")
val date: String? = null,
@SerializedName("extension")
val extension: Extension = Extension(),
@SerializedName("identifier")
val identifier: String? = null,
@SerializedName("title")
val title: String? = null,
@SerializedName("track")
val track: List<PlaylistTrack> = listOf()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class PlaylistExtensionData(
@SerializedName("additional_metadata")
val additionalMetadata: AdditionalMetadata = AdditionalMetadata(),
@SerializedName("created_for")
val createdFor: String? = null,
@SerializedName("creator")
val creator: String? = null,
@SerializedName("last_modified_at")
val lastModifiedAt: String? = null,
@SerializedName("public")
val `public`: Boolean? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class PlaylistPayload(
@SerializedName("playlist")
val playlist: PlaylistData = PlaylistData()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName
import org.listenbrainz.android.model.AdditionalInfo
import org.listenbrainz.android.model.MbidMapping
import org.listenbrainz.android.model.Metadata
import org.listenbrainz.android.model.TrackMetadata
import org.listenbrainz.android.model.feed.FeedListenArtist

data class PlaylistTrack(
@SerializedName("album")
val album: String? = null,
@SerializedName("creator")
val creator: String? = null,
@SerializedName("duration")
val duration: Int? = null,
@SerializedName("extension")
val extension: TrackExtension = TrackExtension(),
@SerializedName("identifier")
val identifier: List<String> = listOf(),
@SerializedName("title")
val title: String? = null
){
fun toMetadata(): Metadata{
val artistMBID = extension.trackExtensionData.additionalMetadata.artists.map{it.artistMbid?:""}
val artist = extension.trackExtensionData.additionalMetadata.artists
val data = Metadata(
trackMetadata = TrackMetadata(
artistName = creator?:"",
releaseName = album,
trackName = title?:"",
mbidMapping = MbidMapping(
artistMbids = artistMBID,
artists = artist.map {
FeedListenArtist(
it.artistCreditName?:"",
it.artistMbid,
it.joinPhrase
)
},
recordingMbid = getRecordingMBID(),
recordingName = title?:""
),
additionalInfo = AdditionalInfo(
artistMbids = artistMBID,
artistNames = artist.map { it.artistCreditName?:"" },
durationMs = duration?:0,
recordingMbid = getRecordingMBID(),
)
)
)
return data
}

fun getRecordingMBID(): String?{
val url = identifier.firstOrNull()
val regex = """recording/([a-f0-9\-]+)""".toRegex()
val matchResult = url?.let { regex.find(it) }
return matchResult?.groupValues?.get(1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class TrackExtension(
@SerializedName("https://musicbrainz.org/doc/jspf#track")
val trackExtensionData: TrackExtensionData = TrackExtensionData()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.listenbrainz.android.model.playlist


import com.google.gson.annotations.SerializedName

data class TrackExtensionData(
@SerializedName("added_at")
val addedAt: String? = null,
@SerializedName("added_by")
val addedBy: String? = null,
@SerializedName("additional_metadata")
val additionalMetadata: AdditionalMetadataTrack = AdditionalMetadataTrack(),
@SerializedName("artist_identifiers")
val artistIdentifiers: List<String> = listOf()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.listenbrainz.android.repository.playlists

import org.listenbrainz.android.model.playlist.CopyPlaylistResponse
import org.listenbrainz.android.model.playlist.PlaylistPayload
import org.listenbrainz.android.util.Resource

interface PlaylistDataRepository {

// Fetches the playlist with tracks for the given MBID
suspend fun fetchPlaylist(playlistMbid: String?): Resource<PlaylistPayload?>

//Duplicates the playlist with the given MBID and returns the new playlist MBID
suspend fun copyPlaylist(playlistMbid: String?): Resource<CopyPlaylistResponse?>
}
Loading
Loading