Created Karaoke module: UI and backend
Integrated karaoke listing api and data caching Integrated Continue Karaoke api and data caching Data syncing with adapters and MyListFragment Dialog showing for karaoke. Implemented Media3 Player view for KaraokePlayerActivity Custom Player controller view - adding close button and title and hiding full screen and settings icon Player setup, hiding user controller view
This commit is contained in:
@@ -15,13 +15,25 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Woka"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".karaoke.player.KaraokePlayerActivity"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||
android:exported="false"
|
||||
android:launchMode="singleTask"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:screenOrientation="portrait"
|
||||
/>
|
||||
<activity
|
||||
android:name=".karaoke.views.KaraokeActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait"/>
|
||||
<activity
|
||||
android:name=".wokagames.playerr.GamePlayerActivity"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||
android:exported="false"
|
||||
android:launchMode="singleTask"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:theme="@style/FullScreenTheme"/>
|
||||
android:theme="@style/FullScreenTheme" />
|
||||
<activity
|
||||
android:name=".wokagames.views.GamesActivity"
|
||||
android:exported="false"
|
||||
|
||||
@@ -78,7 +78,7 @@ object AudioBookRepository {
|
||||
val response = handleApiCall {
|
||||
userActionApiService.continueAudioBookListing(
|
||||
FormBody.Builder()
|
||||
.add("post_type", "7")
|
||||
.add("post_type", PostType.AUDIO_BOOKS.value)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,9 +19,8 @@ import com.woka.utils.toast
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class ContinueAudioAdapter(private val context: Context,
|
||||
config: AsyncDifferConfig<ContinueAudioData>,
|
||||
private var onBookClicked: (ContinueAudioData) -> Unit,
|
||||
private var onContinueBookChanged: (id: Int) -> Unit): ListAdapter<ContinueAudioData, FavoriteViewHolder>(config) {
|
||||
private var onContinueBookChanged: (id: Int) -> Unit): ListAdapter<ContinueAudioData, FavoriteViewHolder>(DIFF_CONFIG) {
|
||||
|
||||
companion object{
|
||||
private val DIFF_UTIL = object : DiffUtil.ItemCallback<ContinueAudioData>(){
|
||||
@@ -39,10 +38,6 @@ class ContinueAudioAdapter(private val context: Context,
|
||||
.build()
|
||||
}
|
||||
|
||||
constructor(context: Context,
|
||||
onBookClicked: (ContinueAudioData) -> Unit,
|
||||
onContinueBookChanged: (id: Int) -> Unit): this(context, DIFF_CONFIG, onBookClicked, onContinueBookChanged)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteViewHolder {
|
||||
return FavoriteViewHolder(
|
||||
FavViewHolderBinding.inflate(
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.woka.home.views.FMActivity
|
||||
import com.woka.home.viewmodels.HomeViewModel
|
||||
import com.woka.home.views.MoreHomeActivity
|
||||
import com.woka.home.models.TimePeriod
|
||||
import com.woka.karaoke.views.KaraokeActivity
|
||||
import com.woka.userdata.userDataModels.UserDataResponse
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.views.LiveStreamPlayerActivity
|
||||
@@ -193,6 +194,12 @@ class Home1Fragment : Fragment(), Listener {
|
||||
startActivity(Intent(it, GamesActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
karaoke.setOnClickListener {
|
||||
activity?.let {
|
||||
startActivity(Intent(it, KaraokeActivity::class.java))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,15 @@ import com.woka.databinding.FragmentMyListBinding
|
||||
import com.woka.home.mylist.MyListRepository
|
||||
import com.woka.home.mylist.adapters.FavAudioAdapter
|
||||
import com.woka.home.mylist.adapters.FavGamesAdapter
|
||||
import com.woka.home.mylist.adapters.KaraokeAdapter
|
||||
import com.woka.home.mylist.adapters.FavKaraokeAdapter
|
||||
import com.woka.home.mylist.adapters.WebSeriesAdapter
|
||||
import com.woka.home.mylist.models.PostType
|
||||
import com.woka.home.mylist.models.BookmarkedShowData
|
||||
import com.woka.home.mylist.models.FavAudioBookData
|
||||
import com.woka.home.mylist.models.FavGameData
|
||||
import com.woka.home.mylist.models.FavKaraokeData
|
||||
import com.woka.karaoke.KaraokeRepository
|
||||
import com.woka.karaoke.models.listing.KaraokeData
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.players.models.VideoPlayList
|
||||
import com.woka.players.views.PlayerActivity
|
||||
@@ -59,7 +62,7 @@ class MyListFragment : Fragment() {
|
||||
private lateinit var webSeriesEAdapter: WebSeriesAdapter
|
||||
private lateinit var webSeriesHAdapter: WebSeriesAdapter
|
||||
private lateinit var audioBooksAdapter: FavAudioAdapter
|
||||
private lateinit var karaokeAdapter: KaraokeAdapter
|
||||
private lateinit var karaokeAdapter: FavKaraokeAdapter
|
||||
private lateinit var gamesAdapter: FavGamesAdapter
|
||||
|
||||
private var webShowIntentLauncher: ActivityResultLauncher<Intent>? = null
|
||||
@@ -77,7 +80,7 @@ class MyListFragment : Fragment() {
|
||||
webSeriesEAdapter = WebSeriesAdapter(requireContext(),"1", ::onListGotEmpty)
|
||||
webSeriesHAdapter = WebSeriesAdapter(requireContext(),"18", ::onListGotEmpty)
|
||||
audioBooksAdapter = FavAudioAdapter(requireContext(), ::onListGotEmpty, ::onAudioBookClicked)
|
||||
karaokeAdapter = KaraokeAdapter(requireContext(), ::onListGotEmpty)
|
||||
karaokeAdapter = FavKaraokeAdapter(requireContext(), ::onListGotEmpty, ::onKaraokeClicked)
|
||||
gamesAdapter = FavGamesAdapter(requireContext(), ::onListGotEmpty, ::onGameClicked)
|
||||
|
||||
// dialogs
|
||||
@@ -606,6 +609,128 @@ class MyListFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
// karaoke
|
||||
private fun onKaraokeClicked(karaokeData: FavKaraokeData, position: Int) {
|
||||
dialogBinding.apply {
|
||||
karaokeData.content_more_details?.let { moreDetailsList ->
|
||||
|
||||
karaokeData.thumbnail_path?.let {
|
||||
image.loadImage(it)
|
||||
}
|
||||
|
||||
fav.isSelected = karaokeData.mark_as_favourite == true
|
||||
like.isSelected = karaokeData.is_liked == true
|
||||
likeCount.text = "${karaokeData.likes_count}"
|
||||
|
||||
year.text = try {
|
||||
karaokeData.release_date?.let {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.time =
|
||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).parse(
|
||||
karaokeData.release_date
|
||||
)!!
|
||||
"${cal.get(Calendar.YEAR)}"
|
||||
} ?: throw Exception()
|
||||
} catch (e: Exception) {
|
||||
"${karaokeData.release_date}"
|
||||
}
|
||||
|
||||
if (moreDetailsList.isNotEmpty()) {
|
||||
|
||||
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) {
|
||||
moreDetailsList[1]?.let { data ->
|
||||
title.text = data.title
|
||||
description.text = Html.fromHtml(
|
||||
data.description?.replace(
|
||||
"<br>",
|
||||
" "
|
||||
), Html.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
}
|
||||
} else {
|
||||
moreDetailsList[0]?.let { data ->
|
||||
title.text = data.title
|
||||
description.text = Html.fromHtml(
|
||||
data.description?.replace(
|
||||
"<br>",
|
||||
" "
|
||||
), Html.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
title.text = karaokeData.title
|
||||
description.text = Html.fromHtml(
|
||||
karaokeData.description?.replace(
|
||||
"<br>",
|
||||
" "
|
||||
), Html.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
}
|
||||
|
||||
activity?.let {
|
||||
watchCard.backgroundTintList = ColorStateList.valueOf(it.getColor(R.color.game_grad_one))
|
||||
}
|
||||
watchCard.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_mic, 0, 0, 0)
|
||||
watchCard.text = getString(R.string.sing_now)
|
||||
watchCard.setOnClickListener {
|
||||
|
||||
}
|
||||
|
||||
like.setOnClickListener {
|
||||
KaraokeRepository.likeUnLikeSong(
|
||||
"${karaokeData.id}",
|
||||
!like.isSelected
|
||||
)
|
||||
|
||||
karaokeData.id?.let {
|
||||
onKaraokeChanged(it)
|
||||
}
|
||||
like.isSelected = !like.isSelected
|
||||
likeCount.text = "${karaokeData.likes_count}"
|
||||
}
|
||||
|
||||
fav.setOnClickListener {
|
||||
if (context?.isNetworkConnected() == false){
|
||||
toast(getString(R.string.no_internet))
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
KaraokeRepository.updateFavShow(
|
||||
KaraokeData(karaokeData),
|
||||
!fav.isSelected
|
||||
)
|
||||
|
||||
try {
|
||||
karaokeAdapter.notifyItemRemoved(position)
|
||||
} catch (e: Exception) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
if (karaokeAdapter.currentList.isEmpty()){
|
||||
onListGotEmpty(PostType.KARAOKE, true)
|
||||
}
|
||||
|
||||
moduleShowerDialog.dismiss()
|
||||
}
|
||||
|
||||
close.setOnClickListener {
|
||||
moduleShowerDialog.dismiss()
|
||||
}
|
||||
|
||||
moduleShowerDialog.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onKaraokeChanged(id: Int) {
|
||||
// updating continue book list
|
||||
val position = karaokeAdapter.currentList.indexOfFirst { it.id == id }
|
||||
if (position >= 0 && position < karaokeAdapter.currentList.size) {
|
||||
karaokeAdapter.notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance() = MyListFragment()
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
package com.woka.home.mylist.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import com.bumptech.glide.Glide
|
||||
import com.woka.R
|
||||
import com.woka.databinding.FavViewHolderBinding
|
||||
import com.woka.home.mylist.MyListRepository
|
||||
import com.woka.home.mylist.models.FavKaraokeData
|
||||
import com.woka.home.mylist.models.PostType
|
||||
import com.woka.home.mylist.models.SingKaraokeData
|
||||
import com.woka.utils.TAG
|
||||
import com.woka.karaoke.KaraokeRepository
|
||||
import com.woka.karaoke.models.listing.KaraokeData
|
||||
import com.woka.utils.isNetworkConnected
|
||||
import com.woka.utils.toast
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.math.max
|
||||
|
||||
class KaraokeAdapter(private val context: Context,
|
||||
config: AsyncDifferConfig<SingKaraokeData>,
|
||||
private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit)): ListAdapter<SingKaraokeData, FavoriteViewHolder>(config) {
|
||||
class FavKaraokeAdapter(private val context: Context,
|
||||
private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit),
|
||||
private var onKaraokeClicked: (FavKaraokeData, Int) -> Unit)
|
||||
: ListAdapter<FavKaraokeData, FavoriteViewHolder>(DIFF_CONFIG) {
|
||||
|
||||
companion object{
|
||||
private val DIFF_UTIL = object : DiffUtil.ItemCallback<SingKaraokeData>(){
|
||||
override fun areItemsTheSame(oldItem: SingKaraokeData, newItem: SingKaraokeData): Boolean = oldItem.id == newItem.id
|
||||
override fun areContentsTheSame(oldItem: SingKaraokeData, newItem: SingKaraokeData): Boolean {
|
||||
return oldItem.title == newItem.title &&
|
||||
private val DIFF_UTIL = object : DiffUtil.ItemCallback<FavKaraokeData>(){
|
||||
override fun areItemsTheSame(oldItem: FavKaraokeData, newItem: FavKaraokeData): Boolean = oldItem.id == newItem.id
|
||||
override fun areContentsTheSame(oldItem: FavKaraokeData, newItem: FavKaraokeData): Boolean {
|
||||
return oldItem.thumbnail_path == newItem.thumbnail_path &&
|
||||
oldItem.title == newItem.title &&
|
||||
oldItem.is_liked == newItem.is_liked &&
|
||||
oldItem.mark_as_favourite == newItem.mark_as_favourite &&
|
||||
oldItem.likes_count == newItem.likes_count
|
||||
}
|
||||
}
|
||||
@@ -38,8 +38,6 @@ class KaraokeAdapter(private val context: Context,
|
||||
.build()
|
||||
}
|
||||
|
||||
constructor(context: Context, onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit)): this(context, DIFF_CONFIG, onListEmptyListener)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteViewHolder {
|
||||
return FavoriteViewHolder(
|
||||
FavViewHolderBinding.inflate(
|
||||
@@ -74,7 +72,13 @@ class KaraokeAdapter(private val context: Context,
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
KaraokeRepository.likeUnLikeSong(
|
||||
"${karaokeData.id}",
|
||||
!like.isSelected
|
||||
)
|
||||
|
||||
like.isSelected = !like.isSelected
|
||||
likeCount.text = "${karaokeData.likes_count}"
|
||||
}
|
||||
|
||||
fav.isSelected = true
|
||||
@@ -85,6 +89,20 @@ class KaraokeAdapter(private val context: Context,
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
KaraokeRepository.updateFavShow(
|
||||
KaraokeData(karaokeData),
|
||||
!fav.isSelected
|
||||
)
|
||||
|
||||
notifyItemRemoved(holder.absoluteAdapterPosition)
|
||||
|
||||
if (currentList.isEmpty()){
|
||||
onListEmptyListener(PostType.KARAOKE, true)
|
||||
}
|
||||
}
|
||||
|
||||
root.setOnClickListener {
|
||||
onKaraokeClicked(karaokeData, holder.absoluteAdapterPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.woka.home.mylist.models
|
||||
|
||||
import com.woka.karaoke.models.listing.ContentMoreDetail
|
||||
import com.woka.karaoke.models.listing.KaraokeData
|
||||
|
||||
data class FavKaraokeData(
|
||||
val age_range_master_id: String?,
|
||||
val bookmark_category_ids: String?,
|
||||
val bookmark_count: Int?,
|
||||
val category_master_id: String?,
|
||||
val content_more_details: List<ContentMoreDetail?>?,
|
||||
val description: String?,
|
||||
val duration: String?,
|
||||
val gender_master_id: String?,
|
||||
val id: Int?,
|
||||
var is_liked: Boolean?,
|
||||
val language_master_id: Int?,
|
||||
var likes_count: Int?,
|
||||
val mark_as_favourite: Boolean?,
|
||||
val release_date: String?,
|
||||
val thumbnail_path: String?,
|
||||
val title: String?,
|
||||
val video_url: String?,
|
||||
val views_count: Int?
|
||||
){
|
||||
constructor(karaoke: KaraokeData): this(
|
||||
karaoke.age_range_master_id,
|
||||
karaoke.bookmark_category_ids,
|
||||
karaoke.bookmark_count,
|
||||
karaoke.category_master_id,
|
||||
karaoke.content_more_details,
|
||||
karaoke.description,
|
||||
karaoke.duration,
|
||||
karaoke.gender_master_id,
|
||||
karaoke.id,
|
||||
karaoke.is_liked,
|
||||
karaoke.language_master_id,
|
||||
karaoke.likes_count,
|
||||
karaoke.mark_as_favourite,
|
||||
karaoke.release_date,
|
||||
karaoke.thumbnail_path,
|
||||
karaoke.title,
|
||||
karaoke.video_url,
|
||||
karaoke.views_count
|
||||
)
|
||||
}
|
||||
@@ -4,6 +4,6 @@ data class Result(
|
||||
val audio_data: MutableList<FavAudioBookData>?,
|
||||
val game_data: MutableList<FavGameData>?,
|
||||
val show_data: MutableList<BookmarkedShowData>?,
|
||||
val sing_karaoke_data: MutableList<SingKaraokeData>?,
|
||||
val sing_karaoke_data: MutableList<FavKaraokeData>?,
|
||||
val video_data: MutableList<Any>?
|
||||
)
|
||||
@@ -3,7 +3,10 @@ package com.woka.karaoke
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.woka.home.mylist.MyListRepository
|
||||
import com.woka.home.mylist.models.FavKaraokeData
|
||||
import com.woka.home.mylist.models.PostType
|
||||
import com.woka.karaoke.models.continuesing.ContinueKaraokeResponse
|
||||
import com.woka.karaoke.models.listing.KaraokeData
|
||||
import com.woka.karaoke.models.listing.KaraokeResponse
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.networking.RetrofitHelper
|
||||
@@ -29,7 +32,14 @@ object KaraokeRepository {
|
||||
|
||||
private var karaokeData: KaraokeResponse? = null
|
||||
|
||||
fun loadGames(){
|
||||
// continue sing karaoke data
|
||||
private val _continueKaraokeLiveData = MutableLiveData<ApiResult<ContinueKaraokeResponse>>()
|
||||
val continueKaraokeLiveData: LiveData<ApiResult<ContinueKaraokeResponse>>
|
||||
get() = _continueKaraokeLiveData
|
||||
|
||||
private var continueKaraokeData: ContinueKaraokeResponse? = null
|
||||
|
||||
fun loadKaraokeSongs(){
|
||||
if (karaokeData != null){
|
||||
_karaokeLiveData.postValue(ApiResult.Success(karaokeData))
|
||||
return
|
||||
@@ -38,7 +48,7 @@ object KaraokeRepository {
|
||||
CoroutineScope(Dispatchers.IO).launch{
|
||||
_karaokeLiveData.postValue(ApiResult.Loading())
|
||||
|
||||
val response = RetrofitHelper.handleApiCall {
|
||||
val response = handleApiCall {
|
||||
apiService.karaokeListing(
|
||||
FormBody.Builder()
|
||||
.build()
|
||||
@@ -60,7 +70,36 @@ object KaraokeRepository {
|
||||
}
|
||||
}
|
||||
|
||||
fun likeUnLikeGame(postId: String, likeIt: Boolean){
|
||||
fun loadContinueKaraoke(){
|
||||
if (continueKaraokeData != null){
|
||||
_continueKaraokeLiveData.postValue(ApiResult.Success(continueKaraokeData))
|
||||
return
|
||||
}
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val response = handleApiCall {
|
||||
userActionApiService.continueKaraokeListing(
|
||||
FormBody.Builder()
|
||||
.add("post_type", PostType.KARAOKE.value)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
when (response){
|
||||
is ApiResult.Error -> {}
|
||||
is ApiResult.Loading -> {}
|
||||
is ApiResult.Success -> {
|
||||
response.data?.let {
|
||||
continueKaraokeData = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_continueKaraokeLiveData.postValue(response)
|
||||
}
|
||||
}
|
||||
|
||||
fun likeUnLikeSong(postId: String, likeIt: Boolean){
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
handleApiCall {
|
||||
if (likeIt){
|
||||
@@ -106,6 +145,27 @@ object KaraokeRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// continue Karaoke data update
|
||||
continueKaraokeData?.result?.let {
|
||||
for (audio in it){
|
||||
var found = false
|
||||
audio?.let {data ->
|
||||
if ("${data.id}" == id){
|
||||
|
||||
data.is_liked = isLiked
|
||||
|
||||
data.likes_count?.let { count ->
|
||||
data.likes_count = if (isLiked) count + 1
|
||||
else max(0, count - 1)
|
||||
}
|
||||
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if (found) break
|
||||
}
|
||||
}
|
||||
|
||||
// changing in fav list locally
|
||||
MyListRepository.myFavData.result?.sing_karaoke_data?.let {
|
||||
for (audioData in it){
|
||||
@@ -120,4 +180,59 @@ object KaraokeRepository {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateFavShow(karaoke: KaraokeData, addToBookmark: Boolean){
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
handleApiCall {
|
||||
if (addToBookmark){
|
||||
userActionApiService.addToFav(
|
||||
FormBody.Builder()
|
||||
.add("post_id", "${karaoke.id}")
|
||||
.add("post_type", PostType.KARAOKE.value)
|
||||
.build()
|
||||
)
|
||||
}else{
|
||||
userActionApiService.removeFromFav(
|
||||
FormBody.Builder()
|
||||
.add("id", "${karaoke.id}")
|
||||
.add("post_type", PostType.KARAOKE.value)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MyListRepository.myFavData.result?.sing_karaoke_data?.let {favAudioData ->
|
||||
karaoke.mark_as_favourite = addToBookmark
|
||||
if (addToBookmark){
|
||||
favAudioData.add(FavKaraokeData(karaoke))
|
||||
}else{
|
||||
favAudioData.removeIf{it.id == karaoke.id}
|
||||
}
|
||||
}
|
||||
|
||||
karaokeData?.karaoke_data?.let {
|
||||
for (audio in it){
|
||||
if (audio?.id == karaoke.id){
|
||||
audio?.mark_as_favourite = addToBookmark
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continueKaraokeData?.result?.let {
|
||||
for (audio in it){
|
||||
if (audio?.id == karaoke.id){
|
||||
audio?.mark_as_favourite = addToBookmark
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun clearData(){
|
||||
karaokeData = null
|
||||
continueKaraokeData = null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.woka.karaoke.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.woka.R
|
||||
import com.woka.WokaApp.Companion.userPrefs
|
||||
import com.woka.databinding.FavViewHolderBinding
|
||||
import com.woka.karaoke.KaraokeRepository
|
||||
import com.woka.karaoke.models.continuesing.ContinueKaraokeData
|
||||
import com.woka.karaoke.models.listing.KaraokeData
|
||||
import com.woka.utils.isNetworkConnected
|
||||
import com.woka.utils.show
|
||||
import com.woka.utils.toast
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class ContinueKaraokeAdapter(
|
||||
private val context: Context,
|
||||
private var onKaraokeClicked: (KaraokeData) -> Unit,
|
||||
private var onKaraokeChanged: (id: Int, isFromContinue: Boolean) -> Unit
|
||||
): ListAdapter<ContinueKaraokeData, ContinueKaraokeAdapter.AudioBookViewHolder>(ASYNC_DIFF_UTIL) {
|
||||
|
||||
inner class AudioBookViewHolder(val binding: FavViewHolderBinding): ViewHolder(binding.root)
|
||||
|
||||
companion object{
|
||||
val DIFF_UTIL = object : DiffUtil.ItemCallback<ContinueKaraokeData>(){
|
||||
override fun areItemsTheSame(oldItem: ContinueKaraokeData, newItem: ContinueKaraokeData): Boolean = oldItem.id == newItem.id
|
||||
|
||||
override fun areContentsTheSame(oldItem: ContinueKaraokeData, newItem: ContinueKaraokeData): Boolean {
|
||||
return oldItem.thumbnail_path == newItem.thumbnail_path &&
|
||||
oldItem.title == newItem.title &&
|
||||
oldItem.is_liked == newItem.is_liked &&
|
||||
oldItem.mark_as_favourite == newItem.mark_as_favourite &&
|
||||
oldItem.likes_count == newItem.likes_count
|
||||
}
|
||||
}
|
||||
|
||||
val ASYNC_DIFF_UTIL = AsyncDifferConfig.Builder(DIFF_UTIL)
|
||||
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
|
||||
.build()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AudioBookViewHolder {
|
||||
return AudioBookViewHolder(
|
||||
FavViewHolderBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: AudioBookViewHolder, position: Int) {
|
||||
val karaokeData = getItem(holder.absoluteAdapterPosition)
|
||||
|
||||
holder.binding.apply {
|
||||
karaokeData.thumbnail_path?.let {
|
||||
image.loadImage(it)
|
||||
}
|
||||
|
||||
karaokeData.content_more_details?.let {moreDetailsList ->
|
||||
title.text = if (moreDetailsList.isNotEmpty()){
|
||||
if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){
|
||||
moreDetailsList[1]?.title
|
||||
}else{
|
||||
moreDetailsList[0]?.title
|
||||
}
|
||||
}else{
|
||||
karaokeData.title
|
||||
}
|
||||
}
|
||||
|
||||
like.show()
|
||||
likeCount.show()
|
||||
fav.show()
|
||||
|
||||
karaokeData.likes_count?.let {
|
||||
likeCount.text = "$it"
|
||||
}
|
||||
|
||||
karaokeData.is_liked?.let {
|
||||
like.isSelected = it
|
||||
}
|
||||
|
||||
like.setOnClickListener {
|
||||
if (!context.isNetworkConnected()){
|
||||
context.toast(context.getString(R.string.no_internet))
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
KaraokeRepository.likeUnLikeSong(
|
||||
"${karaokeData.id}",
|
||||
!like.isSelected
|
||||
)
|
||||
|
||||
karaokeData.likes_count?.let {
|
||||
likeCount.text = "$it"
|
||||
}
|
||||
|
||||
karaokeData.is_liked?.let {
|
||||
like.isSelected = it
|
||||
}
|
||||
|
||||
karaokeData.id?.let{onKaraokeChanged(it, true)}
|
||||
}
|
||||
|
||||
fav.isSelected = karaokeData.mark_as_favourite == true
|
||||
|
||||
fav.setOnClickListener {
|
||||
if (!context.isNetworkConnected()){
|
||||
context.toast(context.getString(R.string.no_internet))
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
KaraokeRepository.updateFavShow(
|
||||
KaraokeData(karaokeData),
|
||||
!fav.isSelected
|
||||
)
|
||||
|
||||
fav.isSelected = karaokeData.mark_as_favourite == true
|
||||
|
||||
karaokeData.id?.let{onKaraokeChanged(it, true)}
|
||||
}
|
||||
|
||||
root.setOnClickListener {
|
||||
onKaraokeClicked(KaraokeData(karaokeData))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
133
app/src/main/java/com/woka/karaoke/adapters/KaraokeAdapter.kt
Normal file
133
app/src/main/java/com/woka/karaoke/adapters/KaraokeAdapter.kt
Normal file
@@ -0,0 +1,133 @@
|
||||
package com.woka.karaoke.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.woka.R
|
||||
import com.woka.WokaApp.Companion.userPrefs
|
||||
import com.woka.databinding.ShowViewHolderBinding
|
||||
import com.woka.karaoke.KaraokeRepository
|
||||
import com.woka.karaoke.models.listing.KaraokeData
|
||||
import com.woka.utils.isNetworkConnected
|
||||
import com.woka.utils.show
|
||||
import com.woka.utils.toast
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class KaraokeAdapter(
|
||||
private val context: Context,
|
||||
private var onKaraokeClicked: (KaraokeData) -> Unit,
|
||||
private var onKaraokeChanged: (id: Int, isContinue: Boolean) -> Unit
|
||||
): ListAdapter<KaraokeData, KaraokeAdapter.AudioBookViewHolder>(ASYNC_DIFF_UTIL) {
|
||||
|
||||
inner class AudioBookViewHolder(val binding: ShowViewHolderBinding): ViewHolder(binding.root)
|
||||
|
||||
companion object{
|
||||
val DIFF_UTIL = object : DiffUtil.ItemCallback<KaraokeData>(){
|
||||
override fun areItemsTheSame(oldItem: KaraokeData, newItem: KaraokeData): Boolean = oldItem.id == newItem.id
|
||||
|
||||
override fun areContentsTheSame(oldItem: KaraokeData, newItem: KaraokeData): Boolean {
|
||||
return oldItem.thumbnail_path == newItem.thumbnail_path &&
|
||||
oldItem.title == newItem.title &&
|
||||
oldItem.is_liked == newItem.is_liked &&
|
||||
oldItem.mark_as_favourite == newItem.mark_as_favourite &&
|
||||
oldItem.likes_count == newItem.likes_count
|
||||
}
|
||||
}
|
||||
|
||||
val ASYNC_DIFF_UTIL = AsyncDifferConfig.Builder(DIFF_UTIL)
|
||||
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
|
||||
.build()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AudioBookViewHolder {
|
||||
return AudioBookViewHolder(
|
||||
ShowViewHolderBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: AudioBookViewHolder, position: Int) {
|
||||
val karaokeData = getItem(holder.absoluteAdapterPosition)
|
||||
|
||||
holder.binding.apply {
|
||||
karaokeData.thumbnail_path?.let {
|
||||
image.loadImage(it)
|
||||
}
|
||||
|
||||
karaokeData.content_more_details?.let {moreDetailsList ->
|
||||
title.text = if (moreDetailsList.isNotEmpty()){
|
||||
if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){
|
||||
moreDetailsList[1]?.title
|
||||
}else{
|
||||
moreDetailsList[0]?.title
|
||||
}
|
||||
}else{
|
||||
karaokeData.title
|
||||
}
|
||||
}
|
||||
|
||||
like.show()
|
||||
likeCount.show()
|
||||
fav.show()
|
||||
|
||||
karaokeData.likes_count?.let {
|
||||
likeCount.text = "$it"
|
||||
}
|
||||
|
||||
karaokeData.is_liked?.let {
|
||||
like.isSelected = it
|
||||
}
|
||||
|
||||
like.setOnClickListener {
|
||||
if (!context.isNetworkConnected()){
|
||||
context.toast(context.getString(R.string.no_internet))
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
KaraokeRepository.likeUnLikeSong(
|
||||
"${karaokeData.id}",
|
||||
!like.isSelected
|
||||
)
|
||||
|
||||
karaokeData.likes_count?.let {
|
||||
likeCount.text = "$it"
|
||||
}
|
||||
|
||||
karaokeData.is_liked?.let {
|
||||
like.isSelected = it
|
||||
}
|
||||
|
||||
karaokeData.id?.let{onKaraokeChanged(it, false)}
|
||||
}
|
||||
|
||||
fav.isSelected = karaokeData.mark_as_favourite == true
|
||||
|
||||
fav.setOnClickListener {
|
||||
if (!context.isNetworkConnected()){
|
||||
context.toast(context.getString(R.string.no_internet))
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
KaraokeRepository.updateFavShow(
|
||||
karaokeData,
|
||||
!fav.isSelected
|
||||
)
|
||||
|
||||
fav.isSelected = karaokeData.mark_as_favourite == true
|
||||
|
||||
karaokeData.id?.let{onKaraokeChanged(it, false)}
|
||||
}
|
||||
|
||||
root.setOnClickListener {
|
||||
onKaraokeClicked(karaokeData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
package com.woka.home.mylist.models
|
||||
package com.woka.karaoke.models.continuesing
|
||||
|
||||
data class SingKaraokeData(
|
||||
import com.woka.karaoke.models.listing.ContentMoreDetail
|
||||
|
||||
data class ContinueKaraokeData(
|
||||
val age_range_master_id: String?,
|
||||
val bookmark_category_ids: String?,
|
||||
val bookmark_count: Int?,
|
||||
val category_master_id: String?,
|
||||
// val content_more_details: List<ContentMoreDetail>?,
|
||||
val content_more_details: List<ContentMoreDetail?>?,
|
||||
val description: String?,
|
||||
val duration: String?,
|
||||
val gender_master_id: String?,
|
||||
@@ -13,10 +14,12 @@ data class SingKaraokeData(
|
||||
var is_liked: Boolean?,
|
||||
val language_master_id: Int?,
|
||||
var likes_count: Int?,
|
||||
val mark_as_favourite: Boolean?,
|
||||
var mark_as_favourite: Boolean?,
|
||||
val release_date: String?,
|
||||
val show_data_count: Any?,
|
||||
val thumbnail_path: String?,
|
||||
val title: String?,
|
||||
val user_video_view: List<Any?>?,
|
||||
val video_url: String?,
|
||||
val views_count: Int?
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.woka.karaoke.models.continuesing
|
||||
|
||||
data class ContinueKaraokeResponse(
|
||||
val result: List<ContinueKaraokeData?>?,
|
||||
val total_records: Int?
|
||||
)
|
||||
@@ -1,24 +1,82 @@
|
||||
package com.woka.karaoke.models.listing
|
||||
|
||||
import com.woka.home.mylist.models.FavKaraokeData
|
||||
import com.woka.karaoke.models.continuesing.ContinueKaraokeData
|
||||
|
||||
data class KaraokeData(
|
||||
val age_range_data: List<Any?>?,
|
||||
val age_range_master_id: String?,
|
||||
val bookmark_category_ids: String?,
|
||||
val bookmark_count: Int?,
|
||||
val category_data: List<Any?>?,
|
||||
val category_master_id: String?,
|
||||
val content_more_details: List<ContentMoreDetail?>?,
|
||||
val description: String?,
|
||||
val duration: String?,
|
||||
val gender_data: List<Any?>?,
|
||||
val gender_master_id: String?,
|
||||
val id: Int?,
|
||||
var is_liked: Boolean?,
|
||||
val language_master_id: Int?,
|
||||
var likes_count: Int?,
|
||||
val mark_as_favourite: Boolean?,
|
||||
var mark_as_favourite: Boolean?,
|
||||
val release_date: String?,
|
||||
val show_data_count: Any?,
|
||||
val thumbnail_path: String?,
|
||||
val title: String?,
|
||||
val user_video_view: List<Any?>?,
|
||||
val video_url: String?,
|
||||
val views_count: Int?
|
||||
)
|
||||
val views_count: Int?,
|
||||
val age_range_data: List<Any?>?,
|
||||
val category_data: List<Any?>?,
|
||||
val gender_data: List<Any?>?
|
||||
){
|
||||
constructor(favKaraoke: FavKaraokeData): this(
|
||||
favKaraoke.age_range_master_id,
|
||||
favKaraoke.bookmark_category_ids,
|
||||
favKaraoke.bookmark_count,
|
||||
favKaraoke.category_master_id,
|
||||
favKaraoke.content_more_details,
|
||||
favKaraoke.description,
|
||||
favKaraoke.duration,
|
||||
favKaraoke.gender_master_id,
|
||||
favKaraoke.id,
|
||||
favKaraoke.is_liked,
|
||||
favKaraoke.language_master_id,
|
||||
favKaraoke.likes_count,
|
||||
favKaraoke.mark_as_favourite,
|
||||
favKaraoke.release_date,
|
||||
null,
|
||||
favKaraoke.thumbnail_path,
|
||||
favKaraoke.title,
|
||||
null,
|
||||
favKaraoke.video_url,
|
||||
favKaraoke.views_count,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
|
||||
constructor(continueKaraoke: ContinueKaraokeData): this(
|
||||
continueKaraoke.age_range_master_id,
|
||||
null,
|
||||
continueKaraoke.bookmark_count,
|
||||
continueKaraoke.category_master_id,
|
||||
continueKaraoke.content_more_details,
|
||||
continueKaraoke.description,
|
||||
continueKaraoke.duration,
|
||||
continueKaraoke.gender_master_id,
|
||||
continueKaraoke.id,
|
||||
continueKaraoke.is_liked,
|
||||
continueKaraoke.language_master_id,
|
||||
continueKaraoke.likes_count,
|
||||
continueKaraoke.mark_as_favourite,
|
||||
continueKaraoke.release_date,
|
||||
continueKaraoke.show_data_count,
|
||||
continueKaraoke.thumbnail_path,
|
||||
continueKaraoke.title,
|
||||
continueKaraoke.user_video_view,
|
||||
continueKaraoke.video_url,
|
||||
continueKaraoke.views_count,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.woka.karaoke.player
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import com.woka.R
|
||||
import com.woka.databinding.ActivityKaraokePlayerrBinding
|
||||
import com.woka.utils.WokaBaseActivity
|
||||
|
||||
class KaraokePlayerActivity : WokaBaseActivity() {
|
||||
|
||||
companion object {
|
||||
const val EXTRA_KARAOKE_DATA = "extra_karaoke_data"
|
||||
}
|
||||
|
||||
private lateinit var binding: ActivityKaraokePlayerrBinding
|
||||
|
||||
private var karaokePlayerData: KaraokePlayerData? = null
|
||||
|
||||
private var player: ExoPlayer? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
binding = ActivityKaraokePlayerrBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
|
||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||
insets
|
||||
}
|
||||
|
||||
val windowInsetsController =
|
||||
WindowCompat.getInsetsController(window, window.decorView)
|
||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||
|
||||
karaokePlayerData = intent.getParcelableExtra(EXTRA_KARAOKE_DATA)
|
||||
|
||||
player = ExoPlayer.Builder(this).build()
|
||||
binding.playerView.player = player
|
||||
|
||||
playVideo()
|
||||
|
||||
initViews()
|
||||
|
||||
clickEvents()
|
||||
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
player?.stop()
|
||||
player?.release()
|
||||
}
|
||||
|
||||
private fun initViews(){
|
||||
binding.apply {
|
||||
playerView.findViewById<TextView>(R.id.player_controller_title).text = karaokePlayerData?.title
|
||||
}
|
||||
}
|
||||
|
||||
private fun clickEvents(){
|
||||
binding.apply {
|
||||
playerView.findViewById<ImageView>(R.id.player_controller_close_btn).setOnClickListener {
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun playVideo() {
|
||||
if (karaokePlayerData?.karaokeVideoUrl == null) return
|
||||
|
||||
player?.setMediaItem(MediaItem.fromUri(karaokePlayerData?.karaokeVideoUrl!!))
|
||||
player?.prepare()
|
||||
player?.play()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.woka.karaoke.player
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class KaraokePlayerData(
|
||||
val karaokeVideoUrl: String,
|
||||
val title: String?
|
||||
): Parcelable
|
||||
361
app/src/main/java/com/woka/karaoke/views/KaraokeActivity.kt
Normal file
361
app/src/main/java/com/woka/karaoke/views/KaraokeActivity.kt
Normal file
@@ -0,0 +1,361 @@
|
||||
package com.woka.karaoke.views
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.InsetDrawable
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
import com.woka.R
|
||||
import com.woka.WokaApp
|
||||
import com.woka.databinding.ActivityKaraokeBinding
|
||||
import com.woka.databinding.DialogModuleShowerBinding
|
||||
import com.woka.karaoke.KaraokeRepository
|
||||
import com.woka.karaoke.adapters.ContinueKaraokeAdapter
|
||||
import com.woka.karaoke.adapters.KaraokeAdapter
|
||||
import com.woka.karaoke.models.listing.KaraokeData
|
||||
import com.woka.karaoke.player.KaraokePlayerActivity
|
||||
import com.woka.karaoke.player.KaraokePlayerActivity.Companion.EXTRA_KARAOKE_DATA
|
||||
import com.woka.karaoke.player.KaraokePlayerData
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.utils.WokaBaseActivity
|
||||
import com.woka.utils.hide
|
||||
import com.woka.utils.show
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class KaraokeActivity : WokaBaseActivity() {
|
||||
|
||||
private lateinit var binding: ActivityKaraokeBinding
|
||||
|
||||
// adapters
|
||||
private lateinit var karaokeAdapter: KaraokeAdapter
|
||||
private lateinit var continueKaraokeAdapter: ContinueKaraokeAdapter
|
||||
|
||||
private lateinit var dialogBinding: DialogModuleShowerBinding
|
||||
private lateinit var karaokeDialog: Dialog
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityKaraokeBinding.inflate(layoutInflater)
|
||||
enableEdgeToEdge()
|
||||
setContentView(binding.root)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
|
||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||
insets
|
||||
}
|
||||
|
||||
window.apply {
|
||||
navigationBarColor = getColor(R.color.color_primary_dark)
|
||||
}
|
||||
|
||||
karaokeAdapter = KaraokeAdapter(this, ::onKaraokeClicked, ::onKaraokeChanged)
|
||||
continueKaraokeAdapter = ContinueKaraokeAdapter(this, ::onKaraokeClicked, ::onKaraokeChanged)
|
||||
|
||||
dialogBinding = DialogModuleShowerBinding.inflate(layoutInflater)
|
||||
karaokeDialog = Dialog(this)
|
||||
karaokeDialog.setContentView(dialogBinding.root)
|
||||
|
||||
initViews()
|
||||
|
||||
initKaraokeDialog()
|
||||
|
||||
clickEvents()
|
||||
|
||||
setObservers()
|
||||
|
||||
KaraokeRepository.loadKaraokeSongs()
|
||||
}
|
||||
|
||||
private fun initViews() {
|
||||
binding.apply {
|
||||
adjustTrailerImage()
|
||||
|
||||
toolbar.title.text = getString(R.string.karaoke)
|
||||
|
||||
rvKaraoke.adapter = karaokeAdapter
|
||||
(rvKaraoke.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
|
||||
|
||||
rvContinueSing.adapter = continueKaraokeAdapter
|
||||
(rvContinueSing.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun initKaraokeDialog() {
|
||||
try {
|
||||
val back = ColorDrawable(Color.TRANSPARENT)
|
||||
val inset = InsetDrawable(back, 50)
|
||||
karaokeDialog.window!!.setBackgroundDrawable(inset)
|
||||
} catch (e: Exception) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
try {
|
||||
val layoutParams = karaokeDialog.window!!.attributes
|
||||
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT
|
||||
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||
karaokeDialog.window!!.setAttributes(layoutParams)
|
||||
} catch (e: Exception) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
dialogBinding.close.setOnClickListener { karaokeDialog.dismiss() }
|
||||
|
||||
dialogBinding.watchCard.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_mic, 0, 0, 0)
|
||||
dialogBinding.watchCard.backgroundTintList = ColorStateList.valueOf(getColor(R.color.game_grad_one))
|
||||
dialogBinding.watchCard.text = getString(R.string.sing_now)
|
||||
}
|
||||
|
||||
private fun clickEvents() {
|
||||
binding.apply {
|
||||
toolbar.backBtn.setOnClickListener {
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
retryBtn.setOnClickListener {
|
||||
KaraokeRepository.loadKaraokeSongs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadTrailerData(karaokeData: KaraokeData) {
|
||||
binding.apply {
|
||||
trailerView.show()
|
||||
adjustTrailerImage()
|
||||
|
||||
karaokeData.thumbnail_path?.let {
|
||||
trailerImage.loadImage(it)
|
||||
}
|
||||
|
||||
karaokeData.content_more_details?.let { moreDetailsList ->
|
||||
trailerName.text = if (moreDetailsList.isNotEmpty()) {
|
||||
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) {
|
||||
moreDetailsList[1]?.title
|
||||
} else {
|
||||
moreDetailsList[0]?.title
|
||||
}
|
||||
} else {
|
||||
karaokeData.title
|
||||
}
|
||||
}
|
||||
|
||||
trailerBtn.setOnClickListener {
|
||||
onSingClicked(karaokeData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSingClicked(karaokeData: KaraokeData){
|
||||
karaokeData.video_url?.let {
|
||||
startActivity(Intent(this@KaraokeActivity, KaraokePlayerActivity::class.java).apply {
|
||||
putExtra(EXTRA_KARAOKE_DATA, KaraokePlayerData(it, karaokeData.title))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun adjustTrailerImage() {
|
||||
// making space for Trailer image
|
||||
binding.apply {
|
||||
topPinnedView.post {
|
||||
val imgParams = trailerImage.layoutParams as CollapsingToolbarLayout.LayoutParams
|
||||
imgParams.setMargins(0, 0, 0, topPinnedView.height)
|
||||
trailerImage.layoutParams = imgParams
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showKaraokeDialog(karaokeData: KaraokeData) {
|
||||
dialogBinding.apply {
|
||||
karaokeData.content_more_details?.let { moreDetailsList ->
|
||||
|
||||
karaokeData.thumbnail_path?.let {
|
||||
image.loadImage(it)
|
||||
}
|
||||
|
||||
fav.isSelected = karaokeData.mark_as_favourite == true
|
||||
like.isSelected = karaokeData.is_liked == true
|
||||
likeCount.text = "${karaokeData.likes_count}"
|
||||
|
||||
year.text = try {
|
||||
karaokeData.release_date?.let {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.time =
|
||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).parse(
|
||||
karaokeData.release_date
|
||||
)!!
|
||||
"${cal.get(Calendar.YEAR)}"
|
||||
} ?: throw Exception()
|
||||
} catch (e: Exception) {
|
||||
"${karaokeData.release_date}"
|
||||
}
|
||||
|
||||
if (moreDetailsList.isNotEmpty()) {
|
||||
|
||||
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) {
|
||||
moreDetailsList[1]?.let { data ->
|
||||
title.text = data.title
|
||||
description.text = Html.fromHtml(
|
||||
data.description?.replace(
|
||||
"<br>",
|
||||
" "
|
||||
), Html.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
}
|
||||
} else {
|
||||
moreDetailsList[0]?.let { data ->
|
||||
title.text = data.title
|
||||
description.text = Html.fromHtml(
|
||||
data.description?.replace(
|
||||
"<br>",
|
||||
" "
|
||||
), Html.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
title.text = karaokeData.title
|
||||
description.text = Html.fromHtml(
|
||||
karaokeData.description?.replace(
|
||||
"<br>",
|
||||
" "
|
||||
), Html.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
}
|
||||
|
||||
watchCard.setOnClickListener {
|
||||
onSingClicked(karaokeData)
|
||||
}
|
||||
|
||||
like.setOnClickListener {
|
||||
KaraokeRepository.likeUnLikeSong(
|
||||
"${karaokeData.id}",
|
||||
!like.isSelected
|
||||
)
|
||||
|
||||
karaokeData.id?.let {
|
||||
onKaraokeChanged(it, false)
|
||||
onKaraokeChanged(it, true)
|
||||
}
|
||||
like.isSelected = !like.isSelected
|
||||
likeCount.text = "${karaokeData.likes_count}"
|
||||
}
|
||||
|
||||
fav.setOnClickListener {
|
||||
KaraokeRepository.updateFavShow(
|
||||
karaokeData,
|
||||
!fav.isSelected
|
||||
)
|
||||
|
||||
karaokeData.id?.let {
|
||||
onKaraokeChanged(it, false)
|
||||
onKaraokeChanged(it, true)
|
||||
}
|
||||
|
||||
fav.isSelected = !fav.isSelected
|
||||
}
|
||||
|
||||
close.setOnClickListener {
|
||||
karaokeDialog.dismiss()
|
||||
}
|
||||
|
||||
karaokeDialog.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onKaraokeChanged(id: Int, isFromContinue: Boolean) {
|
||||
if (isFromContinue){
|
||||
// updating karaoke list
|
||||
val position = karaokeAdapter.currentList.indexOfFirst { it.id == id }
|
||||
if (position >= 0 && position < karaokeAdapter.currentList.size) {
|
||||
karaokeAdapter.notifyItemChanged(position)
|
||||
}
|
||||
}else{
|
||||
// updating continue karaoke list
|
||||
val continuePos = continueKaraokeAdapter.currentList.indexOfFirst { it.id == id }
|
||||
if (continuePos >= 0 && continuePos < continueKaraokeAdapter.currentList.size) {
|
||||
continueKaraokeAdapter.notifyItemChanged(continuePos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onKaraokeClicked(karaokeData: KaraokeData) {
|
||||
loadTrailerData(karaokeData)
|
||||
showKaraokeDialog(karaokeData)
|
||||
}
|
||||
|
||||
private fun setObservers() {
|
||||
KaraokeRepository.karaokeLiveData.observe(this) {
|
||||
when (it) {
|
||||
is ApiResult.Error -> {
|
||||
binding.shimmer.hide()
|
||||
binding.rvKaraoke.hide()
|
||||
binding.singTxt.hide()
|
||||
binding.trailerView.hide()
|
||||
|
||||
binding.errorView.show()
|
||||
}
|
||||
|
||||
is ApiResult.Loading -> {
|
||||
binding.shimmer.show()
|
||||
|
||||
binding.rvKaraoke.hide()
|
||||
binding.singTxt.hide()
|
||||
binding.trailerView.hide()
|
||||
binding.errorView.hide()
|
||||
}
|
||||
|
||||
is ApiResult.Success -> {
|
||||
it.data?.karaoke_data?.filterNotNull()?.let { audioBookData ->
|
||||
if (audioBookData.isNotEmpty()) {
|
||||
binding.shimmer.hide()
|
||||
binding.errorView.hide()
|
||||
|
||||
KaraokeRepository.loadContinueKaraoke()
|
||||
|
||||
loadTrailerData(audioBookData[0])
|
||||
binding.rvKaraoke.show()
|
||||
binding.singTxt.show()
|
||||
|
||||
karaokeAdapter.submitList(audioBookData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KaraokeRepository.continueKaraokeLiveData.observe(this) {
|
||||
when (it) {
|
||||
is ApiResult.Error -> {
|
||||
binding.continueSingTxt.hide()
|
||||
binding.rvContinueSing.hide()
|
||||
}
|
||||
|
||||
is ApiResult.Loading -> {}
|
||||
is ApiResult.Success -> {
|
||||
it.data?.result?.filterNotNull()?.let {continueData ->
|
||||
if (continueData.isNotEmpty()) {
|
||||
binding.continueSingTxt.show()
|
||||
binding.rvContinueSing.show()
|
||||
|
||||
continueKaraokeAdapter.submitList(continueData)
|
||||
} else {
|
||||
binding.continueSingTxt.hide()
|
||||
binding.rvContinueSing.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import androidx.lifecycle.MutableLiveData
|
||||
import com.woka.audiobooks.AudioBookRepository
|
||||
import com.woka.home.models.Theme
|
||||
import com.woka.home.mylist.MyListRepository
|
||||
import com.woka.karaoke.KaraokeRepository
|
||||
import com.woka.networking.ApiResult
|
||||
import com.woka.onboard.views.OnboardActivity
|
||||
import com.woka.userdata.UserRepository
|
||||
@@ -117,5 +118,6 @@ class UserPreference(val context: Context) {
|
||||
WebSeriesRepository.clearData()
|
||||
MyListRepository.clearData()
|
||||
AudioBookRepository.clearData()
|
||||
KaraokeRepository.clearData()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.woka.userdata
|
||||
|
||||
import com.woka.audiobooks.models.continuedata.ContinueAudioResponse
|
||||
import com.woka.karaoke.models.continuesing.ContinueKaraokeResponse
|
||||
import com.woka.networking.ApiResponse
|
||||
import com.woka.webseries.models.ContinueEpisodeResponse
|
||||
import okhttp3.FormBody
|
||||
@@ -27,4 +28,7 @@ interface UserActionApiService {
|
||||
|
||||
@POST("continue_watching")
|
||||
suspend fun continueAudioBookListing(@Body body: FormBody): Response<ApiResponse<ContinueAudioResponse>>
|
||||
|
||||
@POST("continue_watching")
|
||||
suspend fun continueKaraokeListing(@Body body: FormBody): Response<ApiResponse<ContinueKaraokeResponse>>
|
||||
}
|
||||
11
app/src/main/res/drawable/gradient_karaoke.xml
Normal file
11
app/src/main/res/drawable/gradient_karaoke.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<gradient android:startColor="#CC4A1C"
|
||||
android:endColor="#CC9B1C"
|
||||
android:centerColor="#CC9B1C"
|
||||
android:centerX="0.3"
|
||||
android:angle="-45"
|
||||
/>
|
||||
|
||||
</shape>
|
||||
5
app/src/main/res/drawable/ic_mic.xml
Normal file
5
app/src/main/res/drawable/ic_mic.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="31" android:viewportWidth="31" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#ffffff" android:pathData="M15.5,0C11.731,0 8.68,2.967 8.68,6.646V6.82H13.33C13.671,6.82 13.95,7.099 13.95,7.44C13.95,7.781 13.671,8.06 13.33,8.06H8.68V9.3H13.33C13.671,9.3 13.95,9.579 13.95,9.92C13.95,10.262 13.671,10.54 13.33,10.54H8.68V11.78H13.33C13.671,11.78 13.95,12.059 13.95,12.4C13.95,12.741 13.671,13.02 13.33,13.02H8.68V14.434C8.68,18.113 11.731,21.08 15.5,21.08C19.268,21.08 22.32,18.113 22.32,14.434V13.02H17.67C17.326,13.02 17.05,12.741 17.05,12.4C17.05,12.059 17.326,11.78 17.67,11.78H22.32V10.54H17.67C17.326,10.54 17.05,10.262 17.05,9.92C17.05,9.579 17.326,9.3 17.67,9.3H22.32V8.06H17.67C17.326,8.06 17.05,7.781 17.05,7.44C17.05,7.099 17.326,6.82 17.67,6.82H22.32V6.646C22.32,2.967 19.268,0 15.5,0ZM6.084,10.618C5.829,10.671 5.65,10.901 5.657,11.16V14.26C5.657,19.043 9.106,23.054 13.64,23.928V27.28H17.36V23.928C21.894,23.054 25.342,19.043 25.342,14.26V11.16C25.342,10.86 25.1,10.618 24.8,10.618C24.5,10.618 24.257,10.86 24.257,11.16V14.26C24.257,19.097 20.336,23.017 15.5,23.017C10.663,23.017 6.742,19.097 6.742,14.26V11.16C6.745,11.005 6.679,10.857 6.566,10.753C6.449,10.649 6.297,10.598 6.142,10.618C6.122,10.618 6.103,10.618 6.084,10.618ZM9.61,28.52C8.423,28.52 7.459,29.489 7.459,30.671L7.44,31L23.482,30.961L23.502,30.671C23.502,29.489 22.538,28.52 21.351,28.52H9.61Z"/>
|
||||
|
||||
</vector>
|
||||
283
app/src/main/res/layout/activity_karaoke.xml
Normal file
283
app/src/main/res/layout/activity_karaoke.xml
Normal file
@@ -0,0 +1,283 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/gradient_karaoke"
|
||||
android:orientation="vertical"
|
||||
tools:context=".webseries.views.WebSeriesActivity">
|
||||
|
||||
<include android:id="@+id/toolbar"
|
||||
layout="@layout/layout_toolbar"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/shimmer"
|
||||
android:visibility="gone"
|
||||
android:background="@color/color_primary_dark"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.facebook.shimmer.ShimmerFrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:shimmer_auto_start="true"
|
||||
app:shimmer_duration="1500"
|
||||
app:shimmer_highlight_alpha="0.5"
|
||||
>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="none"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/_160sdp"
|
||||
android:background="@color/white_50"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/_100sdp"
|
||||
android:layout_height="@dimen/_37sdp"
|
||||
android:background="@color/white_50"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/_140sdp"
|
||||
android:background="@color/white_50"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/_140sdp"
|
||||
android:background="@color/white_50"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/_140sdp"
|
||||
android:background="@color/white_50"
|
||||
android:layout_marginVertical="15dp"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</com.facebook.shimmer.ShimmerFrameLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/error_view"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/color_primary_dark"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:text="@string/something_went_wrong"
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/_14ssp"
|
||||
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/retry_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:text="@string/retry"
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/_14ssp"
|
||||
|
||||
android:paddingHorizontal="25dp"
|
||||
android:layout_marginTop="15dp"
|
||||
|
||||
android:background="@drawable/grad_btn_bg_4"
|
||||
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/color_primary_dark"
|
||||
>
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/trailer_view"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|snap|exitUntilCollapsed">
|
||||
|
||||
<com.woka.utils.AdiImageView
|
||||
android:id="@+id/trailer_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/_160sdp"
|
||||
android:contentDescription="@string/image"
|
||||
android:src="@drawable/img_masila_full"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_collapseMode="parallax"
|
||||
android:layout_gravity="top"
|
||||
/>
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/top_pinned_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/color_primary_dark"
|
||||
app:layout_collapseMode="pin"
|
||||
app:contentInsetStart="0dp"
|
||||
app:contentInsetLeft="0dp"
|
||||
app:contentInsetStartWithNavigation="0dp"
|
||||
android:layout_gravity="bottom">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="15dp"
|
||||
android:gravity="center"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/trailer_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
tools:text="@string/masila"
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/_16ssp"
|
||||
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/trailer_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:text="@string/sing"
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/_12ssp"
|
||||
|
||||
android:paddingHorizontal="25dp"
|
||||
android:layout_marginTop="15dp"
|
||||
|
||||
android:background="@drawable/play_btn_bg"
|
||||
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/color_primary_dark"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/continue_sing_txt"
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:text="@string/sing_again"
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/_14ssp"
|
||||
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
|
||||
/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_continue_sing"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/continue_show_view_holder"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginStart="15dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sing_txt"
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:text="@string/sing_along_and_dance"
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/_14ssp"
|
||||
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
|
||||
/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_karaoke"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/show_view_holder"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</LinearLayout>
|
||||
67
app/src/main/res/layout/activity_karaoke_playerr.xml
Normal file
67
app/src/main/res/layout/activity_karaoke_playerr.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/main"
|
||||
android:background="@color/black"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".karaoke.player.KaraokePlayerActivity">
|
||||
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/player_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:controller_layout_id="@layout/exo_player_control_view"
|
||||
/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/error_view"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/close_btn"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:contentDescription="@string/image"
|
||||
android:src="@drawable/ic_close"
|
||||
android:layout_margin="25dp"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_centerInParent="true">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:text="@string/something_went_wrong"
|
||||
android:fontFamily="@font/exo_2"
|
||||
android:textColor="@color/white"
|
||||
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/retry_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:text="@string/retry_underline"
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textColor="@color/white"
|
||||
|
||||
android:padding="5dp"
|
||||
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
192
app/src/main/res/layout/exo_player_control_view.xml
Normal file
192
app/src/main/res/layout/exo_player_control_view.xml
Normal file
@@ -0,0 +1,192 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<!-- 0dp dimensions are used to prevent this view from influencing the size of
|
||||
the parent view if it uses "wrap_content". It is expanded to occupy the
|
||||
entirety of the parent in code, after the parent's size has been
|
||||
determined. See: https://github.com/google/ExoPlayer/issues/8726.
|
||||
-->
|
||||
<View android:id="@id/exo_controls_background"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/exo_black_opacity_60"/>
|
||||
|
||||
<FrameLayout android:id="@id/exo_bottom_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/exo_styled_bottom_bar_height"
|
||||
android:layout_marginTop="@dimen/exo_styled_bottom_bar_margin_top"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/exo_bottom_bar_background"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<LinearLayout android:id="@id/exo_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/exo_styled_bottom_bar_time_padding"
|
||||
android:paddingEnd="@dimen/exo_styled_bottom_bar_time_padding"
|
||||
android:paddingLeft="@dimen/exo_styled_bottom_bar_time_padding"
|
||||
android:paddingRight="@dimen/exo_styled_bottom_bar_time_padding"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<TextView android:id="@id/exo_position"
|
||||
style="@style/ExoStyledControls.TimeText.Position"/>
|
||||
|
||||
<TextView
|
||||
style="@style/ExoStyledControls.TimeText.Separator"/>
|
||||
|
||||
<TextView android:id="@id/exo_duration"
|
||||
style="@style/ExoStyledControls.TimeText.Duration"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout android:id="@id/exo_basic_controls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<ImageButton android:id="@id/exo_vr"
|
||||
style="@style/ExoStyledControls.Button.Bottom.VR"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_shuffle"
|
||||
style="@style/ExoStyledControls.Button.Bottom.Shuffle"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_repeat_toggle"
|
||||
style="@style/ExoStyledControls.Button.Bottom.RepeatToggle"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_subtitle"
|
||||
style="@style/ExoStyledControls.Button.Bottom.CC"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_overflow_show"
|
||||
style="@style/ExoStyledControls.Button.Bottom.OverflowShow"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<HorizontalScrollView android:id="@id/exo_extra_controls_scroll_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:visibility="invisible">
|
||||
|
||||
<LinearLayout android:id="@id/exo_extra_controls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<ImageButton android:id="@id/exo_overflow_hide"
|
||||
style="@style/ExoStyledControls.Button.Bottom.OverflowHide"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View android:id="@id/exo_progress_placeholder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/exo_styled_progress_layout_height"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginBottom="@dimen/exo_styled_progress_margin_bottom"/>
|
||||
|
||||
<LinearLayout android:id="@id/exo_minimal_controls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginBottom="@dimen/exo_styled_minimal_controls_margin_bottom"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<ImageButton android:id="@id/exo_minimal_fullscreen"
|
||||
style="@style/ExoStyledControls.Button.Bottom.FullScreen"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@id/exo_center_controls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="@android:color/transparent"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/exo_styled_controls_padding"
|
||||
android:clipToPadding="false"
|
||||
android:layoutDirection="ltr">
|
||||
|
||||
<include layout="@layout/exo_player_control_rewind_button" />
|
||||
|
||||
<ImageButton android:id="@id/exo_play_pause"
|
||||
style="@style/ExoStyledControls.Button.Center.PlayPause"/>
|
||||
|
||||
<include layout="@layout/exo_player_control_ffwd_button" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- custom vie-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/player_controller_close_btn"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:contentDescription="@string/image"
|
||||
android:src="@drawable/ic_close"
|
||||
android:layout_margin="25dp"
|
||||
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
||||
android:padding="5dp"
|
||||
|
||||
style="@style/ExoStyledControls.Button.Center.PlayPause"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/player_controller_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:fontFamily="@font/exo_2_bold"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/_14ssp"
|
||||
android:textAlignment="center"
|
||||
|
||||
android:ems="10"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
|
||||
android:layout_gravity="center_horizontal"
|
||||
|
||||
android:layout_margin="15dp"
|
||||
|
||||
app:layout_constraintTop_toTopOf="@id/player_controller_close_btn"
|
||||
app:layout_constraintBottom_toBottomOf="@id/player_controller_close_btn"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
||||
style="@style/ExoStyledControls.Button.Center.PlayPause"
|
||||
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</merge>
|
||||
@@ -198,4 +198,8 @@
|
||||
<string name="back_warning_text">Clicking \"OK\" will exit you from the game.\nAre you sure you want to proceed?</string>
|
||||
<string name="cancel_caps">CANCEL</string>
|
||||
<string name="ok_caps">OK</string>
|
||||
<string name="sing_along_and_dance">SING ALONG and DANCE</string>
|
||||
<string name="sing_again">SING AGAIN</string>
|
||||
<string name="sing">SING</string>
|
||||
<string name="sing_now">SING NOW</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user