Completed integrating audio books.

- Data caching
- Data syncing between continue data and audio data of like data and fav data
- Data syncing between fav list and audio book and continue data

Dialog of audio book
- Data syncing

Same dialog in fav list
This commit is contained in:
2024-07-05 21:27:07 +05:30
parent a3ce40b251
commit 6b193b1cc7
19 changed files with 997 additions and 133 deletions

View File

@@ -6,11 +6,13 @@ import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.audiobooks.models.audiodata.AudioBooksResponse
import com.woka.audiobooks.models.continuedata.ContinueAudioResponse
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.FavAudioBookData
import com.woka.home.mylist.models.PostType
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.networking.RetrofitHelper.handleApiCall
import com.woka.userdata.UserActionApiService
import com.woka.utils.TAG
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -114,9 +116,9 @@ object AudioBookRepository {
)
}
}
changeLikeLocally(postId, likeIt)
}
changeLikeLocally(postId, likeIt)
}
private fun changeLikeLocally(id: String, isLiked: Boolean){
@@ -141,6 +143,27 @@ object AudioBookRepository {
}
}
// continue audio books data update
continueAudioData?.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?.audio_data?.let {
for (audioData in it){
@@ -156,40 +179,50 @@ object AudioBookRepository {
}
}
fun updateFavShow(id: Int?, addToBookmark: Boolean){
fun updateFavShow(audioBookData: AudioBookData, addToBookmark: Boolean){
CoroutineScope(Dispatchers.IO).launch {
handleApiCall {
if (addToBookmark){
userActionApiService.addToFav(
FormBody.Builder()
.add("post_id", "$id")
.add("post_type", PostType.WEB_SERIES.value)
.add("post_id", "${audioBookData.id}")
.add("post_type", PostType.AUDIO_BOOKS.value)
.build()
)
}else{
userActionApiService.removeFromFav(
FormBody.Builder()
.add("id", "$id")
.add("post_type", PostType.WEB_SERIES.value)
.add("id", "${audioBookData.id}")
.add("post_type", PostType.AUDIO_BOOKS.value)
.build()
)
}
}
}
MyListRepository.myFavData.result?.audio_data?.let {
MyListRepository.myFavData.result?.audio_data?.let {favAudioData ->
audioBookData.mark_as_favourite = addToBookmark
if (addToBookmark){
favAudioData.add(FavAudioBookData(audioBookData))
}else{
favAudioData.removeIf{it.id == audioBookData.id}
}
}
audioBooksData?.audio_data?.let {
for (audio in it){
if (audio.id == id){
audio.mark_as_favourite = addToBookmark
if (audio?.id == audioBookData.id){
audio?.mark_as_favourite = addToBookmark
break
}
}
}
audioBooksData?.audio_data?.filterNotNull()?.let {
continueAudioData?.result?.let {
for (audio in it){
if (audio.id == id){
audio.mark_as_favourite = addToBookmark
if (audio?.id == audioBookData.id){
audio?.mark_as_favourite = addToBookmark
break
}
}
}

View File

@@ -11,20 +11,19 @@ import com.woka.WokaApp.Companion.userPrefs
import com.woka.audiobooks.AudioBookRepository
import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.databinding.ShowViewHolderBinding
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.PostType
import com.woka.utils.isNetworkConnected
import com.woka.utils.show
import com.woka.utils.toast
class AudioBooksAdapter(
private val context: Context,
var onBookClicked: (AudioBookData, Int) -> Unit
private var onBookClicked: (AudioBookData) -> Unit,
private var onBookChanged: (id: Int) -> Unit
): RecyclerView.Adapter<AudioBooksAdapter.AudioBookViewHolder>() {
inner class AudioBookViewHolder(val binding: ShowViewHolderBinding): ViewHolder(binding.root)
private var audioBookList: List<AudioBookData> = ArrayList()
var audioBookList: List<AudioBookData> = ArrayList()
@SuppressLint("NotifyDataSetChanged")
fun submitListShowList(it: List<AudioBookData>) {
@@ -84,11 +83,13 @@ class AudioBooksAdapter(
AudioBookRepository.likeUnLikeAudioBook(
"${audioBook.id}",
!fav.isSelected
!like.isSelected
)
like.isSelected = !like.isSelected
likeCount.text = "${audioBook.likes_count}"
audioBook.id?.let(onBookChanged)
}
fav.isSelected = audioBook.mark_as_favourite == true
@@ -100,15 +101,16 @@ class AudioBooksAdapter(
}
AudioBookRepository.updateFavShow(
audioBook.id,
audioBook,
!fav.isSelected
)
fav.isSelected = audioBook.mark_as_favourite == true
audioBook.id?.let(onBookChanged)
}
root.setOnClickListener {
onBookClicked(audioBook, holder.absoluteAdapterPosition)
onBookClicked(audioBook)
}
}
}

View File

@@ -7,15 +7,21 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import com.woka.R
import com.woka.WokaApp
import com.woka.audiobooks.AudioBookRepository
import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.audiobooks.models.continuedata.ContinueAudioData
import com.woka.databinding.FavViewHolderBinding
import com.woka.home.mylist.adapters.FavoriteViewHolder
import com.woka.utils.isNetworkConnected
import com.woka.utils.show
import com.woka.utils.toast
import java.util.concurrent.Executors
class ContinueAudioAdapter(private val context: Context,
config: AsyncDifferConfig<ContinueAudioData>): ListAdapter<ContinueAudioData, FavoriteViewHolder>(config) {
config: AsyncDifferConfig<ContinueAudioData>,
private var onBookClicked: (ContinueAudioData) -> Unit,
private var onContinueBookChanged: (id: Int) -> Unit): ListAdapter<ContinueAudioData, FavoriteViewHolder>(config) {
companion object{
private val DIFF_UTIL = object : DiffUtil.ItemCallback<ContinueAudioData>(){
@@ -33,7 +39,9 @@ class ContinueAudioAdapter(private val context: Context,
.build()
}
constructor(context: Context): this(context, DIFF_CONFIG)
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(
@@ -46,20 +54,34 @@ class ContinueAudioAdapter(private val context: Context,
}
override fun onBindViewHolder(holder: FavoriteViewHolder, pos: Int) {
val audioData = getItem(holder.absoluteAdapterPosition)
val audioBook = getItem(holder.absoluteAdapterPosition)
holder.binding.apply {
audioData.thumbnail_path?.let {
audioBook.thumbnail_path?.let {
image.loadImage(it)
}
title.text = audioData.title
audioBook.content_more_details?.let {moreDetailsList ->
title.text = if (moreDetailsList.isNotEmpty()){
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){
moreDetailsList[1]?.title
}else{
moreDetailsList[0]?.title
}
}else{
audioBook.title
}
}
audioData.likes_count?.let {
like.show()
likeCount.show()
fav.show()
audioBook.likes_count?.let {
likeCount.text = "$it"
}
audioData.is_liked?.let {
audioBook.is_liked?.let {
like.isSelected = it
}
@@ -69,10 +91,18 @@ class ContinueAudioAdapter(private val context: Context,
return@setOnClickListener
}
AudioBookRepository.likeUnLikeAudioBook(
"${audioBook.id}",
!like.isSelected
)
like.isSelected = !like.isSelected
likeCount.text = "${audioBook.likes_count}"
audioBook?.id?.let(onContinueBookChanged)
}
fav.isSelected = audioData.mark_as_favourite == true
fav.isSelected = audioBook.mark_as_favourite == true
fav.setOnClickListener {
if (!context.isNetworkConnected()){
@@ -80,7 +110,17 @@ class ContinueAudioAdapter(private val context: Context,
return@setOnClickListener
}
AudioBookRepository.updateFavShow(
AudioBookData(audioBook),
!fav.isSelected
)
fav.isSelected = audioBook.mark_as_favourite == true
audioBook?.id?.let(onContinueBookChanged)
}
root.setOnClickListener {
onBookClicked(audioBook)
}
}
}

View File

@@ -1,5 +1,8 @@
package com.woka.audiobooks.models.audiodata
import com.woka.audiobooks.models.continuedata.ContinueAudioData
import com.woka.home.mylist.models.FavAudioBookData
data class AudioBookData(
val age_range_data: List<Any?>?,
val age_range_master_id: String?,
@@ -24,4 +27,56 @@ data class AudioBookData(
val title: String?,
val user_video_view: List<Any?>?,
val views_count: Int?
)
){
constructor(audio: FavAudioBookData): this(
null,
audio.age_range_master_id,
audio.audio_duration,
audio.audio_url,
audio.bookmark_count,
null,
audio.category_master_id,
audio.content_more_details,
audio.description,
null,
audio.gender_master_id,
audio.id,
audio.is_liked,
audio.language_master_id,
audio.likes_count,
audio.mark_as_favourite,
audio.media_id,
audio.release_date,
audio.tags_keyword,
audio.thumbnail_path,
audio.title,
null,
audio.views_count
)
constructor(audio: ContinueAudioData): this(
null,
audio.age_range_master_id,
audio.audio_duration,
audio.audio_url,
audio.bookmark_count,
null,
audio.category_master_id,
audio.content_more_details,
audio.description,
null,
audio.gender_master_id,
audio.id,
audio.is_liked,
audio.language_master_id,
audio.likes_count,
audio.mark_as_favourite,
audio.media_id,
audio.release_date,
audio.tags_keyword,
audio.thumbnail_path,
audio.title,
audio.user_video_view,
audio.views_count
)
}

View File

@@ -1,12 +0,0 @@
package com.woka.audiobooks.models.continuedata
data class ContentMoreDetail(
val content_id: Int?,
val description: String?,
val id: Int?,
val language_master_id: Int?,
val post_type: Int?,
val tags_keywords: String?,
val title: String?,
val url: String?
)

View File

@@ -1,5 +1,7 @@
package com.woka.audiobooks.models.continuedata
import com.woka.audiobooks.models.audiodata.ContentMoreDetail
data class ContinueAudioData(
val age_range_master_id: String?,
val audio_duration: String?,
@@ -10,10 +12,10 @@ data class ContinueAudioData(
val description: String?,
val gender_master_id: String?,
val id: Int?,
val is_liked: Boolean?,
var is_liked: Boolean?,
val language_master_id: Int?,
val likes_count: Int?,
val mark_as_favourite: Boolean?,
var likes_count: Int?,
var mark_as_favourite: Boolean?,
val media_id: String?,
val release_date: String?,
val show_data_count: Any?,

View File

@@ -1,22 +1,43 @@
package com.woka.audiobooks.views
import android.app.Dialog
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.InsetDrawable
import android.os.Bundle
import android.text.Html
import android.util.Log
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.jwplayer.pub.api.media.playlists.PlaylistItem
import com.woka.R
import com.woka.WokaApp
import com.woka.WokaApp.Companion.userPrefs
import com.woka.audiobooks.AudioBookRepository
import com.woka.audiobooks.adapters.AudioBooksAdapter
import com.woka.audiobooks.adapters.ContinueAudioAdapter
import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.audiobooks.models.continuedata.ContinueAudioData
import com.woka.databinding.ActivityAudioBooksBinding
import com.woka.databinding.DialogAudioBookBinding
import com.woka.networking.ApiResult
import com.woka.players.models.VideoPlayList
import com.woka.players.views.PlayerActivity
import com.woka.utils.TAG
import com.woka.utils.WokaBaseActivity
import com.woka.utils.hide
import com.woka.utils.show
import com.woka.webseries.WebSeriesRepository
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.Calendar
import java.util.Locale
class AudioBooksActivity : WokaBaseActivity() {
@@ -25,6 +46,9 @@ class AudioBooksActivity : WokaBaseActivity() {
private lateinit var audioBookAdapter: AudioBooksAdapter
private lateinit var continueAudioAdapter: ContinueAudioAdapter
private lateinit var dialogBinding: DialogAudioBookBinding
private lateinit var audioDialog: Dialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
@@ -40,11 +64,18 @@ class AudioBooksActivity : WokaBaseActivity() {
navigationBarColor = getColor(R.color.color_primary_dark)
}
audioBookAdapter = AudioBooksAdapter(this, ::onBookClicked)
continueAudioAdapter = ContinueAudioAdapter(this)
audioBookAdapter = AudioBooksAdapter(this, ::onBookClicked, ::onBookChanged)
continueAudioAdapter =
ContinueAudioAdapter(this, ::onContinueBookClicked, ::onContinueBookChanged)
dialogBinding = DialogAudioBookBinding.inflate(layoutInflater)
audioDialog = Dialog(this)
audioDialog.setContentView(dialogBinding.root)
initViews()
initAudioDialog()
clickEvents()
setObservers()
@@ -52,7 +83,7 @@ class AudioBooksActivity : WokaBaseActivity() {
AudioBookRepository.loadAudioBooks()
}
private fun initViews(){
private fun initViews() {
binding.apply {
adjustTrailerImage()
@@ -66,7 +97,28 @@ class AudioBooksActivity : WokaBaseActivity() {
}
}
private fun clickEvents(){
private fun initAudioDialog() {
try {
val back = ColorDrawable(Color.TRANSPARENT)
val inset = InsetDrawable(back, 50)
audioDialog.window!!.setBackgroundDrawable(inset)
} catch (e: Exception) {
// do nothing
}
try {
val layoutParams = audioDialog.window!!.attributes
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
audioDialog.window!!.setAttributes(layoutParams)
} catch (e: Exception) {
// do nothing
}
dialogBinding.close.setOnClickListener { audioDialog.dismiss() }
}
private fun clickEvents() {
binding.apply {
toolbar.backBtn.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
@@ -78,9 +130,9 @@ class AudioBooksActivity : WokaBaseActivity() {
}
}
private fun setObservers(){
AudioBookRepository.audioBooksLiveData.observe(this){
when (it){
private fun setObservers() {
AudioBookRepository.audioBooksLiveData.observe(this) {
when (it) {
is ApiResult.Error -> {
binding.shimmer.hide()
binding.rvAudioBooks.hide()
@@ -89,6 +141,7 @@ class AudioBooksActivity : WokaBaseActivity() {
binding.errorView.show()
}
is ApiResult.Loading -> {
binding.shimmer.show()
@@ -97,9 +150,10 @@ class AudioBooksActivity : WokaBaseActivity() {
binding.trailerView.hide()
binding.errorView.hide()
}
is ApiResult.Success -> {
it.data?.audio_data?.filterNotNull()?.let {audioBookData ->
if (audioBookData.isNotEmpty()){
it.data?.audio_data?.filterNotNull()?.let { audioBookData ->
if (audioBookData.isNotEmpty()) {
binding.shimmer.hide()
binding.errorView.hide()
@@ -116,21 +170,22 @@ class AudioBooksActivity : WokaBaseActivity() {
}
}
AudioBookRepository.continueAudioBooksLiveData.observe(this){
when(it){
AudioBookRepository.continueAudioBooksLiveData.observe(this) {
when (it) {
is ApiResult.Error -> {
binding.continueListenTxt.hide()
binding.rvContinueListen.hide()
}
is ApiResult.Loading -> {}
is ApiResult.Success -> {
it.data?.result?.filterNotNull()?.let {continueData ->
if (continueData.isNotEmpty()){
it.data?.result?.filterNotNull()?.let { continueData ->
if (continueData.isNotEmpty()) {
binding.continueListenTxt.show()
binding.rvContinueListen.show()
continueAudioAdapter.submitList(continueData.toMutableList())
}else{
} else {
binding.continueListenTxt.hide()
binding.rvContinueListen.hide()
}
@@ -140,7 +195,7 @@ class AudioBooksActivity : WokaBaseActivity() {
}
}
private fun loadTrailerData(audioBookData: AudioBookData){
private fun loadTrailerData(audioBookData: AudioBookData) {
binding.apply {
trailerView.show()
adjustTrailerImage()
@@ -149,17 +204,21 @@ class AudioBooksActivity : WokaBaseActivity() {
trailerImage.loadImage(it)
}
audioBookData.content_more_details?.let {moreDetailsList ->
trailerName.text = if (moreDetailsList.isNotEmpty()){
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){
audioBookData.content_more_details?.let { moreDetailsList ->
trailerName.text = if (moreDetailsList.isNotEmpty()) {
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) {
moreDetailsList[1]?.title
}else{
} else {
moreDetailsList[0]?.title
}
}else{
} else {
audioBookData.title
}
}
trailerBtn.setOnClickListener {
onListenClicked(audioBookData)
}
}
}
@@ -174,7 +233,168 @@ class AudioBooksActivity : WokaBaseActivity() {
}
}
private fun onBookClicked(audioBookData: AudioBookData, position: Int){
private fun onBookClicked(audioBookData: AudioBookData) {
loadTrailerData(audioBookData)
showAudioDialog(audioBookData)
}
private fun onContinueBookClicked(audioBookData: ContinueAudioData) {
loadTrailerData(AudioBookData(audioBookData))
showAudioDialog(AudioBookData(audioBookData))
}
private fun onBookChanged(id: Int) {
// updating continue book list
val position = continueAudioAdapter.currentList.indexOfFirst { it.id == id }
if (position >= 0 && position < continueAudioAdapter.currentList.size) {
continueAudioAdapter.notifyItemChanged(position)
}
}
private fun onContinueBookChanged(id: Int) {
// updating book list
val position = audioBookAdapter.audioBookList.indexOfFirst { it.id == id }
if (position >= 0 && position < audioBookAdapter.audioBookList.size) {
audioBookAdapter.notifyItemChanged(position)
}
}
private fun onListenClicked(audioBookData: AudioBookData) {
var url: String? = null
var title = ""
audioBookData.content_more_details?.let {moreDetails ->
if (moreDetails.isNotEmpty()){
if (userPrefs?.appLanguage == "hi" && moreDetails.size > 1){
url = moreDetails[1]?.url
title = moreDetails[1]?.title?:""
}else{
url = moreDetails[0]?.url
title = moreDetails[0]?.title?:""
}
}else{
url = audioBookData.audio_url
title = audioBookData.title?:""
}
}
url?.let {
startActivity(Intent(this, PlayerActivity::class.java).apply {
putExtra(
PlayerActivity.EXTRA_PLAY_LIST,
VideoPlayList(
ArrayList<PlaylistItem>().apply {
add(
PlaylistItem.Builder()
.file(it)
.image(it)
.title(title)
.build()
)
},
null
)
)
putExtra(PlayerActivity.EXTRA_PLAY_INDEX, 0)
})
}
}
private fun showAudioDialog(audioBookData: AudioBookData) {
dialogBinding.apply {
audioBookData.content_more_details?.let { moreDetailsList ->
audioBookData.thumbnail_path?.let {
image.loadImage(it)
}
fav.isSelected = audioBookData.mark_as_favourite == true
like.isSelected = audioBookData.is_liked == true
year.text = try {
audioBookData.release_date?.let {
val cal = Calendar.getInstance()
cal.time =
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).parse(
audioBookData.release_date
)!!
"${cal.get(Calendar.YEAR)}"
} ?: throw Exception()
} catch (e: Exception) {
"${audioBookData.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 = audioBookData.title
description.text = Html.fromHtml(
audioBookData.description?.replace(
"<br>",
" "
), Html.FROM_HTML_MODE_LEGACY
)
}
watchCard.setOnClickListener {
onListenClicked(audioBookData)
}
like.setOnClickListener {
AudioBookRepository.likeUnLikeAudioBook(
"${audioBookData.id}",
!like.isSelected
)
audioBookData.id?.let {
onBookChanged(it)
onContinueBookChanged(it)
}
like.isSelected = !like.isSelected
}
fav.setOnClickListener {
AudioBookRepository.updateFavShow(
audioBookData,
!fav.isSelected
)
audioBookData.id?.let {
onBookChanged(it)
onContinueBookChanged(it)
}
fav.isSelected = !fav.isSelected
}
close.setOnClickListener {
audioDialog.dismiss()
}
audioDialog.show()
}
}
}
}

View File

@@ -1,18 +1,30 @@
package com.woka.home.fragments
import android.app.Dialog
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.InsetDrawable
import android.os.Bundle
import android.text.Html
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.SimpleItemAnimator
import com.jwplayer.pub.api.media.playlists.PlaylistItem
import com.woka.R
import com.woka.WokaApp
import com.woka.audiobooks.AudioBookRepository
import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.databinding.DialogAudioBookBinding
import com.woka.databinding.FragmentMyListBinding
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.adapters.FavAudioAdapter
@@ -21,11 +33,20 @@ import com.woka.home.mylist.adapters.KaraokeAdapter
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.networking.ApiResult
import com.woka.players.models.VideoPlayList
import com.woka.players.views.PlayerActivity
import com.woka.utils.TAG
import com.woka.utils.hide
import com.woka.utils.isNetworkConnected
import com.woka.utils.show
import com.woka.utils.toast
import com.woka.webseries.views.SeasonActivity
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class MyListFragment : Fragment() {
@@ -39,6 +60,9 @@ class MyListFragment : Fragment() {
private var webShowIntentLauncher: ActivityResultLauncher<Intent>? = null
private lateinit var dialogBinding: DialogAudioBookBinding
private lateinit var audioDialog: Dialog
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@@ -48,10 +72,17 @@ class MyListFragment : Fragment() {
// adapters
webSeriesEAdapter = WebSeriesAdapter(requireContext(),"1", ::onListGotEmpty)
webSeriesHAdapter = WebSeriesAdapter(requireContext(),"18", ::onListGotEmpty)
audioBooksAdapter = FavAudioAdapter(requireContext(), ::onListGotEmpty)
audioBooksAdapter = FavAudioAdapter(requireContext(), ::onListGotEmpty, ::onAudioBookClicked)
karaokeAdapter = KaraokeAdapter(requireContext(), ::onListGotEmpty)
gamesAdapter = GamesAdapter(requireContext(), ::onListGotEmpty)
// dialogs
dialogBinding = DialogAudioBookBinding.inflate(layoutInflater)
audioDialog = Dialog(requireContext())
audioDialog.setContentView(dialogBinding.root)
initAudioDialog()
initViews()
clickEvents()
@@ -211,6 +242,80 @@ class MyListFragment : Fragment() {
}
}
private fun initAudioDialog() {
try {
val back = ColorDrawable(Color.TRANSPARENT)
val inset = InsetDrawable(back, 50)
audioDialog.window!!.setBackgroundDrawable(inset)
} catch (e: Exception) {
// do nothing
}
try {
val layoutParams = audioDialog.window!!.attributes
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
audioDialog.window!!.setAttributes(layoutParams)
} catch (e: Exception) {
// do nothing
}
dialogBinding.close.setOnClickListener { audioDialog.dismiss() }
}
private fun onAudioItemChanged(id: Int, isRemoved: Boolean) {
// updating book list
val position = audioBooksAdapter.currentList.indexOfFirst { it.id == id }
if (position >= 0 && position < audioBooksAdapter.currentList.size) {
if (!isRemoved) audioBooksAdapter.notifyItemChanged(position)
else audioBooksAdapter.notifyItemRemoved(position)
}
}
private fun onAudioListenClicked(audioBookData: AudioBookData) {
var url: String? = null
var title = ""
audioBookData.content_more_details?.let {moreDetails ->
if (moreDetails.isNotEmpty()){
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetails.size > 1){
url = moreDetails[1]?.url
title = moreDetails[1]?.title?:""
}else{
url = moreDetails[0]?.url
title = moreDetails[0]?.title?:""
}
}else{
url = audioBookData.audio_url
title = audioBookData.title?:""
}
}
activity?.let {activity ->
url?.let {
startActivity(Intent(activity, PlayerActivity::class.java).apply {
putExtra(
PlayerActivity.EXTRA_PLAY_LIST,
VideoPlayList(
ArrayList<PlaylistItem>().apply {
add(
PlaylistItem.Builder()
.file(it)
.image(it)
.title(title)
.build()
)
},
null
)
)
putExtra(PlayerActivity.EXTRA_PLAY_INDEX, 0)
})
}
}
}
private fun onListGotEmpty(postType: PostType, isEng: Boolean = true){
binding.apply {
when (postType){
@@ -236,6 +341,7 @@ class MyListFragment : Fragment() {
}
}
// web show
private fun onWebShowClicked(showData: BookmarkedShowData, position:Int, categoryId: String){
webShowIntentLauncher?.launch(Intent(context, SeasonActivity::class.java).apply {
putExtra(SeasonActivity.EXTRA_SHOW_ID, showData.id)
@@ -257,6 +363,113 @@ class MyListFragment : Fragment() {
}
// audio books
private fun onAudioBookClicked(audioBookData: AudioBookData, position: Int){
dialogBinding.apply {
audioBookData.content_more_details?.let { moreDetailsList ->
audioBookData.thumbnail_path?.let {
image.loadImage(it)
}
fav.isSelected = audioBookData.mark_as_favourite == true
like.isSelected = audioBookData.is_liked == true
year.text = try {
audioBookData.release_date?.let {
val cal = Calendar.getInstance()
cal.time =
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).parse(
audioBookData.release_date
)!!
"${cal.get(Calendar.YEAR)}"
} ?: throw Exception()
} catch (e: Exception) {
"${audioBookData.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 = audioBookData.title
description.text = Html.fromHtml(
audioBookData.description?.replace(
"<br>",
" "
), Html.FROM_HTML_MODE_LEGACY
)
}
watchCard.setOnClickListener {
onAudioListenClicked(audioBookData)
}
like.setOnClickListener {
AudioBookRepository.likeUnLikeAudioBook(
"${audioBookData.id}",
!like.isSelected
)
audioBookData.id?.let {
onAudioItemChanged(it, false)
}
like.isSelected = !like.isSelected
}
fav.setOnClickListener {
if (context?.isNetworkConnected() == false){
toast(getString(R.string.no_internet))
return@setOnClickListener
}
AudioBookRepository.updateFavShow(
audioBookData,
!fav.isSelected
)
try {
audioBooksAdapter.notifyItemRemoved(position)
} catch (e: Exception) {
// do nothing
}
if (audioBooksAdapter.currentList.isEmpty()){
onListGotEmpty(PostType.AUDIO_BOOKS, true)
}
audioDialog.dismiss()
}
close.setOnClickListener {
audioDialog.dismiss()
}
audioDialog.show()
}
}
}
companion object {
fun newInstance() = MyListFragment()
}

View File

@@ -2,21 +2,13 @@ package com.woka.home.mylist
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woka.audiobooks.AudioBookRepository
import com.woka.home.mylist.models.AudioBookData
import com.woka.home.mylist.models.GameData
import com.woka.home.mylist.models.MyListResponse
import com.woka.home.mylist.models.PostType
import com.woka.home.mylist.models.Result
import com.woka.home.mylist.models.SingKaraokeData
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.userdata.UserRepository
import com.woka.webseries.WebSeriesRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.FormBody
object MyListRepository {
@@ -26,6 +18,7 @@ object MyListRepository {
if (shallLoadNewData){
// load new data
loadMyFavList()
shallLoadNewData = false
}else{
// also updating local changes
_myFavListLiveData.postValue(ApiResult.Success(myFavData))
@@ -45,11 +38,7 @@ object MyListRepository {
flag to load a new data whenever necessary
for eg. when user has signed in with new account and the apps hold the older repository
*/
private var shallLoadNewData: Boolean = false
init {
loadMyFavList()
}
private var shallLoadNewData: Boolean = true
fun clearData(){
shallLoadNewData = true

View File

@@ -7,24 +7,26 @@ import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import com.woka.R
import com.woka.WokaApp
import com.woka.audiobooks.AudioBookRepository
import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.databinding.FavViewHolderBinding
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.AudioBookData
import com.woka.home.mylist.models.FavAudioBookData
import com.woka.home.mylist.models.PostType
import com.woka.utils.isNetworkConnected
import com.woka.utils.show
import com.woka.utils.toast
import java.util.concurrent.Executors
import kotlin.math.max
class FavAudioAdapter(private val context: Context,
config: AsyncDifferConfig<AudioBookData>,
private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit)): ListAdapter<AudioBookData, FavoriteViewHolder>(config) {
config: AsyncDifferConfig<FavAudioBookData>,
private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit),
private var onBookClicked: (AudioBookData, Int) -> Unit): ListAdapter<FavAudioBookData, FavoriteViewHolder>(config) {
companion object{
private val DIFF_UTIL = object : DiffUtil.ItemCallback<AudioBookData>(){
override fun areItemsTheSame(oldItem: AudioBookData, newItem: AudioBookData): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: AudioBookData, newItem: AudioBookData): Boolean {
private val DIFF_UTIL = object : DiffUtil.ItemCallback<FavAudioBookData>(){
override fun areItemsTheSame(oldItem: FavAudioBookData, newItem: FavAudioBookData): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: FavAudioBookData, newItem: FavAudioBookData): Boolean {
return oldItem.title == newItem.title &&
oldItem.is_liked == newItem.is_liked &&
oldItem.likes_count == newItem.likes_count &&
@@ -38,7 +40,8 @@ class FavAudioAdapter(private val context: Context,
}
constructor(context: Context,
onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit)): this(context, DIFF_CONFIG, onListEmptyListener)
onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit),
onBookClicked: (AudioBookData, Int) -> Unit): this(context, DIFF_CONFIG, onListEmptyListener, onBookClicked)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteViewHolder {
return FavoriteViewHolder(
@@ -51,20 +54,34 @@ class FavAudioAdapter(private val context: Context,
}
override fun onBindViewHolder(holder: FavoriteViewHolder, pos: Int) {
val audioData = getItem(holder.absoluteAdapterPosition)
val audioBook = getItem(holder.absoluteAdapterPosition)
holder.binding.apply {
audioData.thumbnail_path?.let {
audioBook.thumbnail_path?.let {
image.loadImage(it)
}
title.text = audioData.title
audioBook.content_more_details?.let {moreDetailsList ->
title.text = if (moreDetailsList.isNotEmpty()){
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){
moreDetailsList[1]?.title
}else{
moreDetailsList[0]?.title
}
}else{
audioBook.title
}
}
audioData.likes_count?.let {
like.show()
likeCount.show()
fav.show()
audioBook.likes_count?.let {
likeCount.text = "$it"
}
audioData.is_liked?.let {
audioBook.is_liked?.let {
like.isSelected = it
}
@@ -74,10 +91,16 @@ class FavAudioAdapter(private val context: Context,
return@setOnClickListener
}
AudioBookRepository.likeUnLikeAudioBook(
"${audioBook.id}",
!like.isSelected
)
like.isSelected = !like.isSelected
likeCount.text = "${audioBook.likes_count}"
}
fav.isSelected = true
fav.isSelected = audioBook.mark_as_favourite == true
fav.setOnClickListener {
if (!context.isNetworkConnected()){
@@ -85,6 +108,20 @@ class FavAudioAdapter(private val context: Context,
return@setOnClickListener
}
AudioBookRepository.updateFavShow(
AudioBookData(audioBook),
!fav.isSelected
)
notifyItemRemoved(holder.absoluteAdapterPosition)
if (currentList.isEmpty()){
onListEmptyListener(PostType.AUDIO_BOOKS, true)
}
}
root.setOnClickListener {
onBookClicked(AudioBookData(audioBook), holder.absoluteAdapterPosition)
}
}
}

View File

@@ -1,24 +0,0 @@
package com.woka.home.mylist.models
data class AudioBookData(
val age_range_master_id: String?,
val audio_duration: String?,
val audio_url: 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 gender_master_id: String?,
val id: Int?,
var is_liked: Boolean?,
val language_master_id: Int?,
var likes_count: Int?,
var mark_as_favourite: Boolean?,
val media_id: String?,
val release_date: String?,
val tags_keyword: String?,
val thumbnail_path: String?,
val title: String?,
val views_count: Int?
)

View File

@@ -1,12 +0,0 @@
package com.woka.home.mylist.models
data class ContentMoreDetail(
val content_id: Int?,
val description: String?,
val id: Int?,
val language_master_id: Int?,
val post_type: Int?,
val tags_keywords: String?,
val title: String?,
val url: String?
)

View File

@@ -0,0 +1,50 @@
package com.woka.home.mylist.models
import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.audiobooks.models.audiodata.ContentMoreDetail
data class FavAudioBookData(
val age_range_master_id: String?,
val audio_duration: String?,
val audio_url: 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 gender_master_id: String?,
val id: Int?,
var is_liked: Boolean?,
val language_master_id: Int?,
var likes_count: Int?,
var mark_as_favourite: Boolean?,
val media_id: String?,
val release_date: String?,
val tags_keyword: String?,
val thumbnail_path: String?,
val title: String?,
val views_count: Int?
){
constructor(audio: AudioBookData): this(
audio.age_range_master_id,
audio.audio_duration,
audio.audio_url,
null,
audio.bookmark_count,
audio.category_master_id,
audio.content_more_details,
audio.description,
audio.gender_master_id,
audio.id,
audio.is_liked,
audio.language_master_id,
audio.likes_count,
audio.mark_as_favourite,
audio.media_id,
audio.release_date,
audio.tags_keyword,
audio.thumbnail_path,
audio.title,
audio.views_count
)
}

View File

@@ -5,7 +5,7 @@ data class GameData(
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<ContentMore>?,
val description: String?,
val game_url: String?,
val gender_master_id: String?,

View File

@@ -1,7 +1,7 @@
package com.woka.home.mylist.models
data class Result(
val audio_data: MutableList<AudioBookData>?,
val audio_data: MutableList<FavAudioBookData>?,
val game_data: MutableList<GameData>?,
val show_data: MutableList<BookmarkedShowData>?,
val sing_karaoke_data: MutableList<SingKaraokeData>?,

View File

@@ -5,7 +5,7 @@ data class SingKaraokeData(
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?,

View File

@@ -0,0 +1,269 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/img_season_bg"
android:orientation="vertical"
android:paddingBottom="35dp"
android:paddingTop="15dp">
<com.woka.utils.PressableImageView
android:id="@+id/close"
android:layout_width="25dp"
android:layout_height="25dp"
android:src="@drawable/ic_close_filled"
android:tint="@color/color_primary"
android:contentDescription="@string/image"
android:layout_gravity="end"
android:layout_marginEnd="15dp"
/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:cardBackgroundColor="@color/white"
app:cardElevation="3dp"
app:cardCornerRadius="15dp"
android:layout_marginHorizontal="15dp"
>
<com.woka.utils.AdiImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="@dimen/_120sdp"
android:src="@android:color/darker_gray"
android:contentDescription="@string/image"
android:scaleType="fitXY"
app:imageCornerRadius="15dp"
android:layout_margin="10dp"
/>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="The title of the blog will be displayed here"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/color_primary"
android:layout_marginTop="15dp"
android:layout_marginHorizontal="15dp"
android:maxLines="2"
android:ellipsize="end"
/>
<TextView
android:id="@+id/year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="2022"
android:fontFamily="@font/exo_2"
android:textColor="@color/color_primary"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="5dp"
/>
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="5dp"
>
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Description is here"
android:fontFamily="@font/exo_2"
android:textColor="@color/color_primary"
android:layout_marginHorizontal="15dp"
/>
</ScrollView>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:orientation="horizontal">
<Button
android:id="@+id/watch_card"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/round_bg_25"
android:backgroundTint="#007AC0"
android:drawableStart="@drawable/ic_play_filled"
android:drawablePadding="15dp"
android:fontFamily="@font/exo_2_extrabold"
android:paddingVertical="10dp"
android:paddingStart="15dp"
android:paddingEnd="20dp"
android:text="@string/listen_now"
android:textColor="@color/white"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/fav_season_LL"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/rate_season_ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/watch_card"
app:layout_constraintBottom_toBottomOf="@id/watch_card"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/like"
android:layout_width="@dimen/_24sdp"
android:layout_height="@dimen/_24sdp"
android:contentDescription="@string/image"
android:src="@drawable/ic_like_selector"
android:padding="3dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:textSize="11sp"
android:text="@string/rate"
android:fontFamily="@font/exo_2"
android:textColor="@color/color_primary" />
</LinearLayout>
<View
android:id="@+id/divider_1"
android:layout_width="0.5dp"
android:layout_height="40dp"
android:background="@color/color_primary"
android:layout_marginEnd="5dp"
app:layout_constraintEnd_toStartOf="@id/rate_season_ll"
app:layout_constraintTop_toTopOf="@id/watch_card"
app:layout_constraintBottom_toBottomOf="@id/watch_card"
/>
<LinearLayout
android:id="@+id/share_season_ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toStartOf="@id/divider_1"
app:layout_constraintTop_toTopOf="@id/watch_card"
app:layout_constraintBottom_toBottomOf="@id/watch_card"
android:gravity="center_horizontal"
android:layout_marginEnd="5dp"
android:orientation="vertical">
<ImageView
android:id="@+id/share"
android:layout_width="@dimen/_24sdp"
android:layout_height="@dimen/_23sdp"
android:contentDescription="@string/image"
android:src="@drawable/ic_share"
android:padding="3dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="11sp"
android:text="@string/share"
android:fontFamily="@font/exo_2"
android:textColor="@color/color_primary" />
</LinearLayout>
<View
android:id="@+id/divider_2"
android:layout_width="0.5dp"
android:layout_height="40dp"
android:background="@color/color_primary"
android:layout_marginEnd="5dp"
app:layout_constraintEnd_toStartOf="@id/share_season_ll"
app:layout_constraintTop_toTopOf="@id/watch_card"
app:layout_constraintBottom_toBottomOf="@id/watch_card"
/>
<LinearLayout
android:id="@+id/fav_season_LL"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toStartOf="@id/divider_2"
app:layout_constraintTop_toTopOf="@id/watch_card"
app:layout_constraintBottom_toBottomOf="@id/watch_card"
android:gravity="center_horizontal"
android:layout_marginEnd="5dp"
android:orientation="vertical">
<ImageView
android:id="@+id/fav"
android:layout_width="@dimen/_24sdp"
android:layout_height="@dimen/_24sdp"
android:contentDescription="@string/image"
android:src="@drawable/ic_heart_select"
android:padding="3dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:textSize="11sp"
android:text="@string/add"
android:fontFamily="@font/exo_2"
android:textColor="@color/color_primary" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View File

@@ -146,4 +146,5 @@
<string name="listen">सुनें</string>
<string name="listen_and_enjoy">सुनें और आनंद लें</string>
<string name="continue_audio_book">सुनना जारी रखें</string>
<string name="listen_now">सुनो अब</string>
</resources>

View File

@@ -188,4 +188,5 @@
<string name="listen">Listen</string>
<string name="listen_and_enjoy">LISTEN and ENJOY</string>
<string name="continue_audio_book">CONTINUE AUDIO BOOK</string>
<string name="listen_now">LISTEN NOW</string>
</resources>