From 8a3ca80f095ecc380e9ea96ec6d535ee7e742fa0 Mon Sep 17 00:00:00 2001 From: AdityaGaikwad Date: Thu, 18 Jul 2024 21:07:14 +0530 Subject: [PATCH] Teaser listing api in ViewModel. Creating playlist for episodes and teasers in viewmodel opening fragment from the MyListFragment: Receiving callback and updating data accordingly. Corrected home1 fragment's background timings Updating UI language of MyListFragment when user changes the language with the callback. NoSignInDialog : UI and functionality Implemented in MyListFragment --- app/src/main/AndroidManifest.xml | 10 +- .../com/woka/home/fragments/Home1Fragment.kt | 8 +- .../com/woka/home/fragments/MyListFragment.kt | 100 ++- .../java/com/woka/home/models/TimePeriod.kt | 11 +- .../com/woka/home/mylist/MyListRepository.kt | 41 +- .../home/mylist/adapters/WebSeriesAdapter.kt | 6 +- .../com/woka/userPreference/UserPreference.kt | 3 - .../java/com/woka/utils/NoSignInDialog.kt | 73 +++ .../java/com/woka/webseries/Repository.kt | 197 ------ .../com/woka/webseries/WebSeriesRepository.kt | 403 ++---------- .../adapters/WebSeriesShowAdapter.kt | 6 +- .../models/teaserdata/TeaserResponseData.kt | 2 +- .../com/woka/webseries/viewmodel/ViewModel.kt | 235 ------- .../webseries/viewmodel/WebSeriesViewModel.kt | 382 ++++++++++- .../woka/webseries/views/SeasonActivity.kt | 594 ------------------ .../woka/webseries/views/SeriesActivity.kt | 34 - .../woka/webseries/views/WebSeriesActivity.kt | 395 +----------- .../views/fragments/ShowChangeInterface.kt | 8 + .../views/fragments/WebSeriesFragment.kt | 22 +- .../views/fragments/WebShowFragment.kt | 394 +++++++----- app/src/main/res/drawable/ic_close_circle.xml | 17 + app/src/main/res/layout/activity_series.xml | 7 - .../main/res/layout/activity_web_series.xml | 324 +--------- app/src/main/res/layout/fragment_my_list.xml | 23 + .../res/layout/layout_no_sign_in_dialog.xml | 96 +++ app/src/main/res/values/strings.xml | 3 + 26 files changed, 1055 insertions(+), 2339 deletions(-) create mode 100644 app/src/main/java/com/woka/utils/NoSignInDialog.kt delete mode 100644 app/src/main/java/com/woka/webseries/Repository.kt delete mode 100644 app/src/main/java/com/woka/webseries/viewmodel/ViewModel.kt delete mode 100644 app/src/main/java/com/woka/webseries/views/SeasonActivity.kt delete mode 100644 app/src/main/java/com/woka/webseries/views/SeriesActivity.kt create mode 100644 app/src/main/java/com/woka/webseries/views/fragments/ShowChangeInterface.kt create mode 100644 app/src/main/res/drawable/ic_close_circle.xml delete mode 100644 app/src/main/res/layout/activity_series.xml create mode 100644 app/src/main/res/layout/layout_no_sign_in_dialog.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c4cb747..29cffec 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,7 +18,7 @@ android:theme="@style/Theme.Woka" tools:targetApi="31"> - - - onWebShowItemChanged(showId) + it.data?.getIntExtra(EXTRA_SHOW_ID, -1)?.let { showId -> + if (showId != -1){ + onWebShowItemChanged(showId) + } } } } @@ -144,6 +172,37 @@ class MyListFragment : Fragment() { private fun setObservers(){ binding.apply { + + viewModel.localeChangeLiveData.observe(viewLifecycleOwner){ + webSeriesEngTxt.text = getString(R.string.web_series_english) + webSeriesHinTxt.text = getString(R.string.web_series_hindi) + audioBooksTxt.text = getString(R.string.audio_books) + karaokeTxt.text = getString(R.string.karaoke) + gamesTxt.text = getString(R.string.games) + + noData.text = getString(R.string.no_favorites_added) + + if (webSeriesEAdapter.currentList.isNotEmpty()){ + webSeriesEAdapter.notifyItemRangeChanged(0, webSeriesEAdapter.currentList.size) + } + + if (webSeriesHAdapter.currentList.isNotEmpty()){ + webSeriesHAdapter.notifyItemRangeChanged(0, webSeriesHAdapter.currentList.size) + } + + if (audioBooksAdapter.currentList.isNotEmpty()){ + audioBooksAdapter.notifyItemRangeChanged(0, audioBooksAdapter.currentList.size) + } + + if (karaokeAdapter.currentList.isNotEmpty()){ + karaokeAdapter.notifyItemRangeChanged(0, karaokeAdapter.currentList.size) + } + + if (gamesAdapter.currentList.isNotEmpty()){ + gamesAdapter.notifyItemRangeChanged(0, gamesAdapter.currentList.size) + } + } + MyListRepository.myFavListLiveData.observe(viewLifecycleOwner){ lifecycleScope.launch { when (it){ @@ -151,7 +210,10 @@ class MyListFragment : Fragment() { progressBar.hide() noData.show() } - is ApiResult.Loading -> {} + is ApiResult.Loading -> { + progressBar.show() + noData.hide() + } is ApiResult.Success -> { it.data?.result?.let { result -> @@ -298,11 +360,10 @@ 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) - putExtra(SeasonActivity.EXTRA_SHOW_CATEGORY_DATA, categoryId) - putExtra(SeasonActivity.EXTRA_SHOW_POSITION, position) + private fun onWebShowClicked(showData: BookmarkedShowData, categoryId: String){ + webShowIntentLauncher?.launch(Intent(context, WebSeriesActivity::class.java).apply { + putExtra(EXTRA_SHOW_DATA, ShowData(showData)) + putExtra(EXTRA_SHOW_CATEGORY, categoryId) }) } @@ -316,7 +377,6 @@ class MyListFragment : Fragment() { if (hindiPosition > -1 && hindiPosition < webSeriesHAdapter.currentList.size){ webSeriesHAdapter.notifyItemChanged(hindiPosition) } - } // audio books @@ -347,7 +407,7 @@ class MyListFragment : Fragment() { if (moreDetailsList.isNotEmpty()) { - if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { + if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { moreDetailsList[1]?.let { data -> title.text = data.title description.text = Html.fromHtml( @@ -447,7 +507,7 @@ class MyListFragment : Fragment() { audioBookData.content_more_details?.let {moreDetails -> if (moreDetails.isNotEmpty()){ - if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetails.size > 1){ + if (userPrefs?.appLanguage == "hi" && moreDetails.size > 1){ url = moreDetails[1]?.url title = moreDetails[1]?.title?:"" }else{ @@ -512,7 +572,7 @@ class MyListFragment : Fragment() { if (moreDetailsList.isNotEmpty()) { - if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { + if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { moreDetailsList[1]?.let { data -> title.text = data.title description.text = Html.fromHtml( @@ -639,7 +699,7 @@ class MyListFragment : Fragment() { if (moreDetailsList.isNotEmpty()) { - if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { + if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { moreDetailsList[1]?.let { data -> title.text = data.title description.text = Html.fromHtml( diff --git a/app/src/main/java/com/woka/home/models/TimePeriod.kt b/app/src/main/java/com/woka/home/models/TimePeriod.kt index bd1322b..466e2b5 100644 --- a/app/src/main/java/com/woka/home/models/TimePeriod.kt +++ b/app/src/main/java/com/woka/home/models/TimePeriod.kt @@ -12,11 +12,18 @@ enum class TimePeriod{ fun getCurrentTimePeriod(): TimePeriod { val cal = Calendar.getInstance() val hrs = cal.get(Calendar.HOUR_OF_DAY) + val min = cal.get(Calendar.MINUTE) return when (hrs) { in 6..10 -> MORNING - in 11..15 -> AFTERNOON - in 16..19 -> EVENING + in 11..16 -> { + if (hrs == 16 && min >= 30) EVENING + else AFTERNOON + } + in 17..18 -> { + if (hrs == 18 && min >= 30) NIGHT + else EVENING + } else -> NIGHT } } diff --git a/app/src/main/java/com/woka/home/mylist/MyListRepository.kt b/app/src/main/java/com/woka/home/mylist/MyListRepository.kt index 7318a44..c0b3b64 100644 --- a/app/src/main/java/com/woka/home/mylist/MyListRepository.kt +++ b/app/src/main/java/com/woka/home/mylist/MyListRepository.kt @@ -14,17 +14,7 @@ object MyListRepository { private val _myFavListLiveData = MutableLiveData>() val myFavListLiveData: LiveData> - get() { - if (shallLoadNewData){ - // load new data - loadMyFavList() - shallLoadNewData = false - }else{ - // also updating local changes - _myFavListLiveData.postValue(ApiResult.Success(myFavData)) - } - return _myFavListLiveData - } + get() = _myFavListLiveData var myFavData: MyListResponse = MyListResponse(Result( mutableListOf(), @@ -51,23 +41,26 @@ object MyListRepository { } } - private fun loadMyFavList(){ - CoroutineScope(Dispatchers.IO).launch { - _myFavListLiveData.postValue(ApiResult.Loading()) - val response = UserRepository.loadMyFavList() + fun loadMyFavList(){ + if (shallLoadNewData) { + // shall load new data + CoroutineScope(Dispatchers.IO).launch { + _myFavListLiveData.postValue(ApiResult.Loading()) + val response = UserRepository.loadMyFavList() - when (response){ - is ApiResult.Error -> {} - is ApiResult.Loading -> {} - is ApiResult.Success -> { - response.data?.let { - myFavData = it - shallLoadNewData = false + when (response){ + is ApiResult.Error -> {} + is ApiResult.Loading -> {} + is ApiResult.Success -> { + response.data?.let { + myFavData = it + shallLoadNewData = false + } } } - } - _myFavListLiveData.postValue(response) + _myFavListLiveData.postValue(response) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/woka/home/mylist/adapters/WebSeriesAdapter.kt b/app/src/main/java/com/woka/home/mylist/adapters/WebSeriesAdapter.kt index c692dc2..c33e819 100644 --- a/app/src/main/java/com/woka/home/mylist/adapters/WebSeriesAdapter.kt +++ b/app/src/main/java/com/woka/home/mylist/adapters/WebSeriesAdapter.kt @@ -38,7 +38,7 @@ class WebSeriesAdapter(private val context: Context, .build() } - var onShowClickListener: ((BookmarkedShowData, Int, String) -> Unit)? = null + var onShowClickListener: ((BookmarkedShowData, String) -> Unit)? = null var onLikeChanged: ((Int) -> Unit)? = null constructor(context: Context, @@ -109,7 +109,7 @@ class WebSeriesAdapter(private val context: Context, showData.likes_count?.let { likeCount.text = "$it" } - showData.id?.let { + showData?.id?.let { onLikeChanged?.invoke(it) } } @@ -151,7 +151,7 @@ class WebSeriesAdapter(private val context: Context, } card.setOnClickListener { - onShowClickListener?.invoke(showData, holder.absoluteAdapterPosition, categoryId) + onShowClickListener?.invoke(showData, categoryId) } } diff --git a/app/src/main/java/com/woka/userPreference/UserPreference.kt b/app/src/main/java/com/woka/userPreference/UserPreference.kt index 336c895..2fc9bc9 100644 --- a/app/src/main/java/com/woka/userPreference/UserPreference.kt +++ b/app/src/main/java/com/woka/userPreference/UserPreference.kt @@ -8,10 +8,8 @@ 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.karaoke.KaraokeRepository import com.woka.networking.ApiResult import com.woka.onboard.views.OnboardActivity import com.woka.userdata.UserRepository @@ -115,7 +113,6 @@ class UserPreference(val context: Context) { } private fun clearData(){ - WebSeriesRepository.clearData() MyListRepository.clearData() } } \ No newline at end of file diff --git a/app/src/main/java/com/woka/utils/NoSignInDialog.kt b/app/src/main/java/com/woka/utils/NoSignInDialog.kt new file mode 100644 index 0000000..42f4b55 --- /dev/null +++ b/app/src/main/java/com/woka/utils/NoSignInDialog.kt @@ -0,0 +1,73 @@ +package com.woka.utils + +import android.app.Dialog +import android.content.Context +import android.content.Intent +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.InsetDrawable +import android.view.LayoutInflater +import android.view.WindowManager +import com.woka.databinding.LayoutNoSignInDialogBinding +import com.woka.onboard.views.OnboardActivity + +class NoSignInDialog(context: Context) { + + private val binding: LayoutNoSignInDialogBinding + + private val dialog: Dialog + + init { + binding = LayoutNoSignInDialogBinding.inflate( + LayoutInflater.from(context) + ) + + dialog = Dialog(context) + dialog.setContentView(binding.getRoot()) + dialog.setCancelable(false) + + binding.signIm.setOnClickListener { + dismiss() + context.startActivity(Intent(context, OnboardActivity::class.java).apply { + putExtra(OnboardActivity.ONBOARD_ACTIVITY_INTENT, OnboardActivity.LOG_IN_INTENT) + }) + } + + try { + val back = ColorDrawable(Color.TRANSPARENT) + val inset = InsetDrawable(back, 50) + dialog.window!!.setBackgroundDrawable(inset) + } catch (e: Exception) { + // do nothing + } + + try { + val layoutParams = dialog.window!!.attributes + layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT + layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT + dialog.window!!.setAttributes(layoutParams) + } catch (e: Exception) { + // do nothing + } + } + + fun show(titleTxt: String, messageTxt: String): NoSignInDialog{ + binding.apply { + title.text = titleTxt + message.text = messageTxt + }.also { + show() + } + return this + } + + fun closeListener(click: () -> Unit){ + binding.closeBtn.setOnClickListener { + click() + } + } + + fun show() = dialog.show() + + fun dismiss() = dialog.dismiss() +} \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/Repository.kt b/app/src/main/java/com/woka/webseries/Repository.kt deleted file mode 100644 index 34b1cf3..0000000 --- a/app/src/main/java/com/woka/webseries/Repository.kt +++ /dev/null @@ -1,197 +0,0 @@ -package com.woka.webseries - -import com.woka.home.mylist.MyListRepository -import com.woka.home.mylist.models.BookmarkedShowData -import com.woka.home.mylist.models.PostType -import com.woka.modules.categorymodels.CategoriesResponse -import com.woka.networking.ApiResult -import com.woka.networking.RetrofitHelper -import com.woka.networking.RetrofitHelper.handleApiCall -import com.woka.userdata.UserActionApiService -import com.woka.webseries.models.ContinueEpisodeResponse -import com.woka.webseries.models.ShowData -import com.woka.webseries.models.WebSeriesResponse -import com.woka.webseries.models.episodedata.EpisodeResponseData -import com.woka.webseries.models.seasondata.SeasonDataResponse -import com.woka.webseries.models.teaserdata.TeaserResponseData -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.FormBody -import kotlin.math.max - -object Repository { - // api services - private val apiService = RetrofitHelper.getRetrofit().create(WebSeriesApiService::class.java) - private val userActionApiService = RetrofitHelper.getRetrofit().create(UserActionApiService::class.java) - - suspend fun loadCategories(): ApiResult { - return handleApiCall { - apiService.categoryListing( - FormBody.Builder() - .add("module_id", "7") - .build() - ) - } - } - - suspend fun loadContinueWatchData(): ApiResult { - return handleApiCall { - userActionApiService.continueWatchingShowListing( - FormBody.Builder() - .add("post_type", "3") - .build() - ) - } - } - - suspend fun loadWebSeries(categoryId: String, pageNo: Int, quantity: Int): ApiResult { - return handleApiCall { - apiService.getWebSeries( - FormBody.Builder() - .add("category_id", categoryId) - .add("api_version", "v2") - .add("start", "$pageNo") - .add("limit", "$quantity") - .build() - ) - } - } - - suspend fun teaserListing(showId: Int, seasonId: Int): ApiResult { - return handleApiCall{ - apiService.teaserListing( - FormBody.Builder() - .add("watch_show_master_id", "$showId") - .add("season_master_id", "$seasonId") - .build() - ) - } - } - - suspend fun episodeListing( - showId: String, - seasonId: Int, - pageNo: Int, - quantity: Int - ): ApiResult { - return handleApiCall { - apiService.episodeListing( - FormBody.Builder() - .add("watch_show_master_id", showId) - .add("season_master_id", "$seasonId") - .add("api_version", "v2") - .add("start", "$pageNo") - .add("limit", "$quantity") - .build() - ) - } - } - - suspend fun seasonListing(showId: String, categoryId: String): ApiResult { - return handleApiCall { - apiService.seasonListing( - FormBody.Builder() - .add("watch_show_id", showId) - .add("category_id", categoryId) - .build() - ) - } - } - - fun likeUnLikeShow(postId: String, likeIt: Boolean){ - CoroutineScope(Dispatchers.IO).launch { - handleApiCall { - if (likeIt){ - userActionApiService.likePost( - FormBody.Builder() - .add("post_id", postId) - .add("post_type", PostType.WEB_SERIES.value) - .build() - ) - }else{ - userActionApiService.unLikePost( - FormBody.Builder() - .add("post_id", postId) - .add("post_type", PostType.WEB_SERIES.value) - .build() - ) - } - } - } - - changeLikeLocally(postId, likeIt) - } - - private fun changeLikeLocally(id: String, isLiked: Boolean){ - // changing in fav list locally - MyListRepository.myFavData.result?.show_data?.let { - for (show in it){ - if ("${show.id}" == id){ - show.is_liked = isLiked - show.likes_count?.let { count -> - show.likes_count = if (isLiked) count + 1 - else max(0, count - 1) - } - break - } - } - } - } - - fun updateFavShow(showData: ShowData, addToBookmark: Boolean, categoryId: String){ - CoroutineScope(Dispatchers.IO).launch { - 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) - } - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/WebSeriesRepository.kt b/app/src/main/java/com/woka/webseries/WebSeriesRepository.kt index e5ad08b..5ead369 100644 --- a/app/src/main/java/com/woka/webseries/WebSeriesRepository.kt +++ b/app/src/main/java/com/woka/webseries/WebSeriesRepository.kt @@ -1,16 +1,12 @@ 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.MyListRepository import com.woka.home.mylist.models.BookmarkedShowData import com.woka.home.mylist.models.PostType -import com.woka.modules.ModuleApiService +import com.woka.modules.categorymodels.CategoriesResponse 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.networking.RetrofitHelper.handleApiCall import com.woka.userdata.UserActionApiService import com.woka.webseries.models.ContinueEpisodeResponse import com.woka.webseries.models.ShowData @@ -29,309 +25,83 @@ object WebSeriesRepository { private val apiService = RetrofitHelper.getRetrofit().create(WebSeriesApiService::class.java) private val userActionApiService = RetrofitHelper.getRetrofit().create(UserActionApiService::class.java) - // live data - - // show data (loose caching) - private val _webSeriesLiveData = MutableLiveData>>() - val webSeriesLiveData: LiveData>> - get() = _webSeriesLiveData - - var webSeriesData = HashMap() - - // continue watching (tight caching) - private val _continueWatchLiveData = MutableLiveData>() - val continueWatchLiveData: LiveData> - get() = _continueWatchLiveData - - var continueWatchData: ContinueEpisodeResponse? = null - - // seasonListing data - private val _seasonDataLiveData = MutableLiveData>() - val seasonDataLiveData: LiveData> - get() = _seasonDataLiveData - - // seasons data for every show. where {key -> "showId_categoryId"} - var seasonDataMap = HashMap() - - // episode listing data - private val _episodeDataLiveData = MutableLiveData>() - val episodeDataLiveData: LiveData> - get() = _episodeDataLiveData - - // episode data for every season. where {key -> "showId_seasonId"} - private var episodeDataMap = HashMap() - // episodes playlist, where {key -> "showId_seasonId_categoryId"} - val episodesPlaylistMap = HashMap() - - // teaser listing data - private val _teaserDataLiveData = MutableLiveData>() - val teaserDataLiveData: LiveData> - get() = _teaserDataLiveData - - // teaser data for every season. where {key -> "showId_seasonId"} - private var teaserDataMap = HashMap() - // teasers playlist, where {key -> "showId_seasonId_categoryId"} - var teasersPlaylistMap = HashMap() - - fun loadTeaserData(showId: Int, seasonId: Int){ - if (teaserDataMap.containsKey("${showId}_${seasonId}")){ - _teaserDataLiveData.postValue(ApiResult.Success(data = teaserDataMap["${showId}_${seasonId}"])) - return - } - CoroutineScope(Dispatchers.IO).launch { - _teaserDataLiveData.postValue(ApiResult.Loading()) - val response = RetrofitHelper.handleApiCall { - apiService.teaserListing( - FormBody.Builder() - .add("watch_show_master_id", "$showId") - .add("season_master_id", "$seasonId") - .build() - ) - } - - when (response){ - is ApiResult.Error -> { - _teaserDataLiveData.postValue(response) - } - is ApiResult.Loading -> {} - is ApiResult.Success -> { - response.data?.let {teaserData -> - teaserDataMap["${showId}_${seasonId}"] = teaserData - } - - _teaserDataLiveData.postValue(response) - - // creating a playable playlist - teaserDataMap["${showId}_${seasonId}"]?.result?.filterNotNull()?.let { - val videoPlayListEng = VideoPlayList(ArrayList(), ArrayList()) - val videoPlayListHin = VideoPlayList(ArrayList(), ArrayList()) - - for (teaser in it){ - teaser.content_more_details?.let {moreDetailsList -> - if (moreDetailsList.isNotEmpty()){ - if (moreDetailsList.size > 1){ - moreDetailsList[1]?.let {moreDetail -> - videoPlayListHin.playlist.add( - PlaylistItem.Builder() - .file(moreDetail.content_hd_url) - .title(moreDetail.title) - .image(teaser.thumbnail_path) - .build() - ) - } - } - - moreDetailsList[0]?.let {moreDetail -> - videoPlayListEng.playlist.add( - PlaylistItem.Builder() - .file(moreDetail.content_hd_url) - .title(moreDetail.title) - .image(teaser.thumbnail_path) - .build() - ) - } - } - } - } - - teasersPlaylistMap["${showId}_${seasonId}_18"] = videoPlayListHin - teasersPlaylistMap["${showId}_${seasonId}_1"] = videoPlayListEng - } - } - } + suspend fun loadCategories(): ApiResult { + return handleApiCall { + apiService.categoryListing( + FormBody.Builder() + .add("module_id", "7") + .build() + ) } } - fun loadEpisodeData(showId: Int, seasonId: Int){ - if (episodeDataMap.containsKey("${showId}_${seasonId}")){ - _episodeDataLiveData.postValue(ApiResult.Success(data = episodeDataMap["${showId}_${seasonId}"])) - return - } - CoroutineScope(Dispatchers.IO).launch { - _episodeDataLiveData.postValue(ApiResult.Loading()) - val response = RetrofitHelper.handleApiCall { - apiService.episodeListing( - FormBody.Builder() - .add("watch_show_master_id", "$showId") - .add("season_master_id", "$seasonId") - .build() - ) - } - - when (response){ - is ApiResult.Error -> { - _episodeDataLiveData.postValue(response) - } - is ApiResult.Loading -> {} - is ApiResult.Success -> { - response.data?.let {episodeData -> - episodeDataMap["${showId}_${seasonId}"] = episodeData - } - - _episodeDataLiveData.postValue(response) - - // creating a playable playlist - episodeDataMap["${showId}_${seasonId}"]?.result?.filterNotNull()?.let { - - val videoPlayListItemHin = VideoPlayList(ArrayList(), ArrayList()) - val videoPlayListItemEng = VideoPlayList(ArrayList(), ArrayList()) - - for (episode in it){ - episode.content_more_details?.let {moreDetailsList -> - if (moreDetailsList.isNotEmpty()){ - if (moreDetailsList.size > 1){ - moreDetailsList[1]?.let {moreDetail -> - videoPlayListItemHin.playlist.add( - PlaylistItem.Builder() - .file(moreDetail.content_hd_url) - .title(moreDetail.title) - .image(episode.thumbnail_path) - .build() - ) - - videoPlayListItemHin.videoViewRequestDataList?.add( - VideoViewRequestData( - post_id = "${episode.id}", - post_type = "3", - total_watched_duration = null, - category_id = "18" - ) - ) - } - } - - moreDetailsList[0]?.let {moreDetail -> - videoPlayListItemEng.playlist.add( - PlaylistItem.Builder() - .file(moreDetail.content_hd_url) - .title(moreDetail.title) - .image(episode.thumbnail_path) - .build() - ) - - videoPlayListItemEng.videoViewRequestDataList?.add( - VideoViewRequestData( - post_id = "${episode.id}", - post_type = "3", - total_watched_duration = null, - category_id = "1" - ) - ) - } - } - } - } - - episodesPlaylistMap["${showId}_${seasonId}_18"] = videoPlayListItemHin - episodesPlaylistMap["${showId}_${seasonId}_1"] = videoPlayListItemEng - } - } - } + suspend fun loadContinueWatchData(): ApiResult { + return handleApiCall { + userActionApiService.continueWatchingShowListing( + FormBody.Builder() + .add("post_type", "3") + .build() + ) } } - fun clearEpisodeData(){ - _episodeDataLiveData.postValue(ApiResult.Loading()) - } - - fun loadSeasonListing(showId: Int, categoryId: String){ - if (seasonDataMap.containsKey("${showId}_${categoryId}")){ - _seasonDataLiveData.postValue(ApiResult.Success(data = seasonDataMap["${showId}_${categoryId}"])) - return - } - - CoroutineScope(Dispatchers.IO).launch { - _seasonDataLiveData.postValue(ApiResult.Loading()) - val response = RetrofitHelper.handleApiCall { - apiService.seasonListing( - FormBody.Builder() - .add("watch_show_id", "$showId") - .add("category_id", categoryId) - .build() - ) - } - - when (response){ - is ApiResult.Error -> {} - is ApiResult.Loading -> {} - is ApiResult.Success -> { - response.data?.let {seasonList -> - seasonDataMap["${showId}_${categoryId}"] = seasonList - } - - _seasonDataLiveData.postValue(ApiResult.Success(response.data)) - } - } + suspend fun loadWebSeries(categoryId: String, pageNo: Int, quantity: Int): ApiResult { + return handleApiCall { + apiService.getWebSeries( + FormBody.Builder() + .add("category_id", categoryId) + .add("api_version", "v2") + .add("start", "$pageNo") + .add("limit", "$quantity") + .build() + ) } } - fun loadContinueWatchData(){ - if (continueWatchData != null){ - _continueWatchLiveData.postValue(ApiResult.Success(continueWatchData)) - return - } - - CoroutineScope(Dispatchers.IO).launch { - _continueWatchLiveData.postValue(ApiResult.Loading()) - val response = RetrofitHelper.handleApiCall { - userActionApiService.continueWatchingShowListing( - FormBody.Builder() - .add("post_type", "3") - .build() - ) - } - - when (response){ - is ApiResult.Error -> {} - is ApiResult.Loading -> {} - is ApiResult.Success -> { - continueWatchData = response.data - } - } - - _continueWatchLiveData.postValue(response) + suspend fun teaserListing(showId: String, seasonId: Int): ApiResult { + return handleApiCall{ + apiService.teaserListing( + FormBody.Builder() + .add("watch_show_master_id", showId) + .add("season_master_id", "$seasonId") + .build() + ) } } - fun loadWebSeries(categoryId: String){ - if (webSeriesData.containsKey(categoryId)){ - webSeriesData[categoryId]?.let { - _webSeriesLiveData.postValue(ApiResult.Success(webSeriesData)) - return - } + suspend fun episodeListing( + showId: String, + seasonId: Int, + pageNo: Int, + quantity: Int + ): ApiResult { + return handleApiCall { + apiService.episodeListing( + FormBody.Builder() + .add("watch_show_master_id", showId) + .add("season_master_id", "$seasonId") + .add("api_version", "v2") + .add("start", "$pageNo") + .add("limit", "$quantity") + .build() + ) } + } - CoroutineScope(Dispatchers.IO).launch { - _webSeriesLiveData.postValue(ApiResult.Loading()) - - val response = RetrofitHelper.handleApiCall { - apiService.getWebSeries( - FormBody.Builder() - .add("category_id", categoryId) - .build() - ) - } - - when (response){ - is ApiResult.Error -> { - _webSeriesLiveData.postValue(ApiResult.Error(response.errorMessage, response.error)) - } - is ApiResult.Loading -> { - _webSeriesLiveData.postValue(ApiResult.Loading()) - } - is ApiResult.Success -> { - response.data?.let { - webSeriesData[categoryId] = it - _webSeriesLiveData.postValue(ApiResult.Success(data = webSeriesData)) - } - } - } + suspend fun seasonListing(showId: String, categoryId: String): ApiResult { + return handleApiCall { + apiService.seasonListing( + FormBody.Builder() + .add("watch_show_id", showId) + .add("category_id", categoryId) + .build() + ) } } fun likeUnLikeShow(postId: String, likeIt: Boolean){ CoroutineScope(Dispatchers.IO).launch { - RetrofitHelper.handleApiCall { + handleApiCall { if (likeIt){ userActionApiService.likePost( FormBody.Builder() @@ -354,29 +124,6 @@ object WebSeriesRepository { } private fun changeLikeLocally(id: String, isLiked: Boolean){ - // changing in web series locally - for (showDataResponse in webSeriesData.values){ - showDataResponse.show_data?.let {shows -> - for (show in shows){ - var found = false - show?.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?.show_data?.let { for (show in it){ @@ -394,7 +141,7 @@ object WebSeriesRepository { fun updateFavShow(showData: ShowData, addToBookmark: Boolean, categoryId: String){ CoroutineScope(Dispatchers.IO).launch { - RetrofitHelper.handleApiCall { + handleApiCall { if (addToBookmark){ userActionApiService.addToFav( FormBody.Builder() @@ -446,33 +193,5 @@ object WebSeriesRepository { } } } - - 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()) - _continueWatchLiveData.postValue(ApiResult.Loading()) - - webSeriesData.clear() - continueWatchData = null } } \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/adapters/WebSeriesShowAdapter.kt b/app/src/main/java/com/woka/webseries/adapters/WebSeriesShowAdapter.kt index 80b5ad3..6875488 100644 --- a/app/src/main/java/com/woka/webseries/adapters/WebSeriesShowAdapter.kt +++ b/app/src/main/java/com/woka/webseries/adapters/WebSeriesShowAdapter.kt @@ -12,7 +12,7 @@ import com.woka.databinding.ShowViewHolderBinding import com.woka.utils.isNetworkConnected import com.woka.utils.show import com.woka.utils.toast -import com.woka.webseries.Repository +import com.woka.webseries.WebSeriesRepository import com.woka.webseries.models.ShowData import kotlin.math.max @@ -85,7 +85,7 @@ class WebSeriesShowAdapter( return@setOnClickListener } - Repository.likeUnLikeShow("${showData.id}", !like.isSelected) + WebSeriesRepository.likeUnLikeShow("${showData.id}", !like.isSelected) showData.likes_count?.let { showData.likes_count = if (like.isSelected){ @@ -118,7 +118,7 @@ class WebSeriesShowAdapter( } categoryId?.let { - Repository.updateFavShow( + WebSeriesRepository.updateFavShow( showData, !fav.isSelected, it diff --git a/app/src/main/java/com/woka/webseries/models/teaserdata/TeaserResponseData.kt b/app/src/main/java/com/woka/webseries/models/teaserdata/TeaserResponseData.kt index b7f2987..421d375 100644 --- a/app/src/main/java/com/woka/webseries/models/teaserdata/TeaserResponseData.kt +++ b/app/src/main/java/com/woka/webseries/models/teaserdata/TeaserResponseData.kt @@ -1,6 +1,6 @@ package com.woka.webseries.models.teaserdata data class TeaserResponseData( - val result: List?, + val result: MutableList?, val total_records: Int? ) \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/viewmodel/ViewModel.kt b/app/src/main/java/com/woka/webseries/viewmodel/ViewModel.kt deleted file mode 100644 index deb1d06..0000000 --- a/app/src/main/java/com/woka/webseries/viewmodel/ViewModel.kt +++ /dev/null @@ -1,235 +0,0 @@ -package com.woka.webseries.viewmodel - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.woka.modules.categorymodels.CategoriesResponse -import com.woka.networking.ApiResult -import com.woka.players.models.VideoPlayList -import com.woka.webseries.Repository -import com.woka.webseries.models.ContinueEpisodeResponse -import com.woka.webseries.models.ShowData -import com.woka.webseries.models.episodedata.EpisodeData -import com.woka.webseries.models.seasondata.SeasonData -import kotlinx.coroutines.launch - -class ViewModel : ViewModel() { - - private val repository = Repository - - data class PagingData( - var nextPageToLoad: Int = 0, var quantityPerPage: Int = 6, - var lastPage: Boolean = false - ) - - // categories listing - - private val _showCategoryLiveData = MutableLiveData>() - val showCategoryLiveData: LiveData> - get() = _showCategoryLiveData - - var categoryPagingData = HashMap() - - fun loadCategories() { - viewModelScope.launch { - _showCategoryLiveData.postValue(ApiResult.Loading()) - _showCategoryLiveData.postValue(repository.loadCategories()) - } - } - - // continue watching - private val _continueWatchLiveData = MutableLiveData>() - val continueWatchLiveData: LiveData> - get() = _continueWatchLiveData - - fun loadContinueWatching() { - viewModelScope.launch { - _continueWatchLiveData.postValue(ApiResult.Loading()) - _continueWatchLiveData.postValue(repository.loadContinueWatchData()) - } - } - - // show data - private val _webSeriesLiveData = - MutableLiveData>>() - val webSeriesLiveData: LiveData>> - get() = _webSeriesLiveData - - // map of series data where key is category - private var webSeriesData = HashMap>() - - fun loadWebSeries(categoryId: String){ - if (webSeriesData.containsKey(categoryId) && webSeriesData[categoryId]?.isNotEmpty() == true){ - _webSeriesLiveData.postValue(ApiResult.Success(webSeriesData[categoryId])) - }else{ - loadMoreWebSeries(categoryId) - } - } - - fun loadMoreWebSeries(categoryId: String) { - viewModelScope.launch { - _webSeriesLiveData.postValue(ApiResult.Loading()) - - val pagingData = if (categoryPagingData.containsKey(categoryId)){ - categoryPagingData[categoryId]!! - }else{ - val pagingData = PagingData() - categoryPagingData[categoryId] = pagingData - pagingData - } - - when (val response = repository.loadWebSeries(categoryId, pagingData.nextPageToLoad, pagingData.quantityPerPage)) { - is ApiResult.Error -> { - _webSeriesLiveData.postValue( - ApiResult.Error( - response.errorMessage, - response.error - ) - ) - } - - is ApiResult.Loading -> { - _webSeriesLiveData.postValue(ApiResult.Loading()) - } - - is ApiResult.Success -> { - response.data?.let { data -> - data.show_data?.filterNotNull()?.let { newList -> - val currentList = webSeriesData.getOrDefault(categoryId, ArrayList()) - currentList.addAll(newList) - webSeriesData[categoryId] = currentList - - pagingData.lastPage = webSeriesData[categoryId]?.size == data.total_records - - _webSeriesLiveData.postValue(ApiResult.Success(webSeriesData[categoryId])) - pagingData.nextPageToLoad++ - } - } - } - } - } - } - - fun showCommonDataChanged(showData: ShowData, categoryId: String) { - for (cat in webSeriesData.keys){ - if (cat == categoryId) continue - - webSeriesData[cat]?.let {showList -> - for (show in showList){ - if (show.id == showData.id){ - - // updating common data between categorical lists of show - show.likes_count = showData.likes_count - show.is_liked = showData.is_liked - - break - } - } - } - } - } - - // seasonListing data - private val _seasonListingLiveData = MutableLiveData>>() - val seasonListingLiveData: LiveData>> - get() = _seasonListingLiveData - - // seasons data for every show. where {key -> "showId_categoryId"} - var seasonListingMap = HashMap>() - - fun seasonListing(showId: String, categoryId: String){ - if (seasonListingMap.containsKey("${showId}_${categoryId}")){ - _seasonListingLiveData.postValue(ApiResult.Success(seasonListingMap["${showId}_${categoryId}"])) - return - } - - viewModelScope.launch { - when (val response = repository.seasonListing(showId, categoryId)){ - is ApiResult.Error -> {_seasonListingLiveData.postValue(ApiResult.Error(response.errorMessage, response.error))} - is ApiResult.Loading -> {} - is ApiResult.Success -> { - response.data?.result?.filterNotNull()?.toMutableList()?.let { - seasonListingMap["${showId}_${categoryId}"] = it - _seasonListingLiveData.postValue(ApiResult.Success(it)) - } - } - } - } - } - - fun clearSeasonLiveData() { - _seasonListingLiveData.postValue(ApiResult.Loading()) - } - - // episode listing data - private val _episodeListingLiveData = MutableLiveData>>() - val episodeListingLiveData: LiveData>> - get() = _episodeListingLiveData - - var episodePagingData = HashMap() - - // episode data for every season. where {key -> "showId_seasonId"} - private var episodeDataMap = HashMap>() - // episodes playlist, where {key -> "showId_seasonId_categoryId"} - val episodesPlaylistMap = HashMap() - - fun loadEpisodes(showId: String, seasonId: Int){ - val key = "${showId}_$seasonId" - if (episodeDataMap.containsKey(key) && episodeDataMap[key]?.isNotEmpty() == true){ - _episodeListingLiveData.postValue(ApiResult.Success(episodeDataMap[key])) - }else{ - loadMoreEpisodes(showId, seasonId) - } - } - - fun loadMoreEpisodes(showId: String, seasonId: Int) { - viewModelScope.launch { - _episodeListingLiveData.postValue(ApiResult.Loading()) - - val key = "${showId}_$seasonId" - - val pagingData = if (episodePagingData.containsKey(key)){ - episodePagingData[key]!! - }else{ - val pagingData = PagingData() - episodePagingData[key] = pagingData - pagingData - } - - when (val response = repository.episodeListing(showId, seasonId, pagingData.nextPageToLoad, pagingData.quantityPerPage)) { - is ApiResult.Error -> { - _episodeListingLiveData.postValue( - ApiResult.Error( - response.errorMessage, - response.error - ) - ) - } - - is ApiResult.Loading -> { - _episodeListingLiveData.postValue(ApiResult.Loading()) - } - - is ApiResult.Success -> { - response.data?.let { data -> - data.result?.filterNotNull()?.let { newList -> - val currentList = episodeDataMap.getOrDefault(key, ArrayList()) - currentList.addAll(newList) - episodeDataMap[key] = currentList - - pagingData.lastPage = episodeDataMap[key]?.size == data.total_records - - _episodeListingLiveData.postValue(ApiResult.Success(episodeDataMap[key])) - pagingData.nextPageToLoad++ - } - } - } - } - } - } - - fun clearEpisodeListingLiveData(){ - _episodeListingLiveData.postValue(ApiResult.Loading()) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/viewmodel/WebSeriesViewModel.kt b/app/src/main/java/com/woka/webseries/viewmodel/WebSeriesViewModel.kt index 4bb00e5..f30f8ae 100644 --- a/app/src/main/java/com/woka/webseries/viewmodel/WebSeriesViewModel.kt +++ b/app/src/main/java/com/woka/webseries/viewmodel/WebSeriesViewModel.kt @@ -1,17 +1,389 @@ package com.woka.webseries.viewmodel import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.jwplayer.pub.api.media.playlists.PlaylistItem +import com.woka.modules.categorymodels.CategoriesResponse import com.woka.networking.ApiResult +import com.woka.players.models.VideoPlayList import com.woka.webseries.WebSeriesRepository import com.woka.webseries.models.ContinueEpisodeResponse -import com.woka.webseries.models.WebSeriesResponse +import com.woka.webseries.models.ShowData +import com.woka.webseries.models.episodedata.EpisodeData +import com.woka.webseries.models.seasondata.SeasonData +import com.woka.webseries.models.teaserdata.TeaserData +import kotlinx.coroutines.launch -class WebSeriesViewModel: ViewModel() { +class WebSeriesViewModel : ViewModel() { - val webSeriesLiveData: LiveData>> - get() = WebSeriesRepository.webSeriesLiveData + private val repository = WebSeriesRepository + data class PagingData( + var nextPageToLoad: Int = 0, var quantityPerPage: Int = 6, + var lastPage: Boolean = false + ) + + // categories listing + + private val _showCategoryLiveData = MutableLiveData>() + val showCategoryLiveData: LiveData> + get() = _showCategoryLiveData + + var categoryPagingData = HashMap() + + fun loadCategories() { + viewModelScope.launch { + _showCategoryLiveData.postValue(ApiResult.Loading()) + _showCategoryLiveData.postValue(repository.loadCategories()) + } + } + + // continue watching + private val _continueWatchLiveData = MutableLiveData>() val continueWatchLiveData: LiveData> - get() = WebSeriesRepository.continueWatchLiveData + get() = _continueWatchLiveData + + fun loadContinueWatching() { + viewModelScope.launch { + _continueWatchLiveData.postValue(ApiResult.Loading()) + _continueWatchLiveData.postValue(repository.loadContinueWatchData()) + } + } + + // show data + private val _webSeriesLiveData = + MutableLiveData>>() + val webSeriesLiveData: LiveData>> + get() = _webSeriesLiveData + + // map of series data where key is category + private var webSeriesData = HashMap>() + + fun loadWebSeries(categoryId: String) { + if (webSeriesData.containsKey(categoryId) && webSeriesData[categoryId]?.isNotEmpty() == true) { + _webSeriesLiveData.postValue(ApiResult.Success(webSeriesData[categoryId])) + } else { + loadMoreWebSeries(categoryId) + } + } + + fun loadMoreWebSeries(categoryId: String) { + viewModelScope.launch { + _webSeriesLiveData.postValue(ApiResult.Loading()) + + val pagingData = if (categoryPagingData.containsKey(categoryId)) { + categoryPagingData[categoryId]!! + } else { + val pagingData = PagingData() + categoryPagingData[categoryId] = pagingData + pagingData + } + + when (val response = repository.loadWebSeries( + categoryId, + pagingData.nextPageToLoad, + pagingData.quantityPerPage + )) { + is ApiResult.Error -> { + _webSeriesLiveData.postValue( + ApiResult.Error( + response.errorMessage, + response.error + ) + ) + } + + is ApiResult.Loading -> { + _webSeriesLiveData.postValue(ApiResult.Loading()) + } + + is ApiResult.Success -> { + response.data?.let { data -> + data.show_data?.filterNotNull()?.let { newList -> + val currentList = webSeriesData.getOrDefault(categoryId, ArrayList()) + currentList.addAll(newList) + webSeriesData[categoryId] = currentList + + pagingData.lastPage = + webSeriesData[categoryId]?.size == data.total_records + pagingData.nextPageToLoad++ + _webSeriesLiveData.postValue(ApiResult.Success(webSeriesData[categoryId])) + } + } + } + } + } + } + + fun showCommonDataChanged(showData: ShowData, categoryId: String) { + for (cat in webSeriesData.keys) { + if (cat == categoryId) continue + + webSeriesData[cat]?.let { showList -> + for (show in showList) { + if (show.id == showData.id) { + + // updating common data between categorical lists of show + show.likes_count = showData.likes_count + show.is_liked = showData.is_liked + + break + } + } + } + } + } + + // seasonListing data + private val _seasonListingLiveData = MutableLiveData>>() + val seasonListingLiveData: LiveData>> + get() = _seasonListingLiveData + + // seasons data for every show. where {key -> "showId_categoryId"} + var seasonListingMap = HashMap>() + + fun seasonListing(showId: String, categoryId: String) { + if (seasonListingMap.containsKey("${showId}_${categoryId}")) { + _seasonListingLiveData.postValue(ApiResult.Success(seasonListingMap["${showId}_${categoryId}"])) + return + } + + viewModelScope.launch { + when (val response = repository.seasonListing(showId, categoryId)) { + is ApiResult.Error -> { + _seasonListingLiveData.postValue( + ApiResult.Error( + response.errorMessage, + response.error + ) + ) + } + + is ApiResult.Loading -> {} + is ApiResult.Success -> { + response.data?.result?.filterNotNull()?.toMutableList()?.let { + seasonListingMap["${showId}_${categoryId}"] = it + _seasonListingLiveData.postValue(ApiResult.Success(it)) + } + } + } + } + } + + fun clearSeasonLiveData() { + _seasonListingLiveData.postValue(ApiResult.Loading()) + } + + // episode listing data + private val _episodeListingLiveData = MutableLiveData>>() + val episodeListingLiveData: LiveData>> + get() = _episodeListingLiveData + + var episodePagingData = HashMap() + + // episode data for every season. where {key -> "showId_seasonId"} + private var episodeDataMap = HashMap>() + + // episodes playlist, where {key -> "showId_seasonId_categoryId"} + val episodesPlaylistMap = HashMap() + + fun loadEpisodes(showId: String, seasonId: Int) { + val key = "${showId}_$seasonId" + if (episodeDataMap.containsKey(key) && episodeDataMap[key]?.isNotEmpty() == true) { + _episodeListingLiveData.postValue(ApiResult.Success(episodeDataMap[key])) + } else { + loadMoreEpisodes(showId, seasonId) + } + } + + fun loadMoreEpisodes(showId: String, seasonId: Int) { + viewModelScope.launch { + _episodeListingLiveData.postValue(ApiResult.Loading()) + + val key = "${showId}_$seasonId" + + val pagingData = if (episodePagingData.containsKey(key)) { + episodePagingData[key]!! + } else { + val pagingData = PagingData() + episodePagingData[key] = pagingData + pagingData + } + + when (val response = repository.episodeListing( + showId, + seasonId, + pagingData.nextPageToLoad, + pagingData.quantityPerPage + )) { + is ApiResult.Error -> { + _episodeListingLiveData.postValue( + ApiResult.Error( + response.errorMessage, + response.error + ) + ) + } + + is ApiResult.Loading -> { + _episodeListingLiveData.postValue(ApiResult.Loading()) + } + + is ApiResult.Success -> { + response.data?.let { data -> + data.result?.filterNotNull()?.let { newList -> + val currentList = episodeDataMap.getOrDefault(key, ArrayList()) + currentList.addAll(newList) + episodeDataMap[key] = currentList + + pagingData.lastPage = episodeDataMap[key]?.size == data.total_records + pagingData.nextPageToLoad++ + _episodeListingLiveData.postValue(ApiResult.Success(episodeDataMap[key])) + + val currentPlayListEng = + episodesPlaylistMap["${key}_1"] ?: VideoPlayList( + ArrayList(), + ArrayList() + ) + val currentPlayListHin = + episodesPlaylistMap["${key}_18"] ?: VideoPlayList( + ArrayList(), + ArrayList() + ) + + for (episode in newList) { + episode.content_more_details?.let { moreDetailsList -> + if (moreDetailsList.isNotEmpty()) { + if (moreDetailsList.size > 1) { + moreDetailsList[1]?.let { moreDetail -> + currentPlayListHin.playlist.add( + PlaylistItem.Builder() + .file(moreDetail.content_hd_url) + .title(moreDetail.title) + .image(episode.thumbnail_path) + .build() + ) + } + } + + moreDetailsList[0]?.let { moreDetail -> + currentPlayListEng.playlist.add( + PlaylistItem.Builder() + .file(moreDetail.content_hd_url) + .title(moreDetail.title) + .image(episode.thumbnail_path) + .build() + ) + } + } + } + } + + episodesPlaylistMap["${key}_18"] = currentPlayListHin + episodesPlaylistMap["${key}_1"] = currentPlayListEng + + } + } + } + } + } + } + + fun clearEpisodeListingLiveData() { + _episodeListingLiveData.postValue(ApiResult.Loading()) + } + + // teaser listing + private val _teaserListingLiveData = MutableLiveData>>() + val teaserListingLiveData: LiveData>> + get() = _teaserListingLiveData + + // teaser data for every season. where {key -> "showId_seasonId"} + private var teaserDataMap = HashMap>() + + // teaser playlist, where {key -> "showId_seasonId_categoryId"} + val teaserPlaylistMap = HashMap() + + fun loadTeasers(showId: String, seasonId: Int) { + val key = "${showId}_$seasonId" + if (teaserDataMap.containsKey(key) && teaserDataMap[key]?.isNotEmpty() == true) { + _teaserListingLiveData.postValue(ApiResult.Success(teaserDataMap[key])) + return + } + + viewModelScope.launch { + _teaserListingLiveData.postValue(ApiResult.Loading()) + + when (val response = repository.teaserListing(showId, seasonId)) { + is ApiResult.Error -> { + _teaserListingLiveData.postValue( + ApiResult.Error( + response.errorMessage, + response.error + ) + ) + } + + is ApiResult.Loading -> { + _teaserListingLiveData.postValue(ApiResult.Loading()) + } + + is ApiResult.Success -> { + response.data?.let { data -> + data.result?.filterNotNull()?.toMutableList()?.let { newList -> + teaserDataMap[key] = newList + _teaserListingLiveData.postValue(ApiResult.Success(teaserDataMap[key])) + + val currentPlayListEng = teaserPlaylistMap["${key}_1"] ?: VideoPlayList( + ArrayList(), + ArrayList() + ) + val currentPlayListHin = + teaserPlaylistMap["${key}_18"] ?: VideoPlayList( + ArrayList(), + ArrayList() + ) + + for (teaser in newList) { + teaser.content_more_details?.let { moreDetailsList -> + if (moreDetailsList.isNotEmpty()) { + if (moreDetailsList.size > 1) { + moreDetailsList[1]?.let { moreDetail -> + currentPlayListHin.playlist.add( + PlaylistItem.Builder() + .file(moreDetail.content_hd_url) + .title(moreDetail.title) + .image(teaser.thumbnail_path) + .build() + ) + } + } + + moreDetailsList[0]?.let { moreDetail -> + currentPlayListEng.playlist.add( + PlaylistItem.Builder() + .file(moreDetail.content_hd_url) + .title(moreDetail.title) + .image(teaser.thumbnail_path) + .build() + ) + } + } + } + } + + teaserPlaylistMap["${key}_18"] = currentPlayListHin + teaserPlaylistMap["${key}_1"] = currentPlayListEng + } + } + } + } + } + } + + fun clearTeaserListingLiveData() { + _teaserListingLiveData.postValue(ApiResult.Loading()) + } } \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/views/SeasonActivity.kt b/app/src/main/java/com/woka/webseries/views/SeasonActivity.kt deleted file mode 100644 index 03d6cfe..0000000 --- a/app/src/main/java/com/woka/webseries/views/SeasonActivity.kt +++ /dev/null @@ -1,594 +0,0 @@ -package com.woka.webseries.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.view.WindowManager -import androidx.activity.enableEdgeToEdge -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import com.google.android.material.tabs.TabLayout -import com.google.android.material.tabs.TabLayout.OnTabSelectedListener -import com.jwplayer.pub.api.media.playlists.PlaylistItem -import com.woka.R -import com.woka.WokaApp.Companion.userPrefs -import com.woka.databinding.ActivitySeasonBinding -import com.woka.databinding.DialogEpisodeBinding -import com.woka.home.mylist.MyListRepository -import com.woka.networking.ApiResult -import com.woka.players.views.PlayerActivity -import com.woka.players.views.PlayerActivity.Companion.EXTRA_PLAY_INDEX -import com.woka.players.views.PlayerActivity.Companion.EXTRA_PLAY_LIST -import com.woka.players.models.VideoPlayList -import com.woka.utils.ProgressView -import com.woka.utils.WokaBaseActivity -import com.woka.utils.hide -import com.woka.utils.isNetworkConnected -import com.woka.utils.lightStatusBar -import com.woka.utils.show -import com.woka.utils.toast -import com.woka.webseries.WebSeriesRepository -import com.woka.webseries.adapters.EpisodeAdapter -import com.woka.webseries.adapters.TeaserAdapter -import com.woka.webseries.models.ShowData -import com.woka.webseries.models.episodedata.EpisodeData -import com.woka.webseries.models.teaserdata.TeaserData -import kotlin.math.max - -class SeasonActivity : WokaBaseActivity(), OnTabSelectedListener { - - companion object { - const val EXTRA_SHOW_ID = "extra_show_id_data" - const val EXTRA_SHOW_CATEGORY_DATA = "extra_show_category_data" - const val EXTRA_SHOW_POSITION = "extra_show_position" - } - - private lateinit var binding: ActivitySeasonBinding - - private var showId: Int = -1 - private var categoryId: String? = null - private var showData: ShowData? = null - private var showPosition: Int = -1 - - private lateinit var progressView: ProgressView - - private lateinit var episodeAdapter: EpisodeAdapter - private lateinit var teaserAdapter: TeaserAdapter - - private var selectedSeasonId = -1 - - private lateinit var episodeDialogBinding: DialogEpisodeBinding - private lateinit var episodeDialog: Dialog - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - binding = ActivitySeasonBinding.inflate(layoutInflater) - setContentView(binding.root) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - - with(window) { - statusBarColor = Color.parseColor("#D3EFF8") - lightStatusBar(true) - } - - showId = intent.getIntExtra(EXTRA_SHOW_ID, -1) - categoryId = intent.getStringExtra(EXTRA_SHOW_CATEGORY_DATA) - showPosition = intent.getIntExtra(EXTRA_SHOW_POSITION, -1) - - if (showId == -1 || categoryId == null) { - finish() - return - } - - episodeAdapter = EpisodeAdapter(this) - teaserAdapter = TeaserAdapter(this) - - progressView = ProgressView(this) - progressView.show(getString(R.string.please_wait)) - - WebSeriesRepository.webSeriesData[categoryId]?.show_data?.let { - for (show in it) { - if (showId == show?.id) { - showData = show - break - } - } - } - - if (showData == null) { - MyListRepository.myFavData.result?.show_data?.let { - for (show in it) { - if (showId == show.id) { - showData = ShowData(show) - break - } - } - } - } - - initViews() - - initEpisodeDialog() - - clickEvents() - - setObservers() - - WebSeriesRepository.loadSeasonListing(showId, categoryId!!) - } - - override fun onDestroy() { - super.onDestroy() - WebSeriesRepository.clearEpisodeData() - } - - private fun initViews() { - if (showData != null && categoryId != null) { - binding.apply { - - likeCount.text = "${showData!!.likes_count}" - - favSeason.isSelected = showData!!.isBookMarked(categoryId!!) - - likeSeason.isSelected = showData!!.is_liked ?: false - - binding.seasonsTab.addOnTabSelectedListener(this@SeasonActivity) - - image.onLoadSuccessListener = { playTrailer.show() } - - rvEpisodes.adapter = episodeAdapter - episodeAdapter.onEpisodeClicked = ::onEpisodeClicked - episodeAdapter.onEpisodePlayClicked = ::onEpisodePlayClicked - - rvTeaser.adapter = teaserAdapter - teaserAdapter.onEpisodeClicked = ::onTeaserClicked - teaserAdapter.onEpisodePlayClicked = ::onTeaserPlayClicked - } - } - } - - - private fun initEpisodeDialog() { - episodeDialogBinding = DialogEpisodeBinding.inflate(layoutInflater) - episodeDialog = Dialog(this) - - episodeDialog.setContentView(episodeDialogBinding.root) - - try { - val back = ColorDrawable(Color.TRANSPARENT) - val inset = InsetDrawable(back, 50) - episodeDialog.window!!.setBackgroundDrawable(inset) - } catch (e: Exception) { - // do nothing - } - - try { - val layoutParams = episodeDialog.window!!.attributes - layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT - layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT - episodeDialog.window!!.setAttributes(layoutParams) - } catch (e: Exception) { - // do nothing - } - - episodeDialogBinding.close.setOnClickListener { episodeDialog.dismiss() } - } - - - private fun clickEvents() { - binding.apply { - backBtn.setOnClickListener { - onBackPressedDispatcher.onBackPressed() - } - - watchCard.setOnClickListener { - playTrailer.performClick() - } - - likeSeason.setOnClickListener { - if (!isNetworkConnected()) { - toast(getString(R.string.no_internet)) - return@setOnClickListener - } - - 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 { - if (!isNetworkConnected()) { - toast(getString(R.string.no_internet)) - return@setOnClickListener - } - - if (showData == null) return@setOnClickListener - - categoryId?.let { - WebSeriesRepository.updateFavShow( - showData!!, - !favSeason.isSelected, - it - ) - - favSeason.isSelected = !favSeason.isSelected - - setResult(RESULT_OK, Intent().apply { - putExtra(EXTRA_SHOW_ID, showId) - }) - } - } - - playTrailer.setOnClickListener { - if (seasonsTab.selectedTabPosition >= 0) { - WebSeriesRepository.seasonDataMap["${showId}_${categoryId}"]?.result?.let { seasonList -> - if (seasonsTab.selectedTabPosition < seasonList.size) { - seasonList[seasonsTab.selectedTabPosition]?.let { seasonData -> - - seasonData.season_more_details?.let { moreDetailsList -> - if (moreDetailsList.isNotEmpty()) { - val videoPlayList = VideoPlayList(ArrayList()) - - val playlistItem = PlaylistItem.Builder() - - if (categoryId == "18" && moreDetailsList.size > 1) { - moreDetailsList[1]?.let { seasonMoreData -> - playlistItem.title(seasonMoreData.title) - playlistItem.image(seasonMoreData.trailer_hd_url) - playlistItem.file(seasonMoreData.trailer_hd_url) - } - } else { - moreDetailsList[0]?.let { seasonMoreData -> - playlistItem.title(seasonMoreData.title) - playlistItem.image(seasonMoreData.trailer_hd_url) - playlistItem.file(seasonMoreData.trailer_hd_url) - } - } - - videoPlayList.playlist.add(playlistItem.build()) - - startActivity( - Intent(this@SeasonActivity, PlayerActivity::class.java) - .apply { - putExtra( - EXTRA_PLAY_LIST, - videoPlayList - ) - } - ) - } - } - } - } - } - } - } - } - } - - private fun setObservers() { - WebSeriesRepository.seasonDataLiveData.observe(this) { - binding.seasonsTab.removeAllTabs() - when (it) { - is ApiResult.Error -> { - progressView.hide() - } - - is ApiResult.Loading -> { - progressView.show() - } - - is ApiResult.Success -> { - progressView.hide() - it.data?.result?.let { seasonList -> - for (season in seasonList) { - if (season == null) continue - binding.seasonsTab.addTab( - binding.seasonsTab.newTab().setText("${season.season_number}") - ) - } - } - } - } - } - - WebSeriesRepository.episodeDataLiveData.observe(this) { - when (it) { - is ApiResult.Error -> { - binding.epShimmer.hide() - binding.rvEpisodes.hide() - binding.seasonMediaType.hide() - } - - is ApiResult.Loading -> { - binding.epShimmer.show() - binding.rvEpisodes.hide() - binding.seasonMediaType.hide() - } - - is ApiResult.Success -> { - it.data?.result?.filterNotNull()?.let { episodeList -> - - if (episodeList.isNotEmpty()) { - episodeAdapter.submitList(episodeList) { - binding.epShimmer.hide() - binding.rvEpisodes.show() - binding.seasonMediaType.show() - } - } else { - binding.epShimmer.hide() - binding.seasonMediaType.hide() - binding.rvEpisodes.hide() - } - } - } - } - } - - WebSeriesRepository.teaserDataLiveData.observe(this) { - when (it) { - is ApiResult.Error -> { - binding.rvTeaser.hide() - binding.teaserTxt.hide() - } - - is ApiResult.Loading -> { - binding.rvTeaser.hide() - binding.teaserTxt.hide() - } - - is ApiResult.Success -> { - it.data?.result?.filterNotNull()?.let { episodeList -> - - if (episodeList.isNotEmpty()) { - teaserAdapter.submitList(episodeList) { - binding.rvTeaser.show() - binding.teaserTxt.show() - } - } else { - binding.teaserTxt.hide() - binding.rvTeaser.hide() - } - } - } - } - } - } - - private fun loadSeasonData() { - binding.apply { - if (seasonsTab.selectedTabPosition >= 0) { - WebSeriesRepository.seasonDataMap["${showId}_${categoryId}"]?.result?.let { seasonList -> - if (seasonsTab.selectedTabPosition < seasonList.size) { - seasonList[seasonsTab.selectedTabPosition]?.let { seasonData -> - - // loading episode data - seasonData.id?.let { - selectedSeasonId = it - WebSeriesRepository.loadEpisodeData(showId, it) - WebSeriesRepository.loadTeaserData(showId, it) - } - - - - seasonYear.text = "${seasonData.release_year}" - val noOfEpisodes = - "${seasonData.no_of_episodes} ${seasonData.media_type}" - episodeNumber.text = noOfEpisodes - - seasonMediaType.text = "${seasonData.media_type}" - - seasonData.thumbnail_path?.let { - image.loadImage(it) - } - - seasonData.season_more_details?.let { moreDetailsList -> - if (moreDetailsList.isNotEmpty()) { - if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { - moreDetailsList[1]?.let { moreDetails -> - seasonTitle.text = moreDetails.title?.uppercase() - seasonDescription.text = Html.fromHtml( - moreDetails.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - } - } else { - moreDetailsList[0]?.let { moreDetails -> - seasonTitle.text = moreDetails.title?.uppercase() - seasonDescription.text = Html.fromHtml( - moreDetails.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - } - } - } - } - - } - } - } - } - } - } - - private fun onEpisodeClicked(position: Int, episodeData: EpisodeData) { - episodeDialogBinding.apply { - episodeData.content_more_details?.let { moreDetailsList -> - - episodeData.thumbnail_path?.let { - image.loadImage(it) - } - - if (moreDetailsList.isNotEmpty()) { - - if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { - moreDetailsList[1]?.let { data -> - title.text = data.title - description.text = Html.fromHtml( - data.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - val mediaType = - "${getString(R.string.episode)} ${episodeData.episode_number}" - mediaTypeNumber.text = mediaType - duration.text = episodeData.episode_duration - } - } else { - moreDetailsList[0]?.let { data -> - title.text = data.title - description.text = Html.fromHtml( - data.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - val mediaType = - "${getString(R.string.episode)} ${episodeData.episode_number}" - mediaTypeNumber.text = mediaType - duration.text = episodeData.episode_duration - } - } - } else { - title.text = episodeData.episode_title - description.text = Html.fromHtml( - episodeData.episode_description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - val mediaType = "${getString(R.string.episode)} ${episodeData.episode_number}" - mediaTypeNumber.text = mediaType - duration.text = episodeData.episode_duration - } - - watchCard.setOnClickListener { - onEpisodePlayClicked(position) - } - - close.setOnClickListener { - episodeDialog.dismiss() - } - - episodeDialog.show() - } - } - } - - private fun onEpisodePlayClicked(position: Int) { - startActivity(Intent(this, PlayerActivity::class.java).apply { - putExtra( - EXTRA_PLAY_LIST, - WebSeriesRepository.episodesPlaylistMap["${showId}_${selectedSeasonId}_$categoryId"] - ) - putExtra(EXTRA_PLAY_INDEX, position) - }) - } - - private fun onTeaserClicked(position: Int, teaserData: TeaserData) { - episodeDialogBinding.apply { - teaserData.content_more_details?.let { moreDetailsList -> - - teaserData.thumbnail_path?.let { - image.loadImage(it) - } - - if (moreDetailsList.isNotEmpty()) { - - if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { - moreDetailsList[1]?.let { data -> - title.text = data.title - description.text = Html.fromHtml( - data.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - val mediaType = - "${getString(R.string.teasers)} ${teaserData.teaser_number}" - mediaTypeNumber.text = mediaType - duration.text = teaserData.teaser_duration - } - } else { - moreDetailsList[0]?.let { data -> - title.text = data.title - description.text = Html.fromHtml( - data.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - val mediaType = - "${getString(R.string.teasers)} ${teaserData.teaser_number}" - mediaTypeNumber.text = mediaType - duration.text = teaserData.teaser_duration - } - } - } else { - title.text = teaserData.teaser_title - description.text = Html.fromHtml( - teaserData.teaser_description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - val mediaType = "${getString(R.string.teasers)} ${teaserData.teaser_number}" - mediaTypeNumber.text = mediaType - duration.text = teaserData.teaser_duration - } - - watchCard.setOnClickListener { - onTeaserPlayClicked(position) - } - - close.setOnClickListener { - episodeDialog.dismiss() - } - - episodeDialog.show() - } - } - } - - private fun onTeaserPlayClicked(position: Int) { - startActivity(Intent(this, PlayerActivity::class.java).apply { - putExtra( - EXTRA_PLAY_LIST, - WebSeriesRepository.teasersPlaylistMap["${showId}_${selectedSeasonId}_$categoryId"] - ) - putExtra(EXTRA_PLAY_INDEX, position) - }) - } - - override fun onTabSelected(p0: TabLayout.Tab?) { - binding.playTrailer.hide() - loadSeasonData() - } - - override fun onTabUnselected(p0: TabLayout.Tab?) {} - - override fun onTabReselected(p0: TabLayout.Tab?) {} -} \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/views/SeriesActivity.kt b/app/src/main/java/com/woka/webseries/views/SeriesActivity.kt deleted file mode 100644 index 0c72929..0000000 --- a/app/src/main/java/com/woka/webseries/views/SeriesActivity.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.woka.webseries.views - -import android.os.Bundle -import androidx.activity.enableEdgeToEdge -import androidx.appcompat.content.res.AppCompatResources -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import com.woka.R -import com.woka.databinding.ActivitySeriesBinding -import com.woka.utils.WokaBaseActivity -import com.woka.webseries.views.fragments.WebSeriesFragment - -class SeriesActivity : WokaBaseActivity() { - - private lateinit var binding: ActivitySeriesBinding - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - binding = ActivitySeriesBinding.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 - } - - window.navigationBarColor = getColor(R.color.color_primary_dark) - - supportFragmentManager.beginTransaction() - .add(R.id.fcv_web_series, WebSeriesFragment.newInstance()) - .commit() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/views/WebSeriesActivity.kt b/app/src/main/java/com/woka/webseries/views/WebSeriesActivity.kt index 9e9eb59..6027fa6 100644 --- a/app/src/main/java/com/woka/webseries/views/WebSeriesActivity.kt +++ b/app/src/main/java/com/woka/webseries/views/WebSeriesActivity.kt @@ -1,404 +1,51 @@ package com.woka.webseries.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.view.View -import android.view.WindowManager -import android.widget.AdapterView -import android.widget.AdapterView.OnItemSelectedListener import androidx.activity.enableEdgeToEdge -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat -import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProvider -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.Companion.userPrefs import com.woka.databinding.ActivityWebSeriesBinding -import com.woka.databinding.DialogContinueEpisodeBinding -import com.woka.modules.ModuleRepository -import com.woka.networking.ApiResult -import com.woka.players.views.PlayerActivity -import com.woka.players.views.PlayerActivity.Companion.EXTRA_PLAY_INDEX -import com.woka.players.views.PlayerActivity.Companion.EXTRA_PLAY_LIST -import com.woka.players.models.VideoPlayList -import com.woka.players.models.VideoViewRequestData import com.woka.utils.WokaBaseActivity -import com.woka.utils.hide -import com.woka.utils.show -import com.woka.webseries.WebSeriesRepository -import com.woka.webseries.adapters.ContinueEpisodeAdapter -import com.woka.webseries.adapters.SpinnerAdapter -import com.woka.webseries.adapters.WebSeriesShowAdapter -import com.woka.webseries.models.ContinueEpisodeData import com.woka.webseries.models.ShowData -import com.woka.webseries.models.WebSeriesResponse -import com.woka.webseries.viewmodel.WebSeriesViewModel +import com.woka.webseries.views.fragments.WebSeriesFragment +import com.woka.webseries.views.fragments.WebShowFragment -class WebSeriesActivity : WokaBaseActivity(), Observer>>{ +class WebSeriesActivity : WokaBaseActivity() { + + companion object { + const val EXTRA_SHOW_DATA = "extra_show_data" + const val EXTRA_SHOW_CATEGORY = "extra_show_category" + const val EXTRA_SHOW_ID = "extra_show_id" + } private lateinit var binding: ActivityWebSeriesBinding - private lateinit var viewmodel: WebSeriesViewModel - - private lateinit var showAdapter: WebSeriesShowAdapter - - private lateinit var continueWatchAdapter: ContinueEpisodeAdapter - - private var catSpinnerAdapter: SpinnerAdapter? = null - - private var showIntentLauncher: ActivityResultLauncher? = null - - private lateinit var episodeDialogBinding: DialogContinueEpisodeBinding - private lateinit var episodeDialog: Dialog - + @Suppress("DEPRECATION") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() binding = ActivityWebSeriesBinding.inflate(layoutInflater) setContentView(binding.root) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> + ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } - viewmodel = ViewModelProvider(this)[WebSeriesViewModel::class.java] - window.navigationBarColor = getColor(R.color.color_primary_dark) - initViews() + val showData = intent.getParcelableExtra(EXTRA_SHOW_DATA) + val categoryId = intent.getStringExtra(EXTRA_SHOW_CATEGORY) - initEpisodeDialog() - - clickEvents() - - setObservers() - - resultLaunchers() - - if(!ModuleRepository.showCategoryLiveData.isInitialized){ - ModuleRepository.showCategories() - } - } - - private fun clickEvents() { - binding.apply { - toolbar.backBtn.setOnClickListener { - onBackPressedDispatcher.onBackPressed() - } - - retryBtn.setOnClickListener { - binding.shimmer.show() - binding.errorView.hide() - if (ModuleRepository.showCategoryLiveData.isInitialized && ModuleRepository.showCategoryLiveData.value is ApiResult.Success){ - // categories already available - loadShowData() - }else{ - // categories not available - ModuleRepository.showCategories() + supportFragmentManager.beginTransaction() + .add( + R.id.fcv_web_series, if (showData != null && categoryId != null) { + WebShowFragment.newInstance(showData, categoryId) + } else { + WebSeriesFragment.newInstance() } - } - } - } - private fun initViews(){ - - // adapters - showAdapter = WebSeriesShowAdapter(this, ::onShowClicked) - continueWatchAdapter = ContinueEpisodeAdapter(this) - - binding.apply { - adjustMasilaImage() - - toolbar.title.text = getString(R.string.web_series) - - rvWebSeries.adapter = showAdapter - rvContinueWatch.adapter = continueWatchAdapter - continueWatchAdapter.onEpisodeClicked = ::onContinueEpisodeClicked - - ((rvWebSeries.itemAnimator) as SimpleItemAnimator).supportsChangeAnimations = false - ((rvContinueWatch.itemAnimator) as SimpleItemAnimator).supportsChangeAnimations = false - } - - } - - private fun initEpisodeDialog(){ - episodeDialogBinding = DialogContinueEpisodeBinding.inflate(layoutInflater) - episodeDialog = Dialog(this) - - episodeDialog.setContentView(episodeDialogBinding.root) - - try { - val back = ColorDrawable(Color.TRANSPARENT) - val inset = InsetDrawable(back, 50) - episodeDialog.window!!.setBackgroundDrawable(inset) - } catch (e: Exception) { - // do nothing - } - - try { - val layoutParams = episodeDialog.window!!.attributes - layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT - layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT - layoutParams.horizontalMargin = 0F - episodeDialog.window!!.setAttributes(layoutParams) - } catch (e: Exception) { - // do nothing - } - - episodeDialogBinding.close.setOnClickListener { episodeDialog.dismiss() } - } - - - private fun resultLaunchers(){ - showIntentLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ - if (it.resultCode == RESULT_OK){ - it.data?.getIntExtra(SeasonActivity.EXTRA_SHOW_ID, -1)?.let {showId -> - onWebShowItemChanged(showId) - } - } - } - } - - private fun setObservers(){ - - viewmodel.webSeriesLiveData.observe(this, this) - - viewmodel.continueWatchLiveData.observe(this){ - when (it){ - is ApiResult.Error -> { - binding.rvContinueWatch.hide() - binding.continueWatchTxt.hide() - } - is ApiResult.Loading -> {} - is ApiResult.Success -> { - it.data?.result?.let {continueWatchList -> - if (continueWatchList.isNotEmpty()){ - binding.rvContinueWatch.show() - binding.continueWatchTxt.show() - continueWatchAdapter.submitList(continueWatchList.asReversed()) - }else{ - binding.rvContinueWatch.hide() - binding.continueWatchTxt.hide() - } - } - } - } - } - - ModuleRepository.showCategoryLiveData.observe(this){ - when(it){ - is ApiResult.Error -> { - binding.errorView.show() - binding.shimmer.hide() - } - is ApiResult.Loading -> {} - is ApiResult.Success -> { - it.data?.result?.let {catList -> - binding.shimmer.hide() - - binding.trailerView.show() - - adjustMasilaImage() - - binding.spinnerCard.show() - binding.selectLangTxt.show() - - WebSeriesRepository.continueWatchData?.let { - binding.continueWatchTxt.show() - binding.rvContinueWatch.show() - }?:{ - binding.continueWatchTxt.hide() - binding.rvContinueWatch.hide() - } - - catSpinnerAdapter = SpinnerAdapter(this, catList.filterNotNull()) - binding.categorySpinner.setAdapter(catSpinnerAdapter) - - loadShowData() - WebSeriesRepository.loadContinueWatchData() - } - } - } - } - - binding.categorySpinner.onItemSelectedListener = object : OnItemSelectedListener{ - override fun onItemSelected( - parent: AdapterView<*>?, - view: View?, - position: Int, - id: Long - ) { - if (position != catSpinnerAdapter?.currentSelection){ - catSpinnerAdapter?.selectPosition(position) - loadShowData() - } - } - - override fun onNothingSelected(parent: AdapterView<*>?) {} - } - } - - override fun onChanged(value: ApiResult>) { - when (value){ - is ApiResult.Error -> { - binding.shimmerShowData.hide() - binding.rvWebSeries.hide() - } - is ApiResult.Loading -> { - binding.shimmerShowData.show() - binding.rvWebSeries.hide() - } - is ApiResult.Success -> { - catSpinnerAdapter?.selectedCategoryType?.let { categoryType -> - value.data?.get(categoryType)?.show_data?.let {showList -> - binding.shimmerShowData.hide() - - showAdapter.submitListShowList(showList.filterNotNull(), categoryType) - binding.rvWebSeries.show() - } - } - } - } - } - - private fun loadShowData(){ - catSpinnerAdapter?.selectedCategoryType?.let { - WebSeriesRepository.loadWebSeries(it) - } - } - - private fun adjustMasilaImage() { - // making space for masila image - binding.apply { - topPinnedView.post { - val imgParams = masilaImage.layoutParams as CollapsingToolbarLayout.LayoutParams - imgParams.setMargins(0, 0, 0, topPinnedView.height) - masilaImage.layoutParams = imgParams - } - } - } - - private fun onShowClicked(showData: ShowData, categoryId: String){ - showIntentLauncher?.launch(Intent(this, SeasonActivity::class.java).apply { - putExtra(SeasonActivity.EXTRA_SHOW_ID, showData.id) - putExtra(SeasonActivity.EXTRA_SHOW_CATEGORY_DATA, categoryId) - }) - } - - private fun onWebShowItemChanged(showId: Int){ - val englishPosition = showAdapter.showList.indexOfFirst { it.id == showId } - if (englishPosition > -1 && englishPosition < showAdapter.showList.size){ - showAdapter.notifyItemChanged(englishPosition) - } - } - - private fun onContinueEpisodeClicked(episodeData: ContinueEpisodeData){ - episodeDialogBinding.apply { - episodeData.content_more_details?.let {moreDetailsList -> - - episodeData.thumbnail_path?.let { - image.loadImage(it) - } - - if (moreDetailsList.isNotEmpty()){ - - if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){ - moreDetailsList[1].let {data -> - title.text = data.title - description.text = Html.fromHtml( - data.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - } - }else{ - moreDetailsList[0].let {data -> - title.text = data.title - description.text = Html.fromHtml( - data.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - } - } - }else{ - title.text = episodeData.episode_title - description.text = Html.fromHtml( - episodeData.episode_description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - } - - watchCard.setOnClickListener { - episodeData.content_more_details.let {moreDetailsList -> - val videoPlayList = VideoPlayList(ArrayList(), ArrayList()) - - if (moreDetailsList.isNotEmpty()){ - if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){ - videoPlayList.playlist.add( - PlaylistItem.Builder() - .file(moreDetailsList[1].content_hd_url) - .title(moreDetailsList[1].title) - .image(moreDetailsList[1].content_hd_url) - .build() - ) - - videoPlayList.videoViewRequestDataList?.add( - VideoViewRequestData( - "${episodeData.id}", - "3", - null, - category_id = "18" - ) - ) - }else{ - videoPlayList.playlist.add( - PlaylistItem.Builder() - .file(moreDetailsList[0].content_hd_url) - .title(moreDetailsList[0].title) - .image(moreDetailsList[0].content_hd_url) - .build() - ) - - videoPlayList.videoViewRequestDataList?.add( - VideoViewRequestData( - "${episodeData.id}", - "3", - null, - "1" - ) - ) - } - } - - startActivity(Intent(this@WebSeriesActivity, PlayerActivity::class.java) - .apply { - putExtra(EXTRA_PLAY_LIST, videoPlayList) - putExtra(EXTRA_PLAY_INDEX, 0) - }) - } - } - - close.setOnClickListener { - episodeDialog.dismiss() - } - - episodeDialog.show() - } - } + ) + .commit() } } \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/views/fragments/ShowChangeInterface.kt b/app/src/main/java/com/woka/webseries/views/fragments/ShowChangeInterface.kt new file mode 100644 index 0000000..0593508 --- /dev/null +++ b/app/src/main/java/com/woka/webseries/views/fragments/ShowChangeInterface.kt @@ -0,0 +1,8 @@ +package com.woka.webseries.views.fragments + +import com.woka.webseries.models.ShowData +import java.io.Serializable + +interface ShowChangeInterface: Serializable { + fun onShowDataChanged(showData: ShowData, categoryId: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/woka/webseries/views/fragments/WebSeriesFragment.kt b/app/src/main/java/com/woka/webseries/views/fragments/WebSeriesFragment.kt index e804412..ebd0509 100644 --- a/app/src/main/java/com/woka/webseries/views/fragments/WebSeriesFragment.kt +++ b/app/src/main/java/com/woka/webseries/views/fragments/WebSeriesFragment.kt @@ -38,12 +38,12 @@ import com.woka.webseries.adapters.SpinnerAdapter import com.woka.webseries.adapters.WebSeriesShowAdapter import com.woka.webseries.models.ContinueEpisodeData import com.woka.webseries.models.ShowData -import com.woka.webseries.viewmodel.ViewModel +import com.woka.webseries.viewmodel.WebSeriesViewModel class WebSeriesFragment private constructor(): Fragment() { private lateinit var binding: FragmentWebSeriesBinding - private var viewModel: ViewModel? = null + private var viewModel: WebSeriesViewModel? = null private lateinit var showAdapter: WebSeriesShowAdapter @@ -69,7 +69,7 @@ class WebSeriesFragment private constructor(): Fragment() { it.window.setBackgroundDrawable(AppCompatResources.getDrawable(it, R.drawable.gradient_web_series)) it.window.statusBarColor = 0 it.window.lightStatusBar(false) - viewModel = ViewModelProvider(it)[ViewModel::class.java] + viewModel = ViewModelProvider(it)[WebSeriesViewModel::class.java] } return binding.root } @@ -302,7 +302,7 @@ class WebSeriesFragment private constructor(): Fragment() { private fun onShowClicked(showData: ShowData, categoryId: String){ parentFragmentManager.beginTransaction() - .add(R.id.fcv_web_series, WebShowFragment.newInstance(showData, categoryId)) + .add(R.id.fcv_web_series, WebShowFragment.newInstance(showData, categoryId, ::onShowDataChanged)) .hide(this) .addToBackStack(null) .commit() @@ -314,6 +314,20 @@ class WebSeriesFragment private constructor(): Fragment() { viewModel?.showCommonDataChanged(showData, categoryId) } + private fun onShowDataChanged(showData: ShowData, categoryId: String) { + viewModel?.showCommonDataChanged(showData, categoryId) + val position = showAdapter.showList.indexOfFirst { it.id == showData.id } + if (position >= 0 && position < showAdapter.showList.size){ + val currData = showAdapter.showList[position] + + currData.is_liked = showData.is_liked + currData.likes_count = showData.likes_count + currData.favourite_category_ids = showData.favourite_category_ids + + showAdapter.notifyItemChanged(position) + } + } + private fun onContinueEpisodeClicked(episodeData: ContinueEpisodeData){ episodeDialogBinding.apply { episodeData.content_more_details?.let {moreDetailsList -> diff --git a/app/src/main/java/com/woka/webseries/views/fragments/WebShowFragment.kt b/app/src/main/java/com/woka/webseries/views/fragments/WebShowFragment.kt index 2730f30..e442eb6 100644 --- a/app/src/main/java/com/woka/webseries/views/fragments/WebShowFragment.kt +++ b/app/src/main/java/com/woka/webseries/views/fragments/WebShowFragment.kt @@ -1,7 +1,9 @@ package com.woka.webseries.views.fragments +import android.app.Activity.RESULT_OK import android.app.Dialog import android.content.Context +import android.content.Intent import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.graphics.drawable.InsetDrawable @@ -15,46 +17,47 @@ import androidx.appcompat.content.res.AppCompatResources import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import com.google.android.material.tabs.TabLayout +import com.jwplayer.pub.api.media.playlists.PlaylistItem import com.woka.R import com.woka.WokaApp.Companion.userPrefs import com.woka.databinding.DialogEpisodeBinding import com.woka.databinding.FragmentWebShowBinding import com.woka.networking.ApiResult +import com.woka.players.models.VideoPlayList +import com.woka.players.views.PlayerActivity import com.woka.utils.hide import com.woka.utils.isNetworkConnected import com.woka.utils.lightStatusBar import com.woka.utils.setVisibility import com.woka.utils.show import com.woka.utils.toast -import com.woka.webseries.Repository +import com.woka.webseries.WebSeriesRepository import com.woka.webseries.adapters.EpisodeAdapter import com.woka.webseries.adapters.TeaserAdapter import com.woka.webseries.models.ShowData import com.woka.webseries.models.episodedata.EpisodeData import com.woka.webseries.models.teaserdata.TeaserData -import com.woka.webseries.viewmodel.ViewModel +import com.woka.webseries.viewmodel.WebSeriesViewModel +import com.woka.webseries.views.WebSeriesActivity.Companion.EXTRA_SHOW_ID +import kotlin.math.max -private const val EXTRA_SHOW_DATA = "extra_show_id_data" -private const val EXTRA_SHOW_CATEGORY_ID = "extra_show_category_data" - -class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelectedListener { +class WebShowFragment private constructor( + private var showData: ShowData, + private val categoryId: String, + private val onShowDataChange: ((ShowData, String) -> Unit)? = null +) : Fragment(), TabLayout.OnTabSelectedListener { companion object { - fun newInstance(showData: ShowData, categoryId: String) = - WebShowFragment().apply { - arguments = Bundle().apply { - putParcelable(EXTRA_SHOW_DATA, showData) - putString(EXTRA_SHOW_CATEGORY_ID, categoryId) - } - } + fun newInstance( + showData: ShowData, + categoryId: String, + onShowDataChange: ((ShowData, String) -> Unit)? = null + ) = + WebShowFragment(showData, categoryId, onShowDataChange) } private lateinit var binding: FragmentWebShowBinding - private var viewModel: ViewModel? = null - - // arguments - private var categoryId: String? = null - private var showData: ShowData? = null + private var viewModel: WebSeriesViewModel? = null // variables @@ -67,6 +70,7 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected private lateinit var episodeDialog: Dialog private var loadMoreEpisodes = false + private var showDataChanged: Boolean = false override fun onAttach(context: Context) { super.onAttach(context) @@ -76,24 +80,16 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected episodeDialog = Dialog(context) } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - arguments?.let { - showData = it.getParcelable(EXTRA_SHOW_DATA) - categoryId = it.getString(EXTRA_SHOW_CATEGORY_ID) - } - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentWebShowBinding.inflate(inflater, container, false) - viewModel = ViewModelProvider(this)[ViewModel::class.java] + viewModel = ViewModelProvider(this)[WebSeriesViewModel::class.java] activity?.let { it.window.setBackgroundDrawableResource(R.color.web_show_bg) it.window.lightStatusBar(true) - viewModel = ViewModelProvider(it)[ViewModel::class.java] + viewModel = ViewModelProvider(it)[WebSeriesViewModel::class.java] } return binding.root } @@ -109,48 +105,54 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected setObservers() binding.seasonProgressView.show() - viewModel?.seasonListing("${showData?.id}", "$categoryId") + viewModel?.seasonListing("${showData.id}", categoryId) } override fun onDestroyView() { super.onDestroyView() activity?.let { - it.window.setBackgroundDrawable(AppCompatResources.getDrawable(it, R.drawable.gradient_web_series)) + it.window.setBackgroundDrawable( + AppCompatResources.getDrawable( + it, + R.drawable.gradient_web_series + ) + ) it.window.statusBarColor = 0 it.window.lightStatusBar(false) } viewModel?.clearSeasonLiveData() viewModel?.clearEpisodeListingLiveData() + viewModel?.clearTeaserListingLiveData() + + if (showDataChanged) { + onShowDataChange?.invoke(showData, categoryId) + } } // initializations private fun initViews() { - if (showData != null && categoryId != null) { - binding.apply { + binding.apply { - likeCount.text = "${showData!!.likes_count}" + likeCount.text = "${showData.likes_count}" - favSeason.isSelected = showData!!.isBookMarked(categoryId!!) + favSeason.isSelected = showData.isBookMarked(categoryId) - likeSeason.isSelected = showData!!.is_liked ?: false + likeSeason.isSelected = showData.is_liked ?: false - binding.seasonsTab.addOnTabSelectedListener(this@WebShowFragment) + binding.seasonsTab.addOnTabSelectedListener(this@WebShowFragment) - rvEpisodes.adapter = episodeAdapter - episodeAdapter.onEpisodeClicked = ::onEpisodeClicked - episodeAdapter.onEpisodePlayClicked = ::onEpisodePlayClicked + rvEpisodes.adapter = episodeAdapter + episodeAdapter.onEpisodeClicked = ::onEpisodeClicked + episodeAdapter.onEpisodePlayClicked = ::onEpisodePlayClicked - rvTeaser.adapter = teaserAdapter - teaserAdapter.onEpisodeClicked = ::onTeaserClicked - teaserAdapter.onEpisodePlayClicked = ::onTeaserPlayClicked - } + rvTeaser.adapter = teaserAdapter + teaserAdapter.onEpisodeClicked = ::onTeaserClicked + teaserAdapter.onEpisodePlayClicked = ::onTeaserPlayClicked } } private fun clickEvents() { - if (showData == null || categoryId == null) return - binding.apply { backBtn.setOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() @@ -162,7 +164,7 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected epLoadMoreBtn.setOnClickListener { loadMoreEpisodes = true - viewModel?.loadMoreEpisodes("${showData?.id}", selectedSeasonId) + viewModel?.loadMoreEpisodes("${showData.id}", selectedSeasonId) } likeSeason.setOnClickListener { @@ -171,10 +173,27 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected return@setOnClickListener } - Repository.likeUnLikeShow("${showData?.id}", showData?.is_liked == false) + WebSeriesRepository.likeUnLikeShow("${showData.id}", showData.is_liked == false) + + showData.likes_count?.let { + showData.likes_count = if (likeSeason.isSelected){ + // unlike + max(0, it - 1) + }else{ + // like + it + 1 + } + } + + showData.is_liked = !likeSeason.isSelected likeSeason.isSelected = !likeSeason.isSelected - likeCount.text = "${showData?.likes_count}" + likeCount.text = "${showData.likes_count}" + + showDataChanged = true + activity?.setResult(RESULT_OK, Intent().apply { + putExtra(EXTRA_SHOW_ID, showData.id?:-1) + }) } favSeason.setOnClickListener { @@ -183,62 +202,74 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected return@setOnClickListener } - if (showData == null) return@setOnClickListener + WebSeriesRepository.updateFavShow( + showData, + !showData.isBookMarked(categoryId), + categoryId + ) - categoryId?.let { - Repository.updateFavShow( - showData!!, - showData?.isBookMarked("$categoryId") == false, - "$categoryId" - ) - - favSeason.isSelected = !favSeason.isSelected + if (showData.isBookMarked(categoryId)){ + // remove from fav + showData.removeAsBookMark(categoryId) + }else{ + // add to fav + showData.addAsBookMark(categoryId) } + + favSeason.isSelected = !favSeason.isSelected + + showDataChanged = true + activity?.setResult(RESULT_OK, Intent().apply { + putExtra(EXTRA_SHOW_ID, showData.id?:-1) + }) } playTrailer.setOnClickListener { -// if (seasonsTab.selectedTabPosition >= 0) { -// WebSeriesRepository.seasonDataMap["${showId}_${categoryId}"]?.result?.let { seasonList -> -// if (seasonsTab.selectedTabPosition < seasonList.size) { -// seasonList[seasonsTab.selectedTabPosition]?.let { seasonData -> -// -// seasonData.season_more_details?.let { moreDetailsList -> -// if (moreDetailsList.isNotEmpty()) { -// val videoPlayList = VideoPlayList(ArrayList()) -// -// val playlistItem = PlaylistItem.Builder() -// -// if (categoryId == "18" && moreDetailsList.size > 1) { -// moreDetailsList[1]?.let { seasonMoreData -> -// playlistItem.title(seasonMoreData.title) -// playlistItem.image(seasonMoreData.trailer_hd_url) -// playlistItem.file(seasonMoreData.trailer_hd_url) -// } -// } else { -// moreDetailsList[0]?.let { seasonMoreData -> -// playlistItem.title(seasonMoreData.title) -// playlistItem.image(seasonMoreData.trailer_hd_url) -// playlistItem.file(seasonMoreData.trailer_hd_url) -// } -// } -// -// videoPlayList.playlist.add(playlistItem.build()) -// -// startActivity( -// Intent(this@SeasonActivity, PlayerActivity::class.java) -// .apply { -// putExtra( -// PlayerActivity.EXTRA_PLAY_LIST, -// videoPlayList -// ) -// } -// ) -// } -// } -// } -// } -// } -// } + if (seasonsTab.selectedTabPosition >= 0) { + viewModel?.seasonListingMap?.get("${showData.id}_${categoryId}") + ?.let { seasonList -> + if (seasonsTab.selectedTabPosition < seasonList.size) { + seasonList[seasonsTab.selectedTabPosition].let { seasonData -> + + seasonData.season_more_details?.let { moreDetailsList -> + if (moreDetailsList.isNotEmpty()) { + val videoPlayList = VideoPlayList(ArrayList()) + + val playlistItem = PlaylistItem.Builder() + + if (categoryId == "18" && moreDetailsList.size > 1) { + moreDetailsList[1]?.let { seasonMoreData -> + playlistItem.title(seasonMoreData.title) + playlistItem.image(seasonMoreData.trailer_hd_url) + playlistItem.file(seasonMoreData.trailer_hd_url) + } + } else { + moreDetailsList[0]?.let { seasonMoreData -> + playlistItem.title(seasonMoreData.title) + playlistItem.image(seasonMoreData.trailer_hd_url) + playlistItem.file(seasonMoreData.trailer_hd_url) + } + } + + videoPlayList.playlist.add(playlistItem.build()) + + activity?.let { + startActivity( + Intent(it, PlayerActivity::class.java) + .apply { + putExtra( + PlayerActivity.EXTRA_PLAY_LIST, + videoPlayList + ) + } + ) + } + } + } + } + } + } + } } } } @@ -269,8 +300,8 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected } // callbacks - private fun setObservers(){ - viewModel?.seasonListingLiveData?.observe(viewLifecycleOwner){ + private fun setObservers() { + viewModel?.seasonListingLiveData?.observe(viewLifecycleOwner) { binding.seasonsTab.removeAllTabs() when (it) { is ApiResult.Error -> { @@ -283,8 +314,8 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected is ApiResult.Success -> { binding.seasonProgressView.hide() - it.data?.let {seasonList -> - for (season in seasonList){ + it.data?.let { seasonList -> + for (season in seasonList) { binding.seasonsTab.addTab( binding.seasonsTab.newTab().setText("${season.season_number}") ) @@ -294,41 +325,46 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected } } - viewModel?.episodeListingLiveData?.observe(viewLifecycleOwner){ - when (it){ + viewModel?.episodeListingLiveData?.observe(viewLifecycleOwner) { + when (it) { is ApiResult.Error -> { binding.epShimmer.hide() - if (loadMoreEpisodes){ + if (loadMoreEpisodes) { // load more binding.epLoadMoreBtn.text = getString(R.string.retry) binding.epLoadMoreBtn.show() - }else{ + } else { // first time load binding.rvEpisodes.hide() + binding.seasonMediaType.hide() binding.epShimmer.hide() binding.epLoadMoreBtn.hide() } } + is ApiResult.Loading -> { binding.epShimmer.show() binding.epLoadMoreBtn.hide() binding.rvEpisodes.setVisibility(loadMoreEpisodes) + binding.seasonMediaType.setVisibility(loadMoreEpisodes) } + is ApiResult.Success -> { - it.data?.let {episodeList -> + it.data?.let { episodeList -> binding.rvEpisodes.show() + binding.seasonMediaType.show() binding.epShimmer.hide() binding.epLoadMoreBtn.text = getString(R.string.load_more) - binding.epLoadMoreBtn.setVisibility(viewModel?.episodePagingData?.get("${showData?.id}_$selectedSeasonId")?.lastPage == false) + binding.epLoadMoreBtn.setVisibility(viewModel?.episodePagingData?.get("${showData.id}_$selectedSeasonId")?.lastPage == false) - if (loadMoreEpisodes){ + if (loadMoreEpisodes) { // loaded more data episodeAdapter.notifyItemRangeInserted( episodeAdapter.currentList.size, episodeList.size ) - }else{ + } else { // new category data load episodeAdapter.submitList(episodeList) } @@ -336,6 +372,35 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected } } } + + viewModel?.teaserListingLiveData?.observe(viewLifecycleOwner) { + when (it) { + is ApiResult.Error -> { + binding.rvTeaser.hide() + binding.teaserTxt.hide() + } + + is ApiResult.Loading -> { + binding.rvTeaser.hide() + binding.teaserTxt.hide() + } + + is ApiResult.Success -> { + it.data?.let { teaserList -> + + if (teaserList.isNotEmpty()) { + teaserAdapter.submitList(teaserList) { + binding.rvTeaser.show() + binding.teaserTxt.show() + } + } else { + binding.teaserTxt.hide() + binding.rvTeaser.hide() + } + } + } + } + } } private fun onEpisodeClicked(position: Int, episodeData: EpisodeData) { @@ -404,7 +469,15 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected } private fun onEpisodePlayClicked(position: Int) { - + activity?.let { + startActivity(Intent(it, PlayerActivity::class.java).apply { + putExtra( + PlayerActivity.EXTRA_PLAY_LIST, + viewModel?.episodesPlaylistMap?.get("${showData.id}_${selectedSeasonId}_$categoryId") + ) + putExtra(PlayerActivity.EXTRA_PLAY_INDEX, position) + }) + } } private fun onTeaserClicked(position: Int, teaserData: TeaserData) { @@ -475,68 +548,77 @@ class WebShowFragment private constructor(): Fragment(), TabLayout.OnTabSelected private fun loadSeasonData() { binding.apply { if (seasonsTab.selectedTabPosition >= 0) { - viewModel?.seasonListingMap?.get("${showData?.id}_${categoryId}")?.let { seasonList -> - if (seasonsTab.selectedTabPosition < seasonList.size) { - seasonList[seasonsTab.selectedTabPosition].let { seasonData -> + viewModel?.seasonListingMap?.get("${showData.id}_${categoryId}") + ?.let { seasonList -> + if (seasonsTab.selectedTabPosition < seasonList.size) { + seasonList[seasonsTab.selectedTabPosition].let { seasonData -> - playTrailer.show() - detailsProgressiveView.hide() - detailsView.show() + playTrailer.show() + detailsProgressiveView.hide() + detailsView.show() - // loading episode data - seasonData.id?.let { - selectedSeasonId = it + // loading episode data + seasonData.id?.let { + selectedSeasonId = it - loadMoreEpisodes = false - viewModel?.loadEpisodes("${showData?.id}", it) -// WebSeriesRepository.loadTeaserData(showId, it) - } + loadMoreEpisodes = false + viewModel?.loadEpisodes("${showData.id}", it) + viewModel?.loadTeasers("${showData.id}", it) + } - seasonYear.text = "${seasonData.release_year}" - val noOfEpisodes = - "${seasonData.no_of_episodes} ${seasonData.media_type}" - episodeNumber.text = noOfEpisodes + seasonYear.text = "${seasonData.release_year}" + val noOfEpisodes = + "${seasonData.no_of_episodes} ${seasonData.media_type}" + episodeNumber.text = noOfEpisodes - seasonMediaType.text = "${seasonData.media_type}" + seasonMediaType.text = "${seasonData.media_type}" - seasonData.thumbnail_path?.let { - image.loadImage(it) - } + seasonData.thumbnail_path?.let { + image.loadImage(it) + } - seasonData.season_more_details?.let { moreDetailsList -> - if (moreDetailsList.isNotEmpty()) { - if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { - moreDetailsList[1]?.let { moreDetails -> - seasonTitle.text = moreDetails.title?.uppercase() - seasonDescription.text = Html.fromHtml( - moreDetails.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) - } - } else { - moreDetailsList[0]?.let { moreDetails -> - seasonTitle.text = moreDetails.title?.uppercase() - seasonDescription.text = Html.fromHtml( - moreDetails.description?.replace( - "
", - " " - ), Html.FROM_HTML_MODE_LEGACY - ) + seasonData.season_more_details?.let { moreDetailsList -> + if (moreDetailsList.isNotEmpty()) { + if (userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) { + moreDetailsList[1]?.let { moreDetails -> + seasonTitle.text = moreDetails.title?.uppercase() + seasonDescription.text = Html.fromHtml( + moreDetails.description?.replace( + "
", + " " + ), Html.FROM_HTML_MODE_LEGACY + ) + } + } else { + moreDetailsList[0]?.let { moreDetails -> + seasonTitle.text = moreDetails.title?.uppercase() + seasonDescription.text = Html.fromHtml( + moreDetails.description?.replace( + "
", + " " + ), Html.FROM_HTML_MODE_LEGACY + ) + } } } } } } } - } } } } private fun onTeaserPlayClicked(position: Int) { - + activity?.let { + startActivity(Intent(it, PlayerActivity::class.java).apply { + putExtra( + PlayerActivity.EXTRA_PLAY_LIST, + viewModel?.teaserPlaylistMap?.get("${showData.id}_${selectedSeasonId}_$categoryId") + ) + putExtra(PlayerActivity.EXTRA_PLAY_INDEX, position) + }) + } } // season tab selection diff --git a/app/src/main/res/drawable/ic_close_circle.xml b/app/src/main/res/drawable/ic_close_circle.xml new file mode 100644 index 0000000..8a22c1c --- /dev/null +++ b/app/src/main/res/drawable/ic_close_circle.xml @@ -0,0 +1,17 @@ + + + + diff --git a/app/src/main/res/layout/activity_series.xml b/app/src/main/res/layout/activity_series.xml deleted file mode 100644 index 5dd02a6..0000000 --- a/app/src/main/res/layout/activity_series.xml +++ /dev/null @@ -1,7 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web_series.xml b/app/src/main/res/layout/activity_web_series.xml index d46ddbb..1b84ca5 100644 --- a/app/src/main/res/layout/activity_web_series.xml +++ b/app/src/main/res/layout/activity_web_series.xml @@ -1,325 +1,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -