continue watching for show api integration

continue watching data showing in recyclerview

clearing cached data when user logs out and logs in with new account

custom spinner for category in web series

started making ui for Show details page and episode listing
This commit is contained in:
2024-06-20 20:57:20 +05:30
parent 3527906e07
commit 71b2522f1f
24 changed files with 712 additions and 48 deletions

1
.idea/misc.xml generated
View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">

View File

@@ -51,6 +51,8 @@ ext.jwPlayerVersion = '4.6.0'
ext.exoplayerVersion = '2.19.1'
dependencies {
implementation "com.facebook.shimmer:shimmer:0.5.0"
implementation "com.airbnb.android:lottie:6.4.0"
implementation "androidx.core:core-splashscreen:1.0.1"

View File

@@ -15,10 +15,14 @@
android:supportsRtl="true"
android:theme="@style/Theme.Woka"
tools:targetApi="31">
<activity
android:name=".webseries.views.SeasonActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".webseries.views.WebSeriesActivity"
android:exported="false"
android:screenOrientation="portrait"/>
android:screenOrientation="portrait" />
<activity
android:name=".home.FMActivity"
android:exported="false"

View File

@@ -1,5 +1,6 @@
package com.woka.home.mylist
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woka.home.mylist.models.AudioData
@@ -11,6 +12,7 @@ import com.woka.home.mylist.models.SingKaraokeData
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.userdata.UserRepository
import com.woka.utils.TAG
import com.woka.webseries.WebSeriesRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -25,17 +27,36 @@ object MyListRepository {
private val _myFavListLiveData = MutableLiveData<ApiResult<MyListResponse>>()
val myFavListLiveData: LiveData<ApiResult<MyListResponse>>
get() {
// also updating local changes
myFavData?.let { _myFavListLiveData.postValue(ApiResult.Success(it)) }
if (shallLoadNewData){
// load new data
loadMyFavList()
shallLoadNewData = false
}else{
// also updating local changes
myFavData?.let {
_myFavListLiveData.postValue(ApiResult.Success(it))
}
}
return _myFavListLiveData
}
private var myFavData: MyListResponse? = null
/*
flag to load a new data whenever necessary
for eg. when user has signed in with new account and the apps hold the older repository
*/
private var shallLoadNewData: Boolean = false
init {
loadMyFavList()
}
fun clearData(){
shallLoadNewData = true
myFavData = null
}
private fun loadMyFavList(){
CoroutineScope(Dispatchers.IO).launch {
_myFavListLiveData.postValue(ApiResult.Loading())

View File

@@ -5,6 +5,7 @@ import com.woka.modules.categorymodels.CategoriesResponse
import com.woka.modules.faqs.models.FaqResponse
import com.woka.modules.wokasongs.models.WokaSongsResponse
import com.woka.networking.ApiResponse
import com.woka.webseries.models.ContinueEpisodeResponse
import okhttp3.FormBody
import retrofit2.Response
import retrofit2.http.Body
@@ -30,4 +31,7 @@ interface ModuleApiService {
@POST("category_listing")
suspend fun categoryListing(@Body body: FormBody): Response<ApiResponse<CategoriesResponse>>
@POST("continue_watching")
suspend fun continueWatchingShowListing(@Body body: FormBody): Response<ApiResponse<ContinueEpisodeResponse>>
}

View File

@@ -9,12 +9,14 @@ import android.provider.Settings.Secure
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woka.home.Theme
import com.woka.home.mylist.MyListRepository
import com.woka.networking.ApiResult
import com.woka.onboard.OnboardActivity
import com.woka.userdata.UserRepository
import com.woka.userdata.userDataModels.UserData
import com.woka.userdata.userDataModels.UserDataResponse
import com.woka.utils.UserType
import com.woka.webseries.WebSeriesRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -107,5 +109,12 @@ class UserPreference(val context: Context) {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
})
}
clearData()
}
private fun clearData(){
WebSeriesRepository.clearData()
MyListRepository.clearData()
}
}

View File

@@ -5,9 +5,13 @@ import androidx.lifecycle.MutableLiveData
import com.woka.home.mylist.MyFavApiService
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.BookmarkedShowData
import com.woka.home.mylist.models.MyListResponse
import com.woka.home.mylist.models.PostType
import com.woka.modules.ModuleApiService
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.userdata.UserRepository
import com.woka.webseries.models.ContinueEpisodeResponse
import com.woka.webseries.models.ShowData
import com.woka.webseries.models.WebSeriesResponse
import kotlinx.coroutines.CoroutineScope
@@ -17,9 +21,14 @@ import okhttp3.FormBody
import kotlin.math.max
object WebSeriesRepository {
// api services
private val apiService = RetrofitHelper.getRetrofit().create(WebSeriesApiService::class.java)
private val myFavApiService = RetrofitHelper.getRetrofit().create(MyFavApiService::class.java)
private val moduleApiService = RetrofitHelper.getRetrofit().create(ModuleApiService::class.java)
// live data
// show data (loose caching)
private val _englishWebSeriesLiveData = MutableLiveData<ApiResult<WebSeriesResponse>>()
val englishWebSeriesLiveData: LiveData<ApiResult<WebSeriesResponse>>
get() = _englishWebSeriesLiveData
@@ -32,6 +41,69 @@ object WebSeriesRepository {
var hindiWebSeriesData: WebSeriesResponse? = null
// continue watching (tight caching)
private val _continueWatchLiveData = MutableLiveData<ApiResult<ContinueEpisodeResponse>>()
val continueWatchLiveData: LiveData<ApiResult<ContinueEpisodeResponse>>
get() {
if (shallLoadNewContinueWatchData){
// load new data
loadContinueWatchData()
shallLoadNewContinueWatchData = false
}else{
// also updating local changes
continueWatchData?.let {
_continueWatchLiveData.postValue(ApiResult.Success(it))
}
}
return _continueWatchLiveData
}
var continueWatchData: ContinueEpisodeResponse? = null
/*
flag to load a new data whenever necessary
for eg. when user has signed in with new account and the apps hold the older repository
*/
private var shallLoadNewContinueWatchData: Boolean = false
init {
loadContinueWatchData()
}
private fun loadContinueWatchData(){
CoroutineScope(Dispatchers.IO).launch {
_continueWatchLiveData.postValue(ApiResult.Loading())
val response = RetrofitHelper.handleApiCall {
moduleApiService.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)
}
}
fun clearData(){
_englishWebSeriesLiveData.postValue(ApiResult.Loading())
_hindiWebSeriesLiveData.postValue(ApiResult.Loading())
hindiWebSeriesData = null
englishWebSeriesData = null
shallLoadNewContinueWatchData = true
continueWatchData = null
}
fun loadEnglishWebSeries(){
CoroutineScope(Dispatchers.IO).launch {
_englishWebSeriesLiveData.postValue(ApiResult.Loading())

View File

@@ -0,0 +1,62 @@
package com.woka.webseries.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.bumptech.glide.Glide
import com.woka.databinding.ContinueShowViewHolderBinding
import com.woka.webseries.models.ContinueEpisodeData
import java.util.concurrent.Executors
class ContinueEpisodeAdapter(val context: Context,
config: AsyncDifferConfig<ContinueEpisodeData>): ListAdapter<ContinueEpisodeData, ContinueEpisodeAdapter.ContinueEpisodeViewHolder>(config) {
inner class ContinueEpisodeViewHolder(val binding: ContinueShowViewHolderBinding): ViewHolder(binding.root)
companion object{
private val DIFF_UTIL = object : DiffUtil.ItemCallback<ContinueEpisodeData>(){
override fun areItemsTheSame(oldItem: ContinueEpisodeData, newItem: ContinueEpisodeData): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: ContinueEpisodeData, newItem: ContinueEpisodeData): Boolean {
return true
}
}
private val DIFF_CONFIG = AsyncDifferConfig.Builder(DIFF_UTIL)
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
.build()
}
constructor(context: Context): this(context, DIFF_CONFIG)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContinueEpisodeViewHolder {
return ContinueEpisodeViewHolder(
ContinueShowViewHolderBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: ContinueEpisodeViewHolder, position: Int) {
val episode = getItem(holder.absoluteAdapterPosition)
holder.binding.apply {
episode.thumbnail_path?.let {
Glide.with(context.applicationContext)
.load(it)
.error(android.R.color.darker_gray)
.into(image)
}
title.text = episode.episode_title
val detail = "S${episode.season_number}-E${episode.episode_number}"
details.text = detail
}
}
}

View File

@@ -0,0 +1,48 @@
package com.woka.webseries.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.TextView
import com.woka.R
import com.woka.utils.hide
import com.woka.utils.show
class SpinnerAdapter(context: Context, list: List<String>): ArrayAdapter<String>(context, 0, list){
private var currentSelection: Int = 0
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
return createViewFromResource(convertView, parent, position)
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: LayoutInflater.from(context).inflate(R.layout.spinner_view_holder, parent, false)
val textView = view.findViewById<TextView>(R.id.spinner_text_view)
val tickView = view.findViewById<ImageView>(R.id.spinner_tick)
textView.text = getItem(position)
if (currentSelection == position){
tickView.show()
}else{
tickView.hide()
}
return view
}
private fun createViewFromResource(convertView: View?, parent: ViewGroup, position: Int): View {
val view = convertView ?: LayoutInflater.from(context).inflate(R.layout.spinner_view_holder, parent, false)
val textView = view.findViewById<TextView>(R.id.spinner_text_view)
textView.text = getItem(position)
return view
}
fun selectPosition(position: Int){
this.currentSelection = position
}
}

View File

@@ -0,0 +1,13 @@
package com.woka.webseries.models
data class ContentMoreDetailX(
val content_hd_url: String?,
val content_id: Int?,
val content_sd_url: String?,
val description: String?,
val id: Int?,
val language_master_id: Int?,
val post_type: Int?,
val tags_keywords: String?,
val title: String?
)

View File

@@ -0,0 +1,26 @@
package com.woka.webseries.models
data class ContinueEpisodeData(
val bookmark_count: Int?,
val content_more_details: List<ContentMoreDetailX>?,
val episode_description: String?,
val episode_duration: String?,
val episode_number: Int?,
val episode_title: String?,
val episode_url: String?,
val id: Int?,
val is_liked: Boolean?,
val language_master_id: Int?,
val likes_count: Int?,
val mark_as_favourite: Boolean?,
val release_date: String?,
val season_master_id: Int?,
val season_number: String?,
val show_data_count: ShowDataCount?,
val tags_keyword: String?,
val thumbnail_img_url: String?,
val thumbnail_path: String?,
val user_video_view: List<UserVideoView>?,
val views_count: Int?,
val watch_shows_master_id: Int?
)

View File

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

View File

@@ -13,7 +13,7 @@ data class ShowData(
val gender_master_id: String?,
val id: Int?,
var is_liked: Boolean?,
val liked_category_ids: Int?,
val liked_category_ids: String?,
var likes_count: Int?,
var mark_as_favourite: Boolean?,
val season_data: List<SeasonData?>?,

View File

@@ -0,0 +1,7 @@
package com.woka.webseries.models
data class ShowDataCount(
val id: Int?,
val total_episodes: Int?,
val total_seasons: Int?
)

View File

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

View File

@@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import com.woka.networking.ApiResult
import com.woka.webseries.WebSeriesRepository
import com.woka.webseries.models.ContinueEpisodeResponse
import com.woka.webseries.models.WebSeriesResponse
class WebSeriesViewModel: ViewModel() {
@@ -13,4 +14,7 @@ class WebSeriesViewModel: ViewModel() {
val hindiWebSeriesData: LiveData<ApiResult<WebSeriesResponse>>
get() = WebSeriesRepository.hindiWebSeriesLiveData
val continueWatchLiveData: LiveData<ApiResult<ContinueEpisodeResponse>>
get() = WebSeriesRepository.continueWatchLiveData
}

View File

@@ -0,0 +1,26 @@
package com.woka.webseries.views
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.woka.R
import com.woka.databinding.ActivitySeasonBinding
class SeasonActivity : AppCompatActivity() {
private lateinit var binding: ActivitySeasonBinding
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
}
}
}

View File

@@ -1,7 +1,6 @@
package com.woka.webseries.views
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener
@@ -17,17 +16,17 @@ import com.woka.R
import com.woka.databinding.ActivityWebSeriesBinding
import com.woka.modules.ModuleRepository
import com.woka.networking.ApiResult
import com.woka.utils.TAG
import com.woka.utils.WokaBaseActivity
import com.woka.utils.hide
import com.woka.utils.show
import com.woka.utils.toast
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.WebSeriesResponse
import com.woka.webseries.viewmodel.WebSeriesViewModel
class WebSeriesActivity : WokaBaseActivity(), Observer<ApiResult<WebSeriesResponse>> {
class WebSeriesActivity : WokaBaseActivity(), Observer<ApiResult<WebSeriesResponse>>{
private lateinit var binding: ActivityWebSeriesBinding
@@ -36,6 +35,10 @@ class WebSeriesActivity : WokaBaseActivity(), Observer<ApiResult<WebSeriesRespon
private lateinit var engShowAdapter: WebSeriesShowAdapter
private lateinit var hinShowAdapter: WebSeriesShowAdapter
private lateinit var continueWatchAdapter: ContinueEpisodeAdapter
private var catSpinnerAdapter: SpinnerAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
@@ -67,6 +70,18 @@ class WebSeriesActivity : WokaBaseActivity(), Observer<ApiResult<WebSeriesRespon
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()
}
}
}
}
@@ -75,22 +90,20 @@ class WebSeriesActivity : WokaBaseActivity(), Observer<ApiResult<WebSeriesRespon
// adapters
engShowAdapter = WebSeriesShowAdapter(this, "1")
hinShowAdapter = WebSeriesShowAdapter(this, "18")
continueWatchAdapter = ContinueEpisodeAdapter(this)
binding.apply {
// making space for masila image
topPinnedView.post {
val imgParams = masilaImage.layoutParams as CollapsingToolbarLayout.LayoutParams
imgParams.setMargins(0, 0, 0, topPinnedView.height)
masilaImage.layoutParams = imgParams
}
adjustMasilaImage()
toolbar.title.text = getString(R.string.web_series)
rvHindiWebSeries.adapter = hinShowAdapter
rvEngWebSeries.adapter = engShowAdapter
rvContinueWatch.adapter = continueWatchAdapter
((rvHindiWebSeries.itemAnimator) as SimpleItemAnimator).supportsChangeAnimations = false
((rvEngWebSeries.itemAnimator) as SimpleItemAnimator).supportsChangeAnimations = false
((rvContinueWatch.itemAnimator) as SimpleItemAnimator).supportsChangeAnimations = false
}
}
@@ -99,10 +112,41 @@ class WebSeriesActivity : WokaBaseActivity(), Observer<ApiResult<WebSeriesRespon
viewmodel.hindiWebSeriesData.observe(this, this)
viewmodel.englishWebSeriesData.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 ->
continueWatchAdapter.submitList(continueWatchList)
}
}
}
}
binding.categorySpinner.onItemSelectedListener = object : OnItemSelectedListener{
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
catSpinnerAdapter?.selectPosition(position)
loadShowData()
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
ModuleRepository.showCategoryLiveData.observe(this){
when(it){
is ApiResult.Error -> {}
is ApiResult.Error -> {
binding.errorView.show()
binding.shimmer.hide()
}
is ApiResult.Loading -> {}
is ApiResult.Success -> {
@@ -115,45 +159,42 @@ class WebSeriesActivity : WokaBaseActivity(), Observer<ApiResult<WebSeriesRespon
}
}
val adapter: ArrayAdapter<*> = ArrayAdapter(
this,
android.R.layout.simple_spinner_item,
categories
)
catSpinnerAdapter = SpinnerAdapter(this, categories)
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item
)
loadShowData()
binding.categorySpinner.setAdapter(adapter)
binding.categorySpinner.setAdapter(catSpinnerAdapter)
}
}
}
binding.categorySpinner.onItemSelectedListener = object : OnItemSelectedListener{
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
if (binding.categorySpinner.selectedItemId == 0L){
WebSeriesRepository.loadHindiWebSeries()
}else{
WebSeriesRepository.loadEnglishWebSeries()
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
}
override fun onChanged(value: ApiResult<WebSeriesResponse>) {
when (value){
is ApiResult.Error -> {}
is ApiResult.Error -> {
binding.shimmer.hide()
binding.errorView.show()
}
is ApiResult.Loading -> {}
is ApiResult.Success -> {
value.data?.show_data?.let {
binding.trailerView.show()
adjustMasilaImage()
binding.shimmer.hide()
binding.spinnerCard.show()
binding.selectLangTxt.show()
WebSeriesRepository.continueWatchData?.let {
binding.continueWatchTxt.show()
binding.rvContinueWatch.show()
}?:{
binding.continueWatchTxt.hide()
binding.rvContinueWatch.hide()
}
if (binding.categorySpinner.selectedItemPosition <= 0){
// hindi
binding.rvHindiWebSeries.show()
@@ -171,4 +212,23 @@ class WebSeriesActivity : WokaBaseActivity(), Observer<ApiResult<WebSeriesRespon
}
}
}
private fun loadShowData(){
if (binding.categorySpinner.selectedItemId == 0L){
WebSeriesRepository.loadHindiWebSeries()
}else{
WebSeriesRepository.loadEnglishWebSeries()
}
}
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
}
}
}
}

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".webseries.views.SeasonActivity">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -12,11 +12,124 @@
<include android:id="@+id/toolbar"
layout="@layout/layout_toolbar"/>
<RelativeLayout
android:id="@+id/shimmer"
android:visibility="visible"
android:background="@color/color_primary_dark"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.facebook.shimmer.ShimmerFrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:shimmer_auto_start="true"
app:shimmer_duration="1500"
app:shimmer_highlight_alpha="0.5"
>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="@dimen/_160sdp"
android:background="@color/white_50"
/>
<View
android:layout_width="@dimen/_100sdp"
android:layout_height="@dimen/_37sdp"
android:background="@color/white_50"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="10dp"
/>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/_140sdp"
android:background="@color/white_50"
android:layout_marginHorizontal="15dp"
/>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/_140sdp"
android:background="@color/white_50"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="15dp"
/>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/_140sdp"
android:background="@color/white_50"
android:layout_marginVertical="15dp"
android:layout_marginHorizontal="15dp"
/>
</LinearLayout>
</ScrollView>
</com.facebook.shimmer.ShimmerFrameLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/error_view"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_primary_dark"
android:orientation="vertical"
android:gravity="center"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/something_went_wrong"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/white"
android:textSize="@dimen/_14ssp"
/>
<Button
android:id="@+id/retry_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/retry"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/white"
android:textSize="@dimen/_14ssp"
android:paddingHorizontal="25dp"
android:layout_marginTop="15dp"
android:background="@drawable/grad_btn_bg_4"
/>
</LinearLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/trailer_view"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
@@ -104,20 +217,49 @@
android:orientation="vertical">
<TextView
android:id="@+id/continue_watch_txt"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/continue_watching"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/white"
android:textSize="@dimen/_14ssp"
android:layout_marginHorizontal="15dp"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_continue_watch"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/continue_show_view_holder"
android:orientation="horizontal"
/>
<TextView
android:id="@+id/select_lang_txt"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select_video_language"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/white"
android:textSize="@dimen/_12ssp"
android:textSize="@dimen/_14ssp"
android:layout_marginHorizontal="15dp"
/>
<androidx.cardview.widget.CardView
android:layout_width="@dimen/_120sdp"
android:id="@+id/spinner_card"
android:visibility="gone"
android:layout_width="@dimen/_160sdp"
android:layout_height="@dimen/_40sdp"
android:layout_marginHorizontal="15dp"
@@ -131,11 +273,9 @@
android:layout_width="match_parent"
android:layout_height="@dimen/_37sdp"
android:layout_marginStart="5dp"
android:popupBackground="@drawable/round_bg_5_white"
android:layout_gravity="center_vertical"
android:textAlignment="textStart"
/>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<com.woka.utils.PressableCard xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:pressType="scale"
app:scaleFrom="0.97"
android:layout_marginEnd="5dp"
android:layout_marginStart="10dp"
android:layout_marginVertical="10dp">
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="5dp"
app:cardBackgroundColor="@color/white"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginVertical="10dp"
>
<ImageView
android:id="@+id/image"
android:layout_width="@dimen/_240sdp"
android:layout_height="@dimen/_120sdp"
android:contentDescription="@string/image"
android:src="@android:color/darker_gray"
android:scaleType="fitXY"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
tools:text="Woka title of show"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/color_primary"
android:textSize="@dimen/_14ssp"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="@id/image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/details"
android:layout_marginTop="5dp"
android:layout_marginEnd="10dp"
/>
<TextView
android:id="@+id/details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="S1-E2"
android:fontFamily="@font/exo_2"
android:textColor="@color/color_primary"
android:textSize="@dimen/_12ssp"
android:textAlignment="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/image"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</com.woka.utils.PressableCard>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:paddingVertical="15dp"
android:paddingHorizontal="15dp"
xmlns:ools="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/spinner_text_view"
android:layout_width="0dp"
android:layout_height="match_parent"
tools:text="English"
android:fontFamily="@font/exo_2"
android:textColor="@color/black"
android:textSize="@dimen/_12ssp"
android:textAlignment="textStart"
ools:layout_constraintStart_toStartOf="parent"
ools:layout_constraintEnd_toStartOf="@id/spinner_tick"
ools:layout_constraintTop_toTopOf="parent"
ools:layout_constraintBottom_toBottomOf="parent"
/>
<ImageView
android:id="@+id/spinner_tick"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/image"
android:src="@drawable/ic_tick"
ools:layout_constraintEnd_toEndOf="parent"
ools:layout_constraintTop_toTopOf="parent"
ools:layout_constraintBottom_toBottomOf="parent"
ools:tint="@color/color_primary_dark" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -176,4 +176,5 @@
<string name="no_internet">No internet</string>
<string name="trailer">TRAILER</string>
<string name="select_video_language">Select video language</string>
<string name="continue_watching">Continue watching</string>
</resources>