From ef5ad693adceef4cbc927fc02cf02c9196e7c265 Mon Sep 17 00:00:00 2001 From: brahmkshatriya <69040506+brahmkshatriya@users.noreply.github.com> Date: Mon, 16 Sep 2024 23:59:51 +0530 Subject: [PATCH] Add new radio type item, and more changes to how extensions work --- app/build.gradle.kts | 4 +- .../echo/download/Downloader.kt | 2 + .../echo/offline/OfflineExtension.kt | 120 ++++++++++-------- .../echo/offline/TestExtension.kt | 19 +-- .../echo/playback/PlayerSessionCallback.kt | 4 +- .../dev/brahmkshatriya/echo/playback/Radio.kt | 26 ++-- .../echo/ui/adapter/MediaClickListener.kt | 8 ++ .../echo/ui/adapter/MediaContainerAdapter.kt | 16 +-- .../ui/adapter/MediaContainerViewHolder.kt | 67 ++++++++++ .../echo/ui/adapter/MediaItemViewHolder.kt | 2 + .../SearchForPlaylistClickListener.kt | 12 +- .../echo/ui/item/ItemBottomSheet.kt | 10 +- .../echo/ui/item/ItemFragment.kt | 9 ++ .../echo/ui/item/ItemViewModel.kt | 24 +++- .../echo/viewmodels/PlayerViewModel.kt | 14 +- app/src/main/res/drawable/art_sensors.xml | 10 ++ app/src/main/res/drawable/ic_radio.xml | 9 -- app/src/main/res/drawable/ic_sensors.xml | 9 ++ app/src/main/res/layout/item_album_info.xml | 2 +- app/src/main/res/layout/item_artist_info.xml | 2 +- .../res/layout/item_dialog_button_loading.xml | 2 +- app/src/main/res/layout/new_item_tracks.xml | 74 +++++++++++ app/src/main/res/values/strings.xml | 2 +- .../echo/common/clients/RadioClient.kt | 16 ++- .../common/clients/SaveToLibraryClient.kt | 9 ++ .../echo/common/clients/ShareClient.kt | 12 +- .../echo/common/models/EchoMediaItem.kt | 10 ++ .../echo/common/models/MediaItemsContainer.kt | 14 ++ .../echo/common/models/Radio.kt | 12 ++ .../brahmkshatriya/echo/common/models/Tab.kt | 3 + .../echo/common/providers/ContextProvider.kt | 7 - 31 files changed, 389 insertions(+), 141 deletions(-) create mode 100644 app/src/main/res/drawable/art_sensors.xml delete mode 100644 app/src/main/res/drawable/ic_radio.xml create mode 100644 app/src/main/res/drawable/ic_sensors.xml create mode 100644 app/src/main/res/layout/new_item_tracks.xml create mode 100644 common/src/main/java/dev/brahmkshatriya/echo/common/clients/SaveToLibraryClient.kt create mode 100644 common/src/main/java/dev/brahmkshatriya/echo/common/models/Radio.kt delete mode 100644 common/src/main/java/dev/brahmkshatriya/echo/common/providers/ContextProvider.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5525685a..cc2624a6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -44,7 +44,7 @@ android { dependencies { implementation(project(":common")) - implementation("com.github.brahmkshatriya:plugger:structure-overhaul-SNAPSHOT") + implementation("com.github.JeelPatel231:plugger:structure-overhaul-SNAPSHOT") implementation("androidx.appcompat:appcompat:1.7.0") @@ -87,7 +87,7 @@ dependencies { implementation("com.flaviofaria:kenburnsview:1.0.7") implementation("com.github.paramsen:noise:2.0.0") - implementation("com.github.Kyant0:taglib:1.0.0-alpha17") + implementation("com.github.Kyant0:taglib:1.0.0-alpha22") //TODO : use fetch instead of download manager // implementation("com.github.tonyofrancis.Fetch:xfetch2:3.1.6") diff --git a/app/src/main/java/dev/brahmkshatriya/echo/download/Downloader.kt b/app/src/main/java/dev/brahmkshatriya/echo/download/Downloader.kt index d898100e..9e7dd38b 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/download/Downloader.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/download/Downloader.kt @@ -65,6 +65,8 @@ class Downloader( context.enqueueDownload(info, client, it, playlist.toMediaItem()) } } + + is EchoMediaItem.Lists.RadioItem -> Unit } } diff --git a/app/src/main/java/dev/brahmkshatriya/echo/offline/OfflineExtension.kt b/app/src/main/java/dev/brahmkshatriya/echo/offline/OfflineExtension.kt index 61064b13..d0140586 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/offline/OfflineExtension.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/offline/OfflineExtension.kt @@ -21,6 +21,7 @@ import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Companion.toMediaItem import dev.brahmkshatriya.echo.common.models.MediaItemsContainer import dev.brahmkshatriya.echo.common.models.Playlist import dev.brahmkshatriya.echo.common.models.QuickSearchItem +import dev.brahmkshatriya.echo.common.models.Radio import dev.brahmkshatriya.echo.common.models.Streamable import dev.brahmkshatriya.echo.common.models.Streamable.Audio.Companion.toAudio import dev.brahmkshatriya.echo.common.models.Streamable.Media.Companion.toMedia @@ -41,6 +42,8 @@ import dev.brahmkshatriya.echo.plugger.ExtensionMetadata import dev.brahmkshatriya.echo.plugger.ImportType import dev.brahmkshatriya.echo.utils.getFromCache import dev.brahmkshatriya.echo.utils.saveToCache +import dev.brahmkshatriya.echo.utils.toData +import dev.brahmkshatriya.echo.utils.toJson class OfflineExtension(val context: Context) : ExtensionClient, HomeFeedClient, TrackClient, AlbumClient, ArtistClient, PlaylistClient, RadioClient, SearchClient, LibraryClient, @@ -109,7 +112,7 @@ class OfflineExtension(val context: Context) : ExtensionClient, HomeFeedClient, else -> run { val recentlyAdded = library.songList.sortedByDescending { it.mediaMetadata.extras!!.getLong("ModifiedDate") - }.map { it.toTrack().toMediaItem() } + }.map { it.toTrack() } val albums = library.albumList.map { it.toAlbum().toMediaItem() }.shuffled() @@ -117,21 +120,22 @@ class OfflineExtension(val context: Context) : ExtensionClient, HomeFeedClient, it.toArtist().toMediaItem() }.shuffled() listOf( - MediaItemsContainer.Category( + MediaItemsContainer.Tracks( context.getString(R.string.recently_added), - recentlyAdded.take(10), + recentlyAdded.take(6), + MediaItemsContainer.Tracks.Type.List, null, - PagedData.Single { recentlyAdded }), + PagedData.Single { recentlyAdded }.takeIf { albums.size > 6 }), MediaItemsContainer.Category( context.getString(R.string.albums), albums.take(10), null, - PagedData.Single { albums }), + PagedData.Single { albums }.takeIf { albums.size > 10 }), MediaItemsContainer.Category( context.getString(R.string.artists), artists.take(10), null, - PagedData.Single { artists }) + PagedData.Single { artists }.takeIf { albums.size > 10 }) ) + library.songList.map { it.toTrack().toMediaItem().toMediaItemsContainer() } @@ -202,73 +206,77 @@ class OfflineExtension(val context: Context) : ExtensionClient, HomeFeedClient, find(playlist)!!.toPlaylist() override fun loadTracks(playlist: Playlist): PagedData = PagedData.Single { - if (playlist.id.startsWith("radio_")) radioMap[playlist.id]!! - else find(playlist)!!.songList.map { it.toTrack() } + find(playlist)!!.songList.map { it.toTrack() } } override fun getMediaItems(playlist: Playlist) = PagedData.Single { emptyList() } - private val radioMap = mutableMapOf>() - private fun createRadioPlaylist(title: String, tracks: List): Playlist { - val id = "radio_${tracks.hashCode()}" - radioMap[id] = tracks - return Playlist( + private fun createRadioPlaylist(mediaItem: EchoMediaItem): Radio { + val id = "radio_${mediaItem.hashCode()}" + val title = mediaItem.title + return Radio( id = id, title = context.getString(R.string.item_radio, title), - cover = null, - isEditable = false, - authors = listOf(), - tracks = tracks.size, - creationDate = null, - subtitle = context.getString(R.string.radio_based_on_item, title) + extras = mapOf("mediaItem" to mediaItem.toJson()) ) } - override suspend fun radio(track: Track): Playlist { - val albumTracks = track.album?.let { loadTracks(loadAlbum(it)).loadAll() } - val artistTracks = track.artists.map { artist -> - find(artist)?.songList ?: emptyList() - }.flatten().map { it.toTrack() } - val randomTracks = library.songList.shuffled().take(25).map { it.toTrack() } - val allTracks = - listOfNotNull(albumTracks, artistTracks, randomTracks).flatten().distinctBy { it.id } - .toMutableList() - allTracks.removeIf { it.id == track.id } - allTracks.shuffle() - return createRadioPlaylist(track.title, allTracks) - } + override fun loadTracks(radio: Radio): PagedData = PagedData.Single { + val mediaItem = radio.extras["mediaItem"]!!.toData() + when (mediaItem) { + is EchoMediaItem.Lists.AlbumItem -> { + val album = mediaItem.album + val tracks = loadTracks(album).loadAll().asSequence() + .map { it.artists }.flatten() + .map { artist -> find(artist)?.songList?.map { it.toTrack() }!! }.flatten() + .filter { it.album?.id != album.id }.take(25) + + val randomTracks = library.songList.shuffled().take(25).map { it.toTrack() } + (tracks + randomTracks).distinctBy { it.id }.toMutableList() + } - override suspend fun radio(album: Album): Playlist { - val tracks = loadTracks(album).loadAll().asSequence() - .map { it.artists }.flatten() - .map { artist -> find(artist)?.songList?.map { it.toTrack() }!! }.flatten() - .filter { it.album?.id != album.id }.take(25) + is EchoMediaItem.Lists.PlaylistItem -> { + val playlist = mediaItem.playlist + val tracks = loadTracks(playlist).loadAll() + val randomTracks = library.songList.shuffled().take(25).map { it.toTrack() } + (tracks + randomTracks).distinctBy { it.id }.toMutableList() + } - val randomTracks = library.songList.shuffled().take(25).map { it.toTrack() } - val allTracks = (tracks + randomTracks).distinctBy { it.id }.toMutableList() - allTracks.shuffle() - return createRadioPlaylist(album.title, allTracks) - } + is EchoMediaItem.Profile.ArtistItem -> { + val artist = mediaItem.artist + val tracks = find(artist)?.songList?.map { it.toTrack() } ?: emptyList() + val randomTracks = library.songList.shuffled().take(25).map { it.toTrack() } + (tracks + randomTracks).distinctBy { it.id }.toMutableList() + } + + is EchoMediaItem.TrackItem -> { + val track = mediaItem.track + val albumTracks = track.album?.let { loadTracks(loadAlbum(it)).loadAll() } + val artistTracks = track.artists.map { artist -> + find(artist)?.songList ?: emptyList() + }.flatten().map { it.toTrack() } + val randomTracks = library.songList.shuffled().take(25).map { it.toTrack() } + val allTracks = + listOfNotNull(albumTracks, artistTracks, randomTracks).flatten() + .distinctBy { it.id } + .toMutableList() + allTracks.removeIf { it.id == track.id } + allTracks + } - override suspend fun radio(artist: Artist): Playlist { - val tracks = find(artist)?.songList?.map { it.toTrack() } ?: emptyList() - val randomTracks = library.songList.shuffled().take(25).map { it.toTrack() } - val allTracks = (tracks + randomTracks).distinctBy { it.id }.toMutableList() - allTracks.shuffle() - return createRadioPlaylist(artist.name, allTracks) + else -> throw IllegalAccessException() + }.shuffled() } - override suspend fun radio(user: User): Playlist = throw IllegalAccessException() + override suspend fun radio(track: Track, context: EchoMediaItem?) = + createRadioPlaylist(track.toMediaItem()) - override suspend fun radio(playlist: Playlist): Playlist { - val tracks = loadTracks(playlist).loadAll() - val randomTracks = library.songList.shuffled().take(25).map { it.toTrack() } - val allTracks = (tracks + randomTracks).distinctBy { it.id }.toMutableList() - allTracks.shuffle() - return createRadioPlaylist(playlist.title, allTracks) - } + override suspend fun radio(album: Album) = createRadioPlaylist(album.toMediaItem()) + override suspend fun radio(artist: Artist) = createRadioPlaylist(artist.toMediaItem()) + override suspend fun radio(playlist: Playlist) = createRadioPlaylist(playlist.toMediaItem()) + override suspend fun radio(user: User): Radio = throw IllegalAccessException() override suspend fun quickSearch(query: String?): List { return if (query.isNullOrBlank()) { diff --git a/app/src/main/java/dev/brahmkshatriya/echo/offline/TestExtension.kt b/app/src/main/java/dev/brahmkshatriya/echo/offline/TestExtension.kt index 94a3a603..dde9f200 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/offline/TestExtension.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/offline/TestExtension.kt @@ -9,9 +9,11 @@ import dev.brahmkshatriya.echo.common.clients.TrackClient import dev.brahmkshatriya.echo.common.helpers.PagedData import dev.brahmkshatriya.echo.common.models.Album import dev.brahmkshatriya.echo.common.models.Artist +import dev.brahmkshatriya.echo.common.models.EchoMediaItem import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Companion.toMediaItem import dev.brahmkshatriya.echo.common.models.MediaItemsContainer import dev.brahmkshatriya.echo.common.models.Playlist +import dev.brahmkshatriya.echo.common.models.Radio import dev.brahmkshatriya.echo.common.models.Streamable import dev.brahmkshatriya.echo.common.models.Streamable.Audio.Companion.toAudio import dev.brahmkshatriya.echo.common.models.Streamable.Media.Companion.toAudioVideoMedia @@ -120,12 +122,13 @@ class TestExtension : ExtensionClient, LoginClient.UsernamePassword, TrackClient ) } - private val emptyPlaylist = Playlist("empty", "empty", false) - override suspend fun radio(track: Track) = emptyPlaylist - override suspend fun radio(album: Album) = emptyPlaylist - override suspend fun radio(artist: Artist) = emptyPlaylist - override suspend fun radio(user: User) = emptyPlaylist - override suspend fun radio(playlist: Playlist) = emptyPlaylist + private val radio = Radio("empty", "empty") + override fun loadTracks(radio: Radio) = PagedData.Single { emptyList() } + override suspend fun radio(track: Track, context: EchoMediaItem?) = radio + override suspend fun radio(album: Album) = radio + override suspend fun radio(artist: Artist) = radio + override suspend fun radio(user: User) = radio + override suspend fun radio(playlist: Playlist) = radio override suspend fun getLibraryTabs() = emptyList() @@ -134,7 +137,7 @@ class TestExtension : ExtensionClient, LoginClient.UsernamePassword, TrackClient } override suspend fun listEditablePlaylists(): List { - return listOf(emptyPlaylist) + return listOf() } override suspend fun likeTrack(track: Track, liked: Boolean): Boolean { @@ -143,7 +146,7 @@ class TestExtension : ExtensionClient, LoginClient.UsernamePassword, TrackClient } override suspend fun createPlaylist(title: String, description: String?): Playlist { - return emptyPlaylist + return Playlist("", title, true) } override suspend fun deletePlaylist(playlist: Playlist) {} diff --git a/app/src/main/java/dev/brahmkshatriya/echo/playback/PlayerSessionCallback.kt b/app/src/main/java/dev/brahmkshatriya/echo/playback/PlayerSessionCallback.kt index d6dca93b..dd4fc969 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/playback/PlayerSessionCallback.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/playback/PlayerSessionCallback.kt @@ -98,12 +98,12 @@ class PlayerSessionCallback( val item = args.getSerialized("item") ?: return@future error radioFlow.value = Radio.State.Loading val loaded = Radio.start( - context, messageFlow, throwableFlow, extensionList, clientId, item, 0 + context, messageFlow, throwableFlow, extensionList, clientId, item, null, 0 ) radioFlow.value = loaded ?: Radio.State.Empty if (loaded == null) return@future error val mediaItem = MediaItemUtils.build( - settings, loaded.tracks[0], loaded.clientId, loaded.playlist.toMediaItem() + settings, loaded.tracks[0], loaded.clientId, loaded.radio.toMediaItem() ) player.setMediaItem(mediaItem) player.prepare() diff --git a/app/src/main/java/dev/brahmkshatriya/echo/playback/Radio.kt b/app/src/main/java/dev/brahmkshatriya/echo/playback/Radio.kt index db4775c0..32e9a248 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/playback/Radio.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/playback/Radio.kt @@ -12,7 +12,7 @@ import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Companion.toMediaItem import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Lists import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Profile import dev.brahmkshatriya.echo.common.models.EchoMediaItem.TrackItem -import dev.brahmkshatriya.echo.common.models.Playlist +import dev.brahmkshatriya.echo.common.models.Radio import dev.brahmkshatriya.echo.common.models.Track import dev.brahmkshatriya.echo.playback.MediaItemUtils.clientId import dev.brahmkshatriya.echo.playback.MediaItemUtils.context @@ -47,7 +47,7 @@ class Radio( data object Empty : State() data object Loading : State() data class Loaded( - val clientId: String, val playlist: Playlist, val tracks: List, val played: Int + val clientId: String, val radio: Radio, val tracks: List, val played: Int ) : State() } @@ -59,6 +59,7 @@ class Radio( extensionListFlow: StateFlow?>, clientId: String, item: EchoMediaItem, + itemContext: EchoMediaItem?, play: Int = -1 ): State.Loaded? { val list = extensionListFlow.first { it != null } @@ -78,28 +79,29 @@ class Radio( tryWith(throwableFlow, extension.info) { block() } } - val playlist = tryIO { + val radio = tryIO { when (item) { - is TrackItem -> client.radio(item.track) + is TrackItem -> client.radio(item.track, itemContext) is Lists.PlaylistItem -> client.radio(item.playlist) is Lists.AlbumItem -> client.radio(item.album) is Profile.ArtistItem -> client.radio(item.artist) is Profile.UserItem -> client.radio(item.user) + is Lists.RadioItem -> throw IllegalStateException("Radio inside radio") } } - if (playlist != null) { - val tracks = tryIO { client.loadTracks(playlist).loadFirst() } + if (radio != null) { + val tracks = tryIO { client.loadTracks(radio).loadFirst() } val state = if (!tracks.isNullOrEmpty()) State.Loaded( clientId, - playlist, + radio, tracks, play ) else { messageFlow.emit( SnackBar.Message( - context.getString(R.string.radio_playlist_empty) + context.getString(R.string.radio_empty) ) ) null @@ -115,7 +117,7 @@ class Radio( private fun play(loaded: State.Loaded, play: Int): Boolean { val track = loaded.tracks.getOrNull(play) ?: return false val item = MediaItemUtils.build( - settings, track, loaded.clientId, loaded.playlist.toMediaItem() + settings, track, loaded.clientId, loaded.radio.toMediaItem() ) player.addMediaItem(item) player.prepare() @@ -126,10 +128,12 @@ class Radio( private fun loadPlaylist() { val mediaItem = player.currentMediaItem ?: return val client = mediaItem.clientId - val item = mediaItem.context ?: mediaItem.track.toMediaItem() + val item = mediaItem.track.toMediaItem() + val itemContext = mediaItem.context stateFlow.value = State.Loading scope.launch { - val loaded = start(context, messageFlow, throwFlow, extensionList, client, item, 0) + val loaded = + start(context, messageFlow, throwFlow, extensionList, client, item, itemContext, 0) stateFlow.value = loaded ?: State.Empty if (loaded != null) play(loaded, 0) } diff --git a/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaClickListener.kt b/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaClickListener.kt index cf84b10a..c57fd973 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaClickListener.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaClickListener.kt @@ -8,6 +8,7 @@ import androidx.paging.map import dev.brahmkshatriya.echo.R import dev.brahmkshatriya.echo.common.clients.TrackClient import dev.brahmkshatriya.echo.common.models.EchoMediaItem +import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Companion.toMediaItem import dev.brahmkshatriya.echo.common.models.MediaItemsContainer import dev.brahmkshatriya.echo.common.models.MediaItemsContainer.Category import dev.brahmkshatriya.echo.common.models.MediaItemsContainer.Container @@ -97,6 +98,13 @@ class MediaClickListener( container.more?.toFlow(), transitionView ) + + is MediaItemsContainer.Tracks -> openContainer( + clientId, + container.title, + container.more?.toFlow()?.map { it.map { item -> item.toMediaItem().toMediaItemsContainer() } }, + transitionView + ) } } diff --git a/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaContainerAdapter.kt b/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaContainerAdapter.kt index 6921f186..156007d8 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaContainerAdapter.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaContainerAdapter.kt @@ -14,11 +14,12 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView.RecycledViewPool import dev.brahmkshatriya.echo.common.models.MediaItemsContainer import dev.brahmkshatriya.echo.plugger.ExtensionInfo -import dev.brahmkshatriya.echo.ui.editplaylist.SearchForPlaylistClickListener -import dev.brahmkshatriya.echo.ui.editplaylist.SearchForPlaylistFragment import dev.brahmkshatriya.echo.ui.adapter.MediaContainerViewHolder.Category import dev.brahmkshatriya.echo.ui.adapter.MediaContainerViewHolder.Container import dev.brahmkshatriya.echo.ui.adapter.MediaContainerViewHolder.Media +import dev.brahmkshatriya.echo.ui.adapter.MediaContainerViewHolder.MediaTracks +import dev.brahmkshatriya.echo.ui.editplaylist.SearchForPlaylistClickListener +import dev.brahmkshatriya.echo.ui.editplaylist.SearchForPlaylistFragment import java.lang.ref.WeakReference class MediaContainerAdapter( @@ -126,9 +127,6 @@ class MediaContainerAdapter( submitData(pagingData ?: PagingData.empty()) } - - // Binding - override fun onBindViewHolder(holder: MediaContainerViewHolder, position: Int) { val items = getItem(position) ?: return holder.transitionView.transitionName = (transition + items.id).hashCode().toString() @@ -149,6 +147,7 @@ class MediaContainerAdapter( is MediaItemsContainer.Category -> 0 is MediaItemsContainer.Container -> 1 is MediaItemsContainer.Item -> 2 + is MediaItemsContainer.Tracks -> 3 } } @@ -156,7 +155,8 @@ class MediaContainerAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) { 0 -> Category.create(parent, stateViewModel, sharedPool, extensionInfo.id, listener) 1 -> Container.create(parent) - else -> Media.create(parent, extensionInfo.id, listener) + 2 -> Media.create(parent, extensionInfo.id, listener) + 3 -> MediaTracks.create(parent, sharedPool, extensionInfo.id, listener) + else -> throw IllegalArgumentException("Unknown viewType: $viewType") } -} - +} \ No newline at end of file diff --git a/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaContainerViewHolder.kt b/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaContainerViewHolder.kt index 38233355..9029375b 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaContainerViewHolder.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaContainerViewHolder.kt @@ -5,14 +5,22 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible +import androidx.paging.PagingData import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dev.brahmkshatriya.echo.common.models.EchoMediaItem +import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Companion.toMediaItem import dev.brahmkshatriya.echo.common.models.MediaItemsContainer +import dev.brahmkshatriya.echo.common.models.Track import dev.brahmkshatriya.echo.databinding.NewItemCategoryBinding import dev.brahmkshatriya.echo.databinding.NewItemContainerBinding import dev.brahmkshatriya.echo.databinding.NewItemMediaBinding +import dev.brahmkshatriya.echo.databinding.NewItemTracksBinding import dev.brahmkshatriya.echo.ui.adapter.MediaItemViewHolder.Companion.bind +import dev.brahmkshatriya.echo.ui.item.TrackAdapter +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import java.lang.ref.WeakReference sealed class MediaContainerViewHolder( @@ -146,4 +154,63 @@ sealed class MediaContainerViewHolder( } } } + + class MediaTracks( + val binding: NewItemTracksBinding, + private val sharedPool: RecyclerView.RecycledViewPool, + private val clientId: String?, + val listener: MediaItemAdapter.Listener, + val scope: CoroutineScope, + ) : + MediaContainerViewHolder(binding.root) { + + private val trackListener = object : TrackAdapter.Listener { + override fun onClick(list: List, position: Int, view: View) { + listener.onClick(clientId, list[position].toMediaItem(), view) + } + + override fun onLongClick(list: List, position: Int, view: View): Boolean { + return listener.onLongClick(clientId, list[position].toMediaItem(), view) + } + } + + override fun bind(container: MediaItemsContainer) { + val tracks = container as MediaItemsContainer.Tracks + binding.title.text = tracks.title + binding.subtitle.text = tracks.subtitle + binding.subtitle.isVisible = tracks.subtitle.isNullOrBlank().not() + val adapter = TrackAdapter( + transitionView.transitionName + tracks.id, + trackListener + ) + binding.recyclerView.adapter = adapter + binding.recyclerView.setRecycledViewPool(sharedPool) + binding.more.isVisible = tracks.more != null + scope.launch { adapter.submit(PagingData.from(tracks.list.take(6))) } + } + + val layoutManager get() = binding.recyclerView.layoutManager + override val clickView: View = binding.more + override val transitionView: View = binding.titleCard + + companion object { + fun create( + parent: ViewGroup, + sharedPool: RecyclerView.RecycledViewPool, + clientId: String?, + listener: MediaItemAdapter.Listener, + ): MediaContainerViewHolder { + val layoutInflater = LayoutInflater.from(parent.context) + //TODO + val scope = CoroutineScope(Dispatchers.Main) + return MediaTracks( + NewItemTracksBinding.inflate(layoutInflater, parent, false), + sharedPool, + clientId, + listener, + scope + ) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaItemViewHolder.kt b/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaItemViewHolder.kt index e39d3102..d9c25a2c 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaItemViewHolder.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/ui/adapter/MediaItemViewHolder.kt @@ -101,6 +101,7 @@ sealed class MediaItemViewHolder(itemView: View) : is EchoMediaItem.Profile.UserItem -> R.drawable.art_user is EchoMediaItem.Lists.AlbumItem -> R.drawable.art_album is EchoMediaItem.Lists.PlaylistItem -> R.drawable.art_library_music + is EchoMediaItem.Lists.RadioItem -> R.drawable.art_sensors } fun EchoMediaItem.icon() = when (this) { @@ -109,6 +110,7 @@ sealed class MediaItemViewHolder(itemView: View) : is EchoMediaItem.Profile.UserItem -> R.drawable.ic_person is EchoMediaItem.Lists.AlbumItem -> R.drawable.ic_album is EchoMediaItem.Lists.PlaylistItem -> R.drawable.ic_library_music + is EchoMediaItem.Lists.RadioItem -> R.drawable.ic_sensors } fun NewItemMediaTitleBinding.bind(item: EchoMediaItem) { diff --git a/app/src/main/java/dev/brahmkshatriya/echo/ui/editplaylist/SearchForPlaylistClickListener.kt b/app/src/main/java/dev/brahmkshatriya/echo/ui/editplaylist/SearchForPlaylistClickListener.kt index f0f511cd..6c323d6b 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/ui/editplaylist/SearchForPlaylistClickListener.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/ui/editplaylist/SearchForPlaylistClickListener.kt @@ -7,16 +7,17 @@ import androidx.paging.PagingData import androidx.paging.map import dev.brahmkshatriya.echo.R import dev.brahmkshatriya.echo.common.models.EchoMediaItem +import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Companion.toMediaItem import dev.brahmkshatriya.echo.common.models.MediaItemsContainer import dev.brahmkshatriya.echo.common.models.MediaItemsContainer.Category import dev.brahmkshatriya.echo.common.models.MediaItemsContainer.Container import dev.brahmkshatriya.echo.common.models.MediaItemsContainer.Item +import dev.brahmkshatriya.echo.ui.adapter.MediaContainerAdapter +import dev.brahmkshatriya.echo.ui.adapter.MediaItemAdapter import dev.brahmkshatriya.echo.ui.common.openFragment import dev.brahmkshatriya.echo.ui.container.ContainerFragment import dev.brahmkshatriya.echo.ui.container.ContainerViewModel import dev.brahmkshatriya.echo.ui.item.ItemFragment -import dev.brahmkshatriya.echo.ui.adapter.MediaContainerAdapter -import dev.brahmkshatriya.echo.ui.adapter.MediaItemAdapter import dev.brahmkshatriya.echo.ui.paging.toFlow import dev.brahmkshatriya.echo.viewmodels.ExtensionViewModel.Companion.noClient import dev.brahmkshatriya.echo.viewmodels.SnackBar.Companion.createSnack @@ -83,6 +84,13 @@ class SearchForPlaylistClickListener( container.more?.toFlow(), transitionView ) + + is MediaItemsContainer.Tracks -> openContainer( + clientId, + container.title, + container.more?.toFlow()?.map { it.map { item -> item.toMediaItem().toMediaItemsContainer() } }, + transitionView + ) } } diff --git a/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemBottomSheet.kt b/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemBottomSheet.kt index e8e72a11..97a1e5b8 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemBottomSheet.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemBottomSheet.kt @@ -146,7 +146,7 @@ class ItemBottomSheet : BottomSheetDialogFragment() { } else null, if (client is RadioClient) - ItemAction.Resource(R.drawable.ic_radio, R.string.radio) { + ItemAction.Resource(R.drawable.ic_sensors, R.string.radio) { playerViewModel.radio(clientId, item) } else null, @@ -160,7 +160,7 @@ class ItemBottomSheet : BottomSheetDialogFragment() { is EchoMediaItem.Lists.PlaylistItem -> { listOfNotNull( if (client is RadioClient) - ItemAction.Resource(R.drawable.ic_radio, R.string.radio) { + ItemAction.Resource(R.drawable.ic_sensors, R.string.radio) { playerViewModel.radio(clientId, item) } else null, @@ -183,13 +183,15 @@ class ItemBottomSheet : BottomSheetDialogFragment() { } } } + + is EchoMediaItem.Lists.RadioItem -> listOf() } } is EchoMediaItem.Profile -> { if (item is EchoMediaItem.Profile.ArtistItem) listOfNotNull( if (client is RadioClient) - ItemAction.Resource(R.drawable.ic_radio, R.string.radio) { + ItemAction.Resource(R.drawable.ic_sensors, R.string.radio) { playerViewModel.radio(clientId, item) } else null, @@ -242,7 +244,7 @@ class ItemBottomSheet : BottomSheetDialogFragment() { } else null, if (client is RadioClient) - ItemAction.Resource(R.drawable.ic_radio, R.string.radio) { + ItemAction.Resource(R.drawable.ic_sensors, R.string.radio) { playerViewModel.radio(clientId, item) } else null, diff --git a/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemFragment.kt b/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemFragment.kt index 65be8828..b3a55a15 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemFragment.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemFragment.kt @@ -195,6 +195,8 @@ class ItemFragment : Fragment() { is PlaylistItem -> ConcatAdapter(playlistHeaderAdapter, trackAdapter, itemsAdapter) + is EchoMediaItem.Lists.RadioItem -> ConcatAdapter(trackAdapter) + is ArtistItem -> ConcatAdapter(artistHeaderAdapter, itemsAdapter) else -> itemsAdapter } @@ -247,6 +249,10 @@ class ItemFragment : Fragment() { loadPlaylistTracks(it.playlist) } + is EchoMediaItem.Lists.RadioItem -> { + loadRadioTracks(it.radio) + } + is ArtistItem -> artistHeaderAdapter.submit(it.artist, isFollowClient, isRadioClient) @@ -300,6 +306,9 @@ class ItemFragment : Fragment() { is PlaylistItem -> applyAdapter(extension, R.string.playlist, adapter) + + is EchoMediaItem.Lists.RadioItem -> + applyAdapter(extension, R.string.radio, adapter) } } } diff --git a/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemViewModel.kt b/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemViewModel.kt index ca614c7c..57ec242f 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemViewModel.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/ui/item/ItemViewModel.kt @@ -8,6 +8,7 @@ import dev.brahmkshatriya.echo.common.clients.AlbumClient import dev.brahmkshatriya.echo.common.clients.ArtistClient import dev.brahmkshatriya.echo.common.clients.ArtistFollowClient import dev.brahmkshatriya.echo.common.clients.PlaylistClient +import dev.brahmkshatriya.echo.common.clients.RadioClient import dev.brahmkshatriya.echo.common.clients.TrackClient import dev.brahmkshatriya.echo.common.clients.UserClient import dev.brahmkshatriya.echo.common.helpers.PagedData @@ -17,6 +18,7 @@ import dev.brahmkshatriya.echo.common.models.EchoMediaItem import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Companion.toMediaItem import dev.brahmkshatriya.echo.common.models.MediaItemsContainer import dev.brahmkshatriya.echo.common.models.Playlist +import dev.brahmkshatriya.echo.common.models.Radio import dev.brahmkshatriya.echo.common.models.Track import dev.brahmkshatriya.echo.plugger.ExtensionInfo import dev.brahmkshatriya.echo.plugger.GenericExtension @@ -68,6 +70,10 @@ class ItemViewModel @Inject constructor( is EchoMediaItem.TrackItem -> getClient { load(it, item.track, ::loadTrack, ::getMediaItems)?.toMediaItem() } + + is EchoMediaItem.Lists.RadioItem -> getClient { + load(it, item.radio, null, null)?.toMediaItem() + } } itemFlow.value = mediaItem } @@ -87,12 +93,12 @@ class ItemViewModel @Inject constructor( private suspend fun load( info: ExtensionInfo, item: T, - loadItem: suspend (T) -> T, - loadRelated: (T) -> PagedData + loadItem: (suspend (T) -> T)?, + loadRelated: ((T) -> PagedData)? ): T? { return tryWith(info) { - val loaded = loadItem(item) - if(loadRelatedFeed) viewModelScope.launch { + val loaded = loadItem?.let { it(item) } ?: item + if (loadRelatedFeed && loadRelated != null) viewModelScope.launch { tryWith(info) { loadRelated(loaded).toFlow().map { it } }?.collectTo(relatedFeed) @@ -124,6 +130,16 @@ class ItemViewModel @Inject constructor( } } + fun loadRadioTracks(radio: Radio) { + viewModelScope.launch(Dispatchers.IO) { + getClient { + songsFlow.value = null + val tracks = tryWith(it) { loadTracks(radio) } + tracks?.toFlow()?.collectTo(songsFlow) + } + } + } + fun subscribe(artist: Artist, subscribe: Boolean) { viewModelScope.launch(Dispatchers.IO) { getClient { diff --git a/app/src/main/java/dev/brahmkshatriya/echo/viewmodels/PlayerViewModel.kt b/app/src/main/java/dev/brahmkshatriya/echo/viewmodels/PlayerViewModel.kt index b038c061..26603c3b 100644 --- a/app/src/main/java/dev/brahmkshatriya/echo/viewmodels/PlayerViewModel.kt +++ b/app/src/main/java/dev/brahmkshatriya/echo/viewmodels/PlayerViewModel.kt @@ -134,6 +134,10 @@ class PlayerViewModel @Inject constructor( } else null } + + is EchoMediaItem.Lists.RadioItem -> { + TODO() + } } } @@ -206,7 +210,7 @@ class PlayerViewModel @Inject constructor( val index = played + subIndex + 1 val trackList = tracks.take(index + 1).drop(played + 1).ifEmpty { null } ?: return radioStateFlow.value = state.copy(played = index) - addToQueue(clientId, playlist.toMediaItem(), trackList, true) + addToQueue(clientId, radio.toMediaItem(), trackList, true) withBrowser { play(it.mediaItemCount - 1) } } } @@ -266,13 +270,7 @@ class PlayerViewModel @Inject constructor( val shareLink = MutableSharedFlow() fun onShare(client: ShareClient, item: EchoMediaItem) { viewModelScope.launch(Dispatchers.IO) { - val link = when (item) { - is EchoMediaItem.Lists.AlbumItem -> client.onShare(item.album) - is EchoMediaItem.Lists.PlaylistItem -> client.onShare(item.playlist) - is EchoMediaItem.Profile.ArtistItem -> client.onShare(item.artist) - is EchoMediaItem.Profile.UserItem -> client.onShare(item.user) - is EchoMediaItem.TrackItem -> client.onShare(item.track) - } + val link = client.onShare(item) shareLink.emit(link) } } diff --git a/app/src/main/res/drawable/art_sensors.xml b/app/src/main/res/drawable/art_sensors.xml new file mode 100644 index 00000000..2648755f --- /dev/null +++ b/app/src/main/res/drawable/art_sensors.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_radio.xml b/app/src/main/res/drawable/ic_radio.xml deleted file mode 100644 index 82b1a9e7..00000000 --- a/app/src/main/res/drawable/ic_radio.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_sensors.xml b/app/src/main/res/drawable/ic_sensors.xml new file mode 100644 index 00000000..c0d4e93e --- /dev/null +++ b/app/src/main/res/drawable/ic_sensors.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/item_album_info.xml b/app/src/main/res/layout/item_album_info.xml index 8177ed54..45ea2240 100644 --- a/app/src/main/res/layout/item_album_info.xml +++ b/app/src/main/res/layout/item_album_info.xml @@ -42,7 +42,7 @@ android:text="@string/radio" android:layout_marginHorizontal="8dp" android:textColor="@color/button_radio" - app:icon="@drawable/ic_radio" + app:icon="@drawable/ic_sensors" app:iconTint="@color/button_radio" /> diff --git a/app/src/main/res/layout/item_dialog_button_loading.xml b/app/src/main/res/layout/item_dialog_button_loading.xml index 7309502c..0b6ab82e 100644 --- a/app/src/main/res/layout/item_dialog_button_loading.xml +++ b/app/src/main/res/layout/item_dialog_button_loading.xml @@ -4,7 +4,7 @@ android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" - android:padding="8dp"> + android:padding="24dp"> + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b537c58b..5105e083 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -186,7 +186,7 @@ %1$s (Disabled) Enabled Disabled - Radio Playlist is Empty + Radio is Empty Gradient Navbar Navbar gradually becomes transparent Value diff --git a/common/src/main/java/dev/brahmkshatriya/echo/common/clients/RadioClient.kt b/common/src/main/java/dev/brahmkshatriya/echo/common/clients/RadioClient.kt index 14d26947..8759c5fc 100644 --- a/common/src/main/java/dev/brahmkshatriya/echo/common/clients/RadioClient.kt +++ b/common/src/main/java/dev/brahmkshatriya/echo/common/clients/RadioClient.kt @@ -1,15 +1,19 @@ package dev.brahmkshatriya.echo.common.clients +import dev.brahmkshatriya.echo.common.helpers.PagedData import dev.brahmkshatriya.echo.common.models.Album import dev.brahmkshatriya.echo.common.models.Artist +import dev.brahmkshatriya.echo.common.models.EchoMediaItem import dev.brahmkshatriya.echo.common.models.Playlist +import dev.brahmkshatriya.echo.common.models.Radio import dev.brahmkshatriya.echo.common.models.Track import dev.brahmkshatriya.echo.common.models.User -interface RadioClient : PlaylistClient { - suspend fun radio(track: Track): Playlist - suspend fun radio(album: Album): Playlist - suspend fun radio(artist: Artist): Playlist - suspend fun radio(user: User) : Playlist - suspend fun radio(playlist: Playlist): Playlist +interface RadioClient { + fun loadTracks(radio: Radio): PagedData + suspend fun radio(track: Track, context: EchoMediaItem?): Radio + suspend fun radio(album: Album): Radio + suspend fun radio(artist: Artist): Radio + suspend fun radio(user: User): Radio + suspend fun radio(playlist: Playlist): Radio } \ No newline at end of file diff --git a/common/src/main/java/dev/brahmkshatriya/echo/common/clients/SaveToLibraryClient.kt b/common/src/main/java/dev/brahmkshatriya/echo/common/clients/SaveToLibraryClient.kt new file mode 100644 index 00000000..db7c5c6d --- /dev/null +++ b/common/src/main/java/dev/brahmkshatriya/echo/common/clients/SaveToLibraryClient.kt @@ -0,0 +1,9 @@ +package dev.brahmkshatriya.echo.common.clients + +import dev.brahmkshatriya.echo.common.models.EchoMediaItem + +interface SaveToLibraryClient { + suspend fun saveToLibrary(mediaItem: EchoMediaItem) + suspend fun removeFromLibrary(mediaItem: EchoMediaItem) + suspend fun isSavedToLibrary(mediaItem: EchoMediaItem) +} \ No newline at end of file diff --git a/common/src/main/java/dev/brahmkshatriya/echo/common/clients/ShareClient.kt b/common/src/main/java/dev/brahmkshatriya/echo/common/clients/ShareClient.kt index 8891ad27..2e2a6d39 100644 --- a/common/src/main/java/dev/brahmkshatriya/echo/common/clients/ShareClient.kt +++ b/common/src/main/java/dev/brahmkshatriya/echo/common/clients/ShareClient.kt @@ -1,15 +1,7 @@ package dev.brahmkshatriya.echo.common.clients -import dev.brahmkshatriya.echo.common.models.Album -import dev.brahmkshatriya.echo.common.models.Artist -import dev.brahmkshatriya.echo.common.models.Playlist -import dev.brahmkshatriya.echo.common.models.Track -import dev.brahmkshatriya.echo.common.models.User +import dev.brahmkshatriya.echo.common.models.EchoMediaItem interface ShareClient { - suspend fun onShare(artist: Artist): String - suspend fun onShare(track: Track): String - suspend fun onShare(album: Album): String - suspend fun onShare(playlist: Playlist): String - suspend fun onShare(user: User): String + suspend fun onShare(item: EchoMediaItem): String } \ No newline at end of file diff --git a/common/src/main/java/dev/brahmkshatriya/echo/common/models/EchoMediaItem.kt b/common/src/main/java/dev/brahmkshatriya/echo/common/models/EchoMediaItem.kt index 01597f51..a2fd7eb5 100644 --- a/common/src/main/java/dev/brahmkshatriya/echo/common/models/EchoMediaItem.kt +++ b/common/src/main/java/dev/brahmkshatriya/echo/common/models/EchoMediaItem.kt @@ -26,11 +26,14 @@ sealed class EchoMediaItem { data class AlbumItem(val album: Album) : Lists() @Serializable data class PlaylistItem(val playlist: Playlist) : Lists() + @Serializable + data class RadioItem(val radio: Radio) : Lists() val size get() = when (this) { is AlbumItem -> album.tracks is PlaylistItem -> playlist.tracks + is RadioItem -> 0 } } @@ -40,6 +43,7 @@ sealed class EchoMediaItem { fun Artist.toMediaItem() = Profile.ArtistItem(this) fun User.toMediaItem() = Profile.UserItem(this) fun Playlist.toMediaItem() = Lists.PlaylistItem(this) + fun Radio.toMediaItem() = Lists.RadioItem(this) } fun toMediaItemsContainer() = MediaItemsContainer.Item( @@ -49,6 +53,7 @@ sealed class EchoMediaItem { is Profile.UserItem -> user.toMediaItem() is Lists.AlbumItem -> album.toMediaItem() is Lists.PlaylistItem -> playlist.toMediaItem() + is Lists.RadioItem -> radio.toMediaItem() } ) @@ -58,6 +63,7 @@ sealed class EchoMediaItem { is Profile.UserItem -> other is Profile.UserItem && user.id == other.user.id is Lists.AlbumItem -> other is Lists.AlbumItem && album.id == other.album.id is Lists.PlaylistItem -> other is Lists.PlaylistItem && playlist.id == other.playlist.id + is Lists.RadioItem -> other is Lists.RadioItem && radio.id == other.radio.id } val id @@ -67,6 +73,7 @@ sealed class EchoMediaItem { is Profile.UserItem -> user.id is Lists.AlbumItem -> album.id is Lists.PlaylistItem -> playlist.id + is Lists.RadioItem -> radio.id } val title @@ -76,6 +83,7 @@ sealed class EchoMediaItem { is Profile.UserItem -> user.name is Lists.AlbumItem -> album.title is Lists.PlaylistItem -> playlist.title + is Lists.RadioItem -> radio.title } val cover @@ -85,6 +93,7 @@ sealed class EchoMediaItem { is Profile.UserItem -> user.cover is Lists.AlbumItem -> album.cover is Lists.PlaylistItem -> playlist.cover + is Lists.RadioItem -> radio.cover } val subtitle @@ -94,5 +103,6 @@ sealed class EchoMediaItem { is Profile.UserItem -> null is Lists.AlbumItem -> album.subtitle ?: album.artists.joinToString(", ") { it.name } is Lists.PlaylistItem -> playlist.subtitle + is Lists.RadioItem -> null } } \ No newline at end of file diff --git a/common/src/main/java/dev/brahmkshatriya/echo/common/models/MediaItemsContainer.kt b/common/src/main/java/dev/brahmkshatriya/echo/common/models/MediaItemsContainer.kt index 85e0be93..ff44aaab 100644 --- a/common/src/main/java/dev/brahmkshatriya/echo/common/models/MediaItemsContainer.kt +++ b/common/src/main/java/dev/brahmkshatriya/echo/common/models/MediaItemsContainer.kt @@ -11,6 +11,19 @@ sealed class MediaItemsContainer { val more: PagedData? = null ) : MediaItemsContainer() + data class Tracks( + val title: String, + val list: List, + val type: Type, + val subtitle: String? = null, + val more: PagedData? = null + ) : MediaItemsContainer() { + //TODO + enum class Type { + List, Grid + } + } + data class Item( val media: EchoMediaItem ) : MediaItemsContainer() @@ -26,6 +39,7 @@ sealed class MediaItemsContainer { is Category -> other is Category && this.id == other.id is Item -> other is Item && media.sameAs(other.media) is Container -> other is Container && this.id == other.id + is Tracks -> other is Tracks && this.id == other.id } val id diff --git a/common/src/main/java/dev/brahmkshatriya/echo/common/models/Radio.kt b/common/src/main/java/dev/brahmkshatriya/echo/common/models/Radio.kt new file mode 100644 index 00000000..9b4ebd6e --- /dev/null +++ b/common/src/main/java/dev/brahmkshatriya/echo/common/models/Radio.kt @@ -0,0 +1,12 @@ +package dev.brahmkshatriya.echo.common.models + +import kotlinx.serialization.Serializable + +@Serializable +data class Radio( + val id: String, + val title: String, + val cover: ImageHolder? = null, + val tabs: List = listOf(), + val extras: Map = mapOf() +) \ No newline at end of file diff --git a/common/src/main/java/dev/brahmkshatriya/echo/common/models/Tab.kt b/common/src/main/java/dev/brahmkshatriya/echo/common/models/Tab.kt index 90bb170c..363c8c77 100644 --- a/common/src/main/java/dev/brahmkshatriya/echo/common/models/Tab.kt +++ b/common/src/main/java/dev/brahmkshatriya/echo/common/models/Tab.kt @@ -1,5 +1,8 @@ package dev.brahmkshatriya.echo.common.models +import kotlinx.serialization.Serializable + +@Serializable data class Tab ( val id: String, val name: String, diff --git a/common/src/main/java/dev/brahmkshatriya/echo/common/providers/ContextProvider.kt b/common/src/main/java/dev/brahmkshatriya/echo/common/providers/ContextProvider.kt deleted file mode 100644 index 6c1b9c1f..00000000 --- a/common/src/main/java/dev/brahmkshatriya/echo/common/providers/ContextProvider.kt +++ /dev/null @@ -1,7 +0,0 @@ -package dev.brahmkshatriya.echo.common.providers -// -//import android.content.Context -// -//interface ContextProvider { -// fun setContext(context: Context) -//} \ No newline at end of file