Completed ui for AudioBooksActivity

Integrated api for audio book listing and completed caching

Organized code into repositories for both webshow and audio books.

continue audio books api integration and caching.

inflated all data

working on like functionality
This commit is contained in:
2024-07-03 21:06:20 +05:30
parent 69a8c34a57
commit a3ce40b251
35 changed files with 940 additions and 498 deletions

View File

@@ -0,0 +1,12 @@
package com.woka.audiobooks
import com.woka.audiobooks.models.audiodata.AudioBooksResponse
import com.woka.networking.ApiResponse
import retrofit2.Response
import retrofit2.http.POST
interface AudioBookApiService {
@POST("listen_audio_listing")
suspend fun audioBookListing(): Response<ApiResponse<AudioBooksResponse>>
}

View File

@@ -0,0 +1,203 @@
package com.woka.audiobooks
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
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.PostType
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.networking.RetrofitHelper.handleApiCall
import com.woka.userdata.UserActionApiService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.FormBody
import kotlin.math.max
object AudioBookRepository {
// api services
private val apiService = RetrofitHelper.getRetrofit().create(AudioBookApiService::class.java)
private val userActionApiService = RetrofitHelper.getRetrofit().create(UserActionApiService::class.java)
// live data
// audio books data (loose caching)
private val _audioBooksLiveData = MutableLiveData<ApiResult<AudioBooksResponse>>()
val audioBooksLiveData: LiveData<ApiResult<AudioBooksResponse>>
get() = _audioBooksLiveData
private var audioBooksData: AudioBooksResponse? = null
// continue watch audio books data
private val _continueAudioBooksLiveData = MutableLiveData<ApiResult<ContinueAudioResponse>>()
val continueAudioBooksLiveData: LiveData<ApiResult<ContinueAudioResponse>>
get() = _continueAudioBooksLiveData
private var continueAudioData: ContinueAudioResponse? = null
fun loadAudioBooks(){
if (audioBooksData != null){
_audioBooksLiveData.postValue(ApiResult.Success(audioBooksData))
return
}
CoroutineScope(Dispatchers.IO).launch{
_audioBooksLiveData.postValue(ApiResult.Loading())
val response = handleApiCall{
apiService.audioBookListing()
}
when (response){
is ApiResult.Error -> _audioBooksLiveData.postValue(ApiResult.Error(response.errorMessage, response.error))
is ApiResult.Loading -> _audioBooksLiveData.postValue(ApiResult.Loading())
is ApiResult.Success -> {
response.data?.let {
audioBooksData = it
_audioBooksLiveData.postValue(ApiResult.Success(it))
}?:{
_audioBooksLiveData.postValue(ApiResult.Error())
}
}
}
}
}
fun loadContinueListening(){
if (continueAudioData != null){
_continueAudioBooksLiveData.postValue(ApiResult.Success(continueAudioData))
return
}
CoroutineScope(Dispatchers.IO).launch {
val response = handleApiCall {
userActionApiService.continueAudioBookListing(
FormBody.Builder()
.add("post_type", "7")
.build()
)
}
when (response){
is ApiResult.Error -> {}
is ApiResult.Loading -> {}
is ApiResult.Success -> {
response.data?.let {
continueAudioData = it
}
}
}
_continueAudioBooksLiveData.postValue(response)
}
}
fun likeUnLikeAudioBook(postId: String, likeIt: Boolean){
CoroutineScope(Dispatchers.IO).launch {
handleApiCall {
if (likeIt){
userActionApiService.likePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", PostType.AUDIO_BOOKS.value)
.build()
)
}else{
userActionApiService.unLikePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", PostType.AUDIO_BOOKS.value)
.build()
)
}
}
changeLikeLocally(postId, likeIt)
}
}
private fun changeLikeLocally(id: String, isLiked: Boolean){
// changing in audio books locally
audioBooksData?.audio_data?.let {audioBooks ->
for (audio in audioBooks){
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){
if ("${audioData.id}" == id){
audioData.is_liked = isLiked
audioData.likes_count?.let { count ->
audioData.likes_count = if (isLiked) count + 1
else max(0, count - 1)
}
break
}
}
}
}
fun updateFavShow(id: Int?, addToBookmark: Boolean){
CoroutineScope(Dispatchers.IO).launch {
handleApiCall {
if (addToBookmark){
userActionApiService.addToFav(
FormBody.Builder()
.add("post_id", "$id")
.add("post_type", PostType.WEB_SERIES.value)
.build()
)
}else{
userActionApiService.removeFromFav(
FormBody.Builder()
.add("id", "$id")
.add("post_type", PostType.WEB_SERIES.value)
.build()
)
}
}
}
MyListRepository.myFavData.result?.audio_data?.let {
for (audio in it){
if (audio.id == id){
audio.mark_as_favourite = addToBookmark
break
}
}
}
audioBooksData?.audio_data?.filterNotNull()?.let {
for (audio in it){
if (audio.id == id){
audio.mark_as_favourite = addToBookmark
}
}
}
}
fun clearData(){
audioBooksData = null
continueAudioData = null
}
}

View File

@@ -0,0 +1,115 @@
package com.woka.audiobooks.adapters
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.woka.R
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
): RecyclerView.Adapter<AudioBooksAdapter.AudioBookViewHolder>() {
inner class AudioBookViewHolder(val binding: ShowViewHolderBinding): ViewHolder(binding.root)
private var audioBookList: List<AudioBookData> = ArrayList()
@SuppressLint("NotifyDataSetChanged")
fun submitListShowList(it: List<AudioBookData>) {
this.audioBookList = it
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AudioBookViewHolder {
return AudioBookViewHolder(
ShowViewHolderBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun getItemCount(): Int = audioBookList.size
override fun onBindViewHolder(holder: AudioBookViewHolder, position: Int) {
val audioBook = audioBookList[holder.absoluteAdapterPosition]
holder.binding.apply {
audioBook.thumbnail_path?.let {
image.loadImage(it)
}
audioBook.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{
audioBook.title
}
}
like.show()
likeCount.show()
fav.show()
audioBook.likes_count?.let {
likeCount.text = "$it"
}
audioBook.is_liked?.let {
like.isSelected = it
}
like.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
AudioBookRepository.likeUnLikeAudioBook(
"${audioBook.id}",
!fav.isSelected
)
like.isSelected = !like.isSelected
likeCount.text = "${audioBook.likes_count}"
}
fav.isSelected = audioBook.mark_as_favourite == true
fav.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
AudioBookRepository.updateFavShow(
audioBook.id,
!fav.isSelected
)
fav.isSelected = audioBook.mark_as_favourite == true
}
root.setOnClickListener {
onBookClicked(audioBook, holder.absoluteAdapterPosition)
}
}
}
}

View File

@@ -0,0 +1,87 @@
package com.woka.audiobooks.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 com.woka.R
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.toast
import java.util.concurrent.Executors
class ContinueAudioAdapter(private val context: Context,
config: AsyncDifferConfig<ContinueAudioData>): ListAdapter<ContinueAudioData, FavoriteViewHolder>(config) {
companion object{
private val DIFF_UTIL = object : DiffUtil.ItemCallback<ContinueAudioData>(){
override fun areItemsTheSame(oldItem: ContinueAudioData, newItem: ContinueAudioData): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: ContinueAudioData, newItem: ContinueAudioData): Boolean {
return oldItem.title == newItem.title &&
oldItem.is_liked == newItem.is_liked &&
oldItem.likes_count == newItem.likes_count &&
oldItem.mark_as_favourite == newItem.mark_as_favourite
}
}
private val DIFF_CONFIG = AsyncDifferConfig.Builder(DIFF_UTIL)
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
.build()
}
constructor(context: Context): this(context, DIFF_CONFIG)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteViewHolder {
return FavoriteViewHolder(
FavViewHolderBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: FavoriteViewHolder, pos: Int) {
val audioData = getItem(holder.absoluteAdapterPosition)
holder.binding.apply {
audioData.thumbnail_path?.let {
image.loadImage(it)
}
title.text = audioData.title
audioData.likes_count?.let {
likeCount.text = "$it"
}
audioData.is_liked?.let {
like.isSelected = it
}
like.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
}
fav.isSelected = audioData.mark_as_favourite == true
fav.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
}
}
}
}

View File

@@ -0,0 +1,27 @@
package com.woka.audiobooks.models.audiodata
data class AudioBookData(
val age_range_data: List<Any?>?,
val age_range_master_id: String?,
val audio_duration: String?,
val audio_url: String?,
val bookmark_count: Int?,
val category_data: List<CategoryData?>?,
val category_master_id: String?,
val content_more_details: List<ContentMoreDetail?>?,
val description: 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?,
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 user_video_view: List<Any?>?,
val views_count: Int?
)

View File

@@ -0,0 +1,6 @@
package com.woka.audiobooks.models.audiodata
data class AudioBooksResponse(
val audio_data: List<AudioBookData?>?,
val total_records: Int?
)

View File

@@ -0,0 +1,6 @@
package com.woka.audiobooks.models.audiodata
data class CategoryData(
val category_name: String?,
val id: Int?
)

View File

@@ -0,0 +1,12 @@
package com.woka.audiobooks.models.audiodata
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,12 @@
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

@@ -0,0 +1,25 @@
package com.woka.audiobooks.models.continuedata
data class ContinueAudioData(
val age_range_master_id: String?,
val audio_duration: String?,
val audio_url: 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?,
val is_liked: Boolean?,
val language_master_id: Int?,
val likes_count: Int?,
val mark_as_favourite: Boolean?,
val media_id: String?,
val release_date: String?,
val show_data_count: Any?,
val tags_keyword: String?,
val thumbnail_path: String?,
val title: String?,
val user_video_view: List<UserVideoView?>?,
val views_count: Int?
)

View File

@@ -0,0 +1,6 @@
package com.woka.audiobooks.models.continuedata
data class ContinueAudioResponse(
val result: List<ContinueAudioData?>?,
val total_records: Int?
)

View File

@@ -0,0 +1,11 @@
package com.woka.audiobooks.models.continuedata
data class UserVideoView(
val category_id: Int?,
val id: Int?,
val last_watched_left: String?,
val post_id: Int?,
val post_type: Int?,
val total_watched_duration: String?,
val user_id: Int?
)

View File

@@ -4,15 +4,27 @@ import android.os.Bundle
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.audiobooks.AudioBookRepository
import com.woka.audiobooks.adapters.AudioBooksAdapter
import com.woka.audiobooks.adapters.ContinueAudioAdapter
import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.databinding.ActivityAudioBooksBinding
import com.woka.networking.ApiResult
import com.woka.utils.WokaBaseActivity
import com.woka.utils.hide
import com.woka.utils.show
class AudioBooksActivity : WokaBaseActivity() {
private lateinit var binding: ActivityAudioBooksBinding
private lateinit var audioBookAdapter: AudioBooksAdapter
private lateinit var continueAudioAdapter: ContinueAudioAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
@@ -24,7 +36,20 @@ class AudioBooksActivity : WokaBaseActivity() {
insets
}
window.apply {
navigationBarColor = getColor(R.color.color_primary_dark)
}
audioBookAdapter = AudioBooksAdapter(this, ::onBookClicked)
continueAudioAdapter = ContinueAudioAdapter(this)
initViews()
clickEvents()
setObservers()
AudioBookRepository.loadAudioBooks()
}
private fun initViews(){
@@ -32,6 +57,109 @@ class AudioBooksActivity : WokaBaseActivity() {
adjustTrailerImage()
toolbar.title.text = getString(R.string.audio_books)
rvAudioBooks.adapter = audioBookAdapter
(rvAudioBooks.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
rvContinueListen.adapter = continueAudioAdapter
(rvContinueListen.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
}
}
private fun clickEvents(){
binding.apply {
toolbar.backBtn.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
retryBtn.setOnClickListener {
AudioBookRepository.loadAudioBooks()
}
}
}
private fun setObservers(){
AudioBookRepository.audioBooksLiveData.observe(this){
when (it){
is ApiResult.Error -> {
binding.shimmer.hide()
binding.rvAudioBooks.hide()
binding.listenTxt.hide()
binding.trailerView.hide()
binding.errorView.show()
}
is ApiResult.Loading -> {
binding.shimmer.show()
binding.rvAudioBooks.hide()
binding.listenTxt.hide()
binding.trailerView.hide()
binding.errorView.hide()
}
is ApiResult.Success -> {
it.data?.audio_data?.filterNotNull()?.let {audioBookData ->
if (audioBookData.isNotEmpty()){
binding.shimmer.hide()
binding.errorView.hide()
AudioBookRepository.loadContinueListening()
loadTrailerData(audioBookData[0])
binding.rvAudioBooks.show()
binding.listenTxt.show()
audioBookAdapter.submitListShowList(audioBookData)
}
}
}
}
}
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()){
binding.continueListenTxt.show()
binding.rvContinueListen.show()
continueAudioAdapter.submitList(continueData.toMutableList())
}else{
binding.continueListenTxt.hide()
binding.rvContinueListen.hide()
}
}
}
}
}
}
private fun loadTrailerData(audioBookData: AudioBookData){
binding.apply {
trailerView.show()
adjustTrailerImage()
audioBookData.thumbnail_path?.let {
trailerImage.loadImage(it)
}
audioBookData.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{
audioBookData.title
}
}
}
}
@@ -45,4 +173,8 @@ class AudioBooksActivity : WokaBaseActivity() {
}
}
}
private fun onBookClicked(audioBookData: AudioBookData, position: Int){
}
}

View File

@@ -2,7 +2,6 @@ package com.woka.home.fragments
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
@@ -16,17 +15,15 @@ import androidx.recyclerview.widget.SimpleItemAnimator
import com.woka.R
import com.woka.databinding.FragmentMyListBinding
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.adapters.AudioBooksAdapter
import com.woka.home.mylist.adapters.FavAudioAdapter
import com.woka.home.mylist.adapters.GamesAdapter
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.networking.ApiResult
import com.woka.utils.TAG
import com.woka.utils.hide
import com.woka.utils.show
import com.woka.webseries.models.ShowData
import com.woka.webseries.views.SeasonActivity
import kotlinx.coroutines.launch
@@ -36,7 +33,7 @@ class MyListFragment : Fragment() {
private lateinit var webSeriesEAdapter: WebSeriesAdapter
private lateinit var webSeriesHAdapter: WebSeriesAdapter
private lateinit var audioBooksAdapter: AudioBooksAdapter
private lateinit var audioBooksAdapter: FavAudioAdapter
private lateinit var karaokeAdapter: KaraokeAdapter
private lateinit var gamesAdapter: GamesAdapter
@@ -51,7 +48,7 @@ class MyListFragment : Fragment() {
// adapters
webSeriesEAdapter = WebSeriesAdapter(requireContext(),"1", ::onListGotEmpty)
webSeriesHAdapter = WebSeriesAdapter(requireContext(),"18", ::onListGotEmpty)
audioBooksAdapter = AudioBooksAdapter(requireContext(), ::onListGotEmpty)
audioBooksAdapter = FavAudioAdapter(requireContext(), ::onListGotEmpty)
karaokeAdapter = KaraokeAdapter(requireContext(), ::onListGotEmpty)
gamesAdapter = GamesAdapter(requireContext(), ::onListGotEmpty)

View File

@@ -2,11 +2,11 @@ package com.woka.home.mylist
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woka.home.mylist.models.AudioData
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.BookmarkedShowData
import com.woka.home.mylist.models.Result
import com.woka.home.mylist.models.SingKaraokeData
import com.woka.networking.ApiResult
@@ -17,12 +17,9 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.FormBody
import kotlin.math.max
object MyListRepository {
private val myFavApiService = RetrofitHelper.getRetrofit().create(MyFavApiService::class.java)
private val _myFavListLiveData = MutableLiveData<ApiResult<MyListResponse>>()
val myFavListLiveData: LiveData<ApiResult<MyListResponse>>
get() {
@@ -84,270 +81,4 @@ object MyListRepository {
_myFavListLiveData.postValue(response)
}
}
fun likePost(postId: String, postType: PostType, categoryId: String = "0"){
CoroutineScope(Dispatchers.IO).launch {
RetrofitHelper.handleApiCall {
myFavApiService.likePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", postType.value)
.build()
)
}
}
changeLikeLocally(postId, postType, true)
}
fun unLikePost(postId: String, postType: PostType) {
CoroutineScope(Dispatchers.IO).launch {
val response = RetrofitHelper.handleApiCall {
myFavApiService.unLikePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", postType.value)
.build()
)
}
}
changeLikeLocally(postId, postType, false)
}
fun markAsFavShowLocally(showData: BookmarkedShowData,
addToFav: Boolean,
categoryId: String){
CoroutineScope(Dispatchers.IO).launch {
RetrofitHelper.handleApiCall {
if (addToFav){
myFavApiService.addToFav(
FormBody.Builder()
.add("post_id", "${showData.id}")
.add("post_type", PostType.WEB_SERIES.value)
.add("category_id", categoryId)
.build()
)
}else{
myFavApiService.removeFromFav(
FormBody.Builder()
.add("id", "${showData.id}")
.add("post_type", PostType.WEB_SERIES.value)
.add("category_id", categoryId)
.build()
)
}
}
}
myFavData.result?.show_data?.let {
var found = false
var showFound: BookmarkedShowData? = null
for (show in it){
if (showData.id == show.id){
if (addToFav){
show.addAsBookMark(categoryId)
}else{
show.removeAsBookMark(categoryId)
}
showFound = show
found = true
break
}
}
if (!found && addToFav){
myFavData.result?.show_data?.add(showData)
}
if (found){
showFound?.let {bookMarkShowData ->
if (!bookMarkShowData.isBookMarked()){
it.remove(bookMarkShowData)
}
}
}
}
WebSeriesRepository.webSeriesData[categoryId]?.show_data?.let {
for (show in it){
var found = false
show?.let {data ->
if (showData.id == data.id){
found = true
if (addToFav){
show.addAsBookMark(categoryId)
}else{
show.removeAsBookMark(categoryId)
}
}
}
if (found) break
}
}
}
fun markAsFavAudioLocally(audioData: AudioData, addToFav: Boolean){
CoroutineScope(Dispatchers.IO).launch {
val response = RetrofitHelper.handleApiCall {
if (addToFav){
myFavApiService.addToFav(
FormBody.Builder()
.add("post_id", "${audioData.id}")
.add("post_type", PostType.AUDIO_BOOKS.value)
.build()
)
}else{
myFavApiService.removeFromFav(
FormBody.Builder()
.add("id", "${audioData.id}")
.add("post_type", PostType.AUDIO_BOOKS.value)
.build()
)
}
}
when (response){
is ApiResult.Error -> {}
is ApiResult.Loading -> {}
is ApiResult.Success -> {
myFavData?.result?.audio_data?.let {
if (addToFav){
it.add(audioData)
}else{
it.remove(audioData)
}
}
}
}
}
}
fun markAsFavKaraokeLocally(karaokeData: SingKaraokeData, addToFav: Boolean){
CoroutineScope(Dispatchers.IO).launch {
val response = RetrofitHelper.handleApiCall {
if (addToFav){
myFavApiService.addToFav(
FormBody.Builder()
.add("post_id", "${karaokeData.id}")
.add("post_type", PostType.KARAOKE.value)
.build()
)
}else{
myFavApiService.removeFromFav(
FormBody.Builder()
.add("id", "${karaokeData.id}")
.add("post_type", PostType.KARAOKE.value)
.build()
)
}
}
when (response){
is ApiResult.Error -> {}
is ApiResult.Loading -> {}
is ApiResult.Success -> {
myFavData?.result?.sing_karaoke_data?.let {
if (addToFav){
it.add(karaokeData)
}else{
it.remove(karaokeData)
}
}
}
}
}
}
fun markAsFavGameLocally(gameData: GameData, addToFav: Boolean){
CoroutineScope(Dispatchers.IO).launch {
val response = RetrofitHelper.handleApiCall {
if (addToFav){
myFavApiService.addToFav(
FormBody.Builder()
.add("post_id", "${gameData.id}")
.add("post_type", PostType.GAMES.value)
.build()
)
}else{
myFavApiService.removeFromFav(
FormBody.Builder()
.add("id", "${gameData.id}")
.add("post_type", PostType.GAMES.value)
.build()
)
}
}
when (response){
is ApiResult.Error -> {}
is ApiResult.Loading -> {}
is ApiResult.Success -> {
myFavData?.result?.game_data?.let {
if (addToFav){
it.add(gameData)
}else{
it.remove(gameData)
}
}
}
}
}
}
private fun changeLikeLocally(id: String, postType: PostType, isLiked: Boolean){
when(postType){
PostType.WEB_SERIES -> {
WebSeriesRepository.changeLikeLocally(id, isLiked)
}
PostType.AUDIO_BOOKS -> {
myFavData.result?.audio_data?.let {
for (audio in it){
if ("${audio.id}" == id){
audio.is_liked = isLiked
audio.likes_count?.let { count ->
audio.likes_count = if (isLiked) count + 1
else max(0, count - 1)
}
break
}
}
}
}
PostType.KARAOKE -> {
myFavData.result?.sing_karaoke_data?.let {
for (song in it){
if ("${song.id}" == id){
song.is_liked = isLiked
song.likes_count?.let { count ->
song.likes_count = if (isLiked) count + 1
else max(0, count - 1)
}
break
}
}
}
}
PostType.GAMES -> {
myFavData.result?.game_data?.let {
for (game in it){
if ("${game.id}" == id){
game.is_liked = isLiked
game.likes_count?.let { count ->
game.likes_count = if (isLiked) count + 1
else max(0, count - 1)
}
break
}
}
}
}
}
}
}

View File

@@ -6,28 +6,29 @@ 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.audiobooks.AudioBookRepository
import com.woka.databinding.FavViewHolderBinding
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.AudioData
import com.woka.home.mylist.models.AudioBookData
import com.woka.home.mylist.models.PostType
import com.woka.utils.isNetworkConnected
import com.woka.utils.toast
import java.util.concurrent.Executors
import kotlin.math.max
class AudioBooksAdapter(private val context: Context,
config: AsyncDifferConfig<AudioData>,
private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit)): ListAdapter<AudioData, FavoriteViewHolder>(config) {
class FavAudioAdapter(private val context: Context,
config: AsyncDifferConfig<AudioBookData>,
private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit)): ListAdapter<AudioBookData, FavoriteViewHolder>(config) {
companion object{
private val DIFF_UTIL = object : DiffUtil.ItemCallback<AudioData>(){
override fun areItemsTheSame(oldItem: AudioData, newItem: AudioData): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: AudioData, newItem: AudioData): Boolean {
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 {
return oldItem.title == newItem.title &&
oldItem.is_liked == newItem.is_liked &&
oldItem.likes_count == newItem.likes_count
oldItem.likes_count == newItem.likes_count &&
oldItem.mark_as_favourite == newItem.mark_as_favourite
}
}
@@ -73,28 +74,7 @@ class AudioBooksAdapter(private val context: Context,
return@setOnClickListener
}
if (like.isSelected){
MyListRepository.unLikePost(
"${audioData.id}",
PostType.AUDIO_BOOKS
)
audioData.likes_count?.let {
likeCount.text = "${max(it - 1, 0)}"
}
}else{
MyListRepository.likePost(
"${audioData.id}",
PostType.AUDIO_BOOKS
)
audioData.likes_count?.let {
val value = it + 1
likeCount.text = "$value"
}
}
like.isSelected = !like.isSelected
}
fav.isSelected = true
@@ -105,20 +85,6 @@ class AudioBooksAdapter(private val context: Context,
return@setOnClickListener
}
if (fav.isSelected){
MyListRepository.markAsFavAudioLocally(
audioData,
false
)
val currentList = currentList.toMutableList()
currentList.removeAt(holder.absoluteAdapterPosition)
submitList(currentList)
if (currentList.isEmpty()){
onListEmptyListener(PostType.AUDIO_BOOKS, false)
}
}
}
}
}

View File

@@ -73,28 +73,7 @@ class GamesAdapter(private val context: Context,
return@setOnClickListener
}
if (like.isSelected){
MyListRepository.unLikePost(
"${gameData.id}",
PostType.GAMES
)
gameData.likes_count?.let {
likeCount.text = "${max(it - 1, 0)}"
}
}else{
MyListRepository.likePost(
"${gameData.id}",
PostType.GAMES
)
gameData.likes_count?.let {
val value = it + 1
likeCount.text = "$value"
}
}
like.isSelected = !like.isSelected
}
fav.isSelected = true
@@ -105,20 +84,7 @@ class GamesAdapter(private val context: Context,
return@setOnClickListener
}
if (fav.isSelected){
MyListRepository.markAsFavGameLocally(
gameData,
false
)
val currentList = currentList.toMutableList()
currentList.removeAt(holder.absoluteAdapterPosition)
submitList(currentList)
if (currentList.isEmpty()){
onListEmptyListener(PostType.GAMES, false)
}
}
}
}
}

View File

@@ -74,28 +74,7 @@ class KaraokeAdapter(private val context: Context,
return@setOnClickListener
}
if (like.isSelected){
MyListRepository.unLikePost(
"${karaokeData.id}",
PostType.KARAOKE
)
karaokeData.likes_count?.let {
likeCount.text = "${max(it - 1, 0)}"
}
}else{
MyListRepository.likePost(
"${karaokeData.id}",
PostType.KARAOKE
)
karaokeData.likes_count?.let {
val value = it + 1
likeCount.text = "$value"
}
}
like.isSelected = !like.isSelected
}
fav.isSelected = true
@@ -106,20 +85,6 @@ class KaraokeAdapter(private val context: Context,
return@setOnClickListener
}
if (fav.isSelected){
MyListRepository.markAsFavKaraokeLocally(
karaokeData,
false
)
val currentList = currentList.toMutableList()
currentList.removeAt(holder.absoluteAdapterPosition)
submitList(currentList)
if (currentList.isEmpty()){
onListEmptyListener(PostType.KARAOKE, false)
}
}
}
}
}

View File

@@ -9,14 +9,14 @@ import androidx.recyclerview.widget.ListAdapter
import com.woka.R
import com.woka.WokaApp
import com.woka.databinding.FavViewHolderBinding
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.BookmarkedShowData
import com.woka.home.mylist.models.PostType
import com.woka.utils.isNetworkConnected
import com.woka.utils.show
import com.woka.utils.toast
import com.woka.webseries.WebSeriesRepository
import com.woka.webseries.models.ShowData
import java.util.concurrent.Executors
import kotlin.math.max
class WebSeriesAdapter(private val context: Context,
private val categoryId: String,
@@ -93,19 +93,22 @@ class WebSeriesAdapter(private val context: Context,
}
if (like.isSelected){
MyListRepository.unLikePost(
WebSeriesRepository.likeUnLikeShow(
"${showData.id}",
PostType.WEB_SERIES
false
)
}else{
MyListRepository.likePost(
WebSeriesRepository.likeUnLikeShow(
"${showData.id}",
PostType.WEB_SERIES
true
)
}
like.isSelected = !like.isSelected
likeCount.text = "${showData.likes_count}"
showData.likes_count?.let {
likeCount.text = "$it"
}
showData.id?.let {
onLikeChanged?.invoke(it)
}
@@ -131,8 +134,8 @@ class WebSeriesAdapter(private val context: Context,
}
if (fav.isSelected){
MyListRepository.markAsFavShowLocally(
showData,
WebSeriesRepository.updateFavShow(
ShowData(showData),
false,
categoryId
)

View File

@@ -1,6 +1,6 @@
package com.woka.home.mylist.models
data class AudioData(
data class AudioBookData(
val age_range_master_id: String?,
val audio_duration: String?,
val audio_url: String?,
@@ -14,7 +14,7 @@ data class AudioData(
var is_liked: Boolean?,
val language_master_id: Int?,
var likes_count: Int?,
val mark_as_favourite: Boolean?,
var mark_as_favourite: Boolean?,
val media_id: String?,
val release_date: String?,
val tags_keyword: String?,

View File

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

View File

@@ -1,5 +1,6 @@
package com.woka.modules
import com.woka.audiobooks.models.continuedata.ContinueAudioResponse
import com.woka.modules.blogs.models.BlogsResponse
import com.woka.modules.categorymodels.CategoriesResponse
import com.woka.modules.faqs.models.FaqResponse
@@ -31,7 +32,4 @@ interface ModuleApiService {
@POST("category_listing")
suspend fun categoryListing(@Body body: FormBody): Response<ApiResponse<CategoriesResponse>>
@POST("continue_watching")
suspend fun continueWatchingShowListing(@Body body: FormBody): Response<ApiResponse<ContinueEpisodeResponse>>
}

View File

@@ -19,6 +19,8 @@ import com.woka.home.views.HomeActivity
import com.woka.userdata.userDataModels.UserDataResponse
import com.woka.networking.ApiResult
import com.woka.userPreference.UserType
import com.woka.utils.hide
import com.woka.utils.show
import com.woka.utils.toast
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -52,6 +54,18 @@ class SplashFragment : Fragment(), Observer<ApiResult<UserDataResponse>?> {
// thus, loading data
userPrefs?.loadUserData()
}
clickEvents()
}
private fun clickEvents() {
binding.apply {
retryBtn.setOnClickListener {
retryBtn.hide()
progressBar.show()
userPrefs?.loadUserData()
}
}
}
private fun playBgMusic() {
@@ -118,9 +132,13 @@ class SplashFragment : Fragment(), Observer<ApiResult<UserDataResponse>?> {
when (value){
is ApiResult.Error -> {
toast(value.errorMessage)
binding.retryBtn.show()
binding.progressBar.hide()
}
is ApiResult.Loading -> {}
is ApiResult.Success -> {
binding.retryBtn.hide()
binding.progressBar.hide()
goForward()
}

View File

@@ -8,6 +8,7 @@ import android.content.SharedPreferences
import android.provider.Settings.Secure
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woka.audiobooks.AudioBookRepository
import com.woka.home.models.Theme
import com.woka.home.mylist.MyListRepository
import com.woka.networking.ApiResult
@@ -115,5 +116,6 @@ class UserPreference(val context: Context) {
private fun clearData(){
WebSeriesRepository.clearData()
MyListRepository.clearData()
AudioBookRepository.clearData()
}
}

View File

@@ -1,12 +1,14 @@
package com.woka.home.mylist
package com.woka.userdata
import com.woka.audiobooks.models.continuedata.ContinueAudioResponse
import com.woka.networking.ApiResponse
import com.woka.webseries.models.ContinueEpisodeResponse
import okhttp3.FormBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
interface MyFavApiService {
interface UserActionApiService {
@POST("post_like")
suspend fun likePost(@Body body: FormBody): Response<ApiResponse<Any>>
@@ -19,4 +21,10 @@ interface MyFavApiService {
@POST("favourite_remove")
suspend fun removeFromFav(@Body body: FormBody): Response<ApiResponse<Any>>
@POST("continue_watching")
suspend fun continueWatchingShowListing(@Body body: FormBody): Response<ApiResponse<ContinueEpisodeResponse>>
@POST("continue_watching")
suspend fun continueAudioBookListing(@Body body: FormBody): Response<ApiResponse<ContinueAudioResponse>>
}

View File

@@ -1,9 +1,11 @@
package com.woka.userdata
import com.woka.audiobooks.models.continuedata.ContinueAudioResponse
import com.woka.home.mylist.models.MyListResponse
import com.woka.home.notifications.models.NotificationData
import com.woka.userdata.userDataModels.UserDataResponse
import com.woka.networking.ApiResponse
import com.woka.webseries.models.ContinueEpisodeResponse
import okhttp3.FormBody
import retrofit2.Response
import retrofit2.http.Body

View File

@@ -3,7 +3,6 @@ package com.woka.webseries
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.jwplayer.pub.api.media.playlists.PlaylistItem
import com.woka.home.mylist.MyFavApiService
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.BookmarkedShowData
import com.woka.home.mylist.models.PostType
@@ -12,6 +11,7 @@ import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.players.models.VideoPlayList
import com.woka.players.models.VideoViewRequestData
import com.woka.userdata.UserActionApiService
import com.woka.webseries.models.ContinueEpisodeResponse
import com.woka.webseries.models.ShowData
import com.woka.webseries.models.WebSeriesResponse
@@ -27,8 +27,7 @@ import kotlin.math.max
object WebSeriesRepository {
// api services
private val apiService = RetrofitHelper.getRetrofit().create(WebSeriesApiService::class.java)
private val myFavApiService = RetrofitHelper.getRetrofit().create(MyFavApiService::class.java)
private val moduleApiService = RetrofitHelper.getRetrofit().create(ModuleApiService::class.java)
private val userActionApiService = RetrofitHelper.getRetrofit().create(UserActionApiService::class.java)
// live data
@@ -42,32 +41,10 @@ object WebSeriesRepository {
// continue watching (tight caching)
private val _continueWatchLiveData = MutableLiveData<ApiResult<ContinueEpisodeResponse>>()
val continueWatchLiveData: LiveData<ApiResult<ContinueEpisodeResponse>>
get() {
if (shallLoadNewContinueWatchData){
// load new data
loadContinueWatchData()
shallLoadNewContinueWatchData = false
}else{
// also updating local changes
continueWatchData?.let {
_continueWatchLiveData.postValue(ApiResult.Success(it))
}
}
return _continueWatchLiveData
}
get() = _continueWatchLiveData
var continueWatchData: ContinueEpisodeResponse? = null
init {
loadContinueWatchData()
}
/*
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 shallLoadNewContinueWatchData: Boolean = false
// seasonListing data
private val _seasonDataLiveData = MutableLiveData<ApiResult<SeasonDataResponse>>()
val seasonDataLiveData: LiveData<ApiResult<SeasonDataResponse>>
@@ -262,6 +239,7 @@ object WebSeriesRepository {
_seasonDataLiveData.postValue(ApiResult.Success(data = seasonDataMap["${showId}_${categoryId}"]))
return
}
CoroutineScope(Dispatchers.IO).launch {
_seasonDataLiveData.postValue(ApiResult.Loading())
val response = RetrofitHelper.handleApiCall {
@@ -287,11 +265,16 @@ object WebSeriesRepository {
}
}
private fun loadContinueWatchData(){
fun loadContinueWatchData(){
if (continueWatchData != null){
_continueWatchLiveData.postValue(ApiResult.Success(continueWatchData))
return
}
CoroutineScope(Dispatchers.IO).launch {
_continueWatchLiveData.postValue(ApiResult.Loading())
val response = RetrofitHelper.handleApiCall {
moduleApiService.continueWatchingShowListing(
userActionApiService.continueWatchingShowListing(
FormBody.Builder()
.add("post_type", "3")
.build()
@@ -346,18 +329,18 @@ object WebSeriesRepository {
}
}
fun likeUnLikeShow(postId: String, likeIt: Boolean, categoryId: String){
fun likeUnLikeShow(postId: String, likeIt: Boolean){
CoroutineScope(Dispatchers.IO).launch {
RetrofitHelper.handleApiCall {
if (likeIt){
myFavApiService.likePost(
userActionApiService.likePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", PostType.WEB_SERIES.value)
.build()
)
}else{
myFavApiService.unLikePost(
userActionApiService.unLikePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", PostType.WEB_SERIES.value)
@@ -365,12 +348,12 @@ object WebSeriesRepository {
)
}
}
changeLikeLocally(postId, likeIt)
}
changeLikeLocally(postId, likeIt)
}
fun changeLikeLocally(id: String, isLiked: Boolean){
private fun changeLikeLocally(id: String, isLiked: Boolean){
// changing in web series locally
for (showDataResponse in webSeriesData.values){
showDataResponse.show_data?.let {shows ->
@@ -395,7 +378,7 @@ object WebSeriesRepository {
}
// changing in fav list locally
MyListRepository.myFavData?.result?.show_data?.let {
MyListRepository.myFavData.result?.show_data?.let {
for (show in it){
if ("${show.id}" == id){
show.is_liked = isLiked
@@ -410,18 +393,86 @@ object WebSeriesRepository {
}
fun updateFavShow(showData: ShowData, addToBookmark: Boolean, categoryId: String){
MyListRepository.markAsFavShowLocally(
BookmarkedShowData(showData, categoryId),
addToBookmark,
categoryId
)
CoroutineScope(Dispatchers.IO).launch {
RetrofitHelper.handleApiCall {
if (addToBookmark){
userActionApiService.addToFav(
FormBody.Builder()
.add("post_id", "${showData.id}")
.add("post_type", PostType.WEB_SERIES.value)
.add("category_id", categoryId)
.build()
)
}else{
userActionApiService.removeFromFav(
FormBody.Builder()
.add("id", "${showData.id}")
.add("post_type", PostType.WEB_SERIES.value)
.add("category_id", categoryId)
.build()
)
}
}
}
MyListRepository.myFavData.result?.show_data?.let {
var found = false
var showFound: BookmarkedShowData? = null
for (show in it){
if (showData.id == show.id){
if (addToBookmark){
show.addAsBookMark(categoryId)
}else{
show.removeAsBookMark(categoryId)
}
showFound = show
found = true
break
}
}
if (!found && addToBookmark){
MyListRepository.myFavData.result?.show_data?.add(BookmarkedShowData(showData, categoryId))
}
if (found){
showFound?.let {bookMarkShowData ->
if (!bookMarkShowData.isBookMarked()){
it.remove(bookMarkShowData)
}
}
}
}
webSeriesData[categoryId]?.show_data?.let {
for (show in it){
var found = false
show?.let {data ->
if (showData.id == data.id){
found = true
if (addToBookmark){
show.addAsBookMark(categoryId)
}else{
show.removeAsBookMark(categoryId)
}
}
}
if (found) break
}
}
}
fun clearData(){
_webSeriesLiveData.postValue(ApiResult.Loading())
webSeriesData.clear()
_continueWatchLiveData.postValue(ApiResult.Loading())
shallLoadNewContinueWatchData = true
webSeriesData.clear()
continueWatchData = null
}
}

View File

@@ -84,23 +84,15 @@ class WebSeriesShowAdapter(
return@setOnClickListener
}
categoryId?.let {
if (like.isSelected){
WebSeriesRepository.likeUnLikeShow("${showData.id}", false, it)
if (like.isSelected){
WebSeriesRepository.likeUnLikeShow("${showData.id}", false)
}else{
WebSeriesRepository.likeUnLikeShow("${showData.id}", true)
}
showData.likes_count?.let {likeCountInt ->
likeCount.text = "${max(likeCountInt - 1, 0)}"
}
}else{
WebSeriesRepository.likeUnLikeShow("${showData.id}", true, it)
showData.likes_count?.let {likeCountInt ->
val value = likeCountInt + 1
likeCount.text = "$value"
}
}
like.isSelected = !like.isSelected
like.isSelected = !like.isSelected
showData.likes_count?.let {
likeCount.text = "$it"
}
}

View File

@@ -1,6 +1,6 @@
package com.woka.webseries.models
data class ContinueEpisodeResponse(
val result: List<ContinueEpisodeData>?,
val result: List<ContinueEpisodeData?>?,
val total_records: Int?
)

View File

@@ -201,27 +201,18 @@ class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener {
return@setOnClickListener
}
categoryId?.let {
if (likeSeason.isSelected) {
WebSeriesRepository.likeUnLikeShow("${showData?.id}", false, it)
showData?.likes_count?.let { likeCountInt ->
likeCount.text = "${max(likeCountInt - 1, 0)}"
}
} else {
WebSeriesRepository.likeUnLikeShow("${showData?.id}", true, it)
showData?.likes_count?.let { likeCountInt ->
val value = likeCountInt + 1
likeCount.text = "$value"
}
}
likeSeason.isSelected = !likeSeason.isSelected
setResult(RESULT_OK, Intent().apply {
putExtra(EXTRA_SHOW_ID, showId)
})
if (likeSeason.isSelected) {
WebSeriesRepository.likeUnLikeShow("${showData?.id}", false)
} else {
WebSeriesRepository.likeUnLikeShow("${showData?.id}", true)
}
likeSeason.isSelected = !likeSeason.isSelected
likeCount.text = "${showData?.likes_count}"
setResult(RESULT_OK, Intent().apply {
putExtra(EXTRA_SHOW_ID, showId)
})
}
favSeason.setOnClickListener {

View File

@@ -225,6 +225,7 @@ class WebSeriesActivity : WokaBaseActivity(), Observer<ApiResult<HashMap<String,
binding.categorySpinner.setAdapter(catSpinnerAdapter)
loadShowData()
WebSeriesRepository.loadContinueWatchData()
}
}
}

View File

@@ -132,7 +132,7 @@
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/trailer_view"
android:visibility="visible"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
@@ -142,7 +142,7 @@
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|snap|exitUntilCollapsed">
<ImageView
<com.woka.utils.AdiImageView
android:id="@+id/trailer_image"
android:layout_width="match_parent"
android:layout_height="@dimen/_160sdp"
@@ -185,6 +185,7 @@
/>
<Button
android:id="@+id/trailer_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -208,17 +209,74 @@
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_web_series"
android:visibility="visible"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/show_view_holder"
android:layout_marginTop="15dp"
android:layout_height="match_parent"
android:background="@color/color_primary_dark"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
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_listen_txt"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/continue_audio_book"
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_listen"
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/listen_txt"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/listen_and_enjoy"
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_audio_books"
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>

View File

@@ -22,4 +22,38 @@
android:transitionName="logo"
/>
<TextView
android:id="@+id/retry_btn"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/retry_underline"
android:fontFamily="@font/exo_2_semibold"
android:textColor="@color/color_primary"
android:textSize="@dimen/_14ssp"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="25dp"
android:padding="5dp"
/>
<ProgressBar
android:id="@+id/progress_bar"
android:visibility="gone"
android:layout_width="25dp"
android:layout_height="25dp"
android:indeterminateTint="@color/color_primary"
android:indeterminate="true"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="30dp"
/>
</RelativeLayout>

View File

@@ -103,7 +103,7 @@
<string name="theme">थीम</string>
<string name="hello">नमस्ते</string>
<string name="web_series">वेब सीरीज</string>
<string name="audio_books">ऑडियो-किताबें</string>
<string name="audio_books">सुनें</string>
<string name="play">खेल</string>
<string name="karaoke">कराओके</string>
<string name="shop">दुकान</string>
@@ -143,4 +143,7 @@
<string name="couldnt_play_video">वीडियो नहीं चलाया जा सका</string>
<string name="teasers">टीज़र</string>
<string name="episode">एपिसोड</string>
<string name="listen">सुनें</string>
<string name="listen_and_enjoy">सुनें और आनंद लें</string>
<string name="continue_audio_book">सुनना जारी रखें</string>
</resources>

View File

@@ -167,7 +167,7 @@
<string name="slash" translatable="false">/</string>
<string name="notifications" translatable="false">Notifications</string>
<string name="retry">Retry</string>
<string name="retry_underline"><u>Retry</u></string>
<string name="retry_underline" translatable="false"><u>Retry</u></string>
<string name="no_notifications_found" translatable="false">No notifications found</string>
<string name="favorites" translatable="false">Favorites</string>
<string name="web_series_hindi">WEB SERIES (HINDI)</string>
@@ -186,4 +186,6 @@
<string name="teasers">Teasers</string>
<string name="episode">Episode</string>
<string name="listen">Listen</string>
<string name="listen_and_enjoy">LISTEN and ENJOY</string>
<string name="continue_audio_book">CONTINUE AUDIO BOOK</string>
</resources>