Created Games module: UI and backend

Integrated game listing and data caching

Data syncing with adapters and MyListFragment

Dialog showing for game.

GamePlayerActivity created - loading url, keeping screen on, hiding system bars.

Integrated karaoke api and caching
data syncing for like and fav data
This commit is contained in:
2024-07-08 19:57:39 +05:30
parent 6b193b1cc7
commit 294afcb80a
34 changed files with 1787 additions and 217 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" > xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
@@ -14,11 +14,22 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.Woka" android:theme="@style/Theme.Woka"
tools:targetApi="31" > tools:targetApi="31">
<activity
android:name=".wokagames.playerr.GamePlayerActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:exported="false"
android:launchMode="singleTask"
android:supportsPictureInPicture="true"
android:theme="@style/FullScreenTheme"/>
<activity
android:name=".wokagames.views.GamesActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity <activity
android:name=".audiobooks.views.AudioBooksActivity" android:name=".audiobooks.views.AudioBooksActivity"
android:exported="false" android:exported="false"
android:screenOrientation="portrait"/> android:screenOrientation="portrait" />
<activity <activity
android:name=".players.views.PlayerActivity" android:name=".players.views.PlayerActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
@@ -103,7 +114,7 @@
android:name=".onboard.views.WelcomeActivity" android:name=".onboard.views.WelcomeActivity"
android:exported="true" android:exported="true"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/Theme.App.Starting" > android:theme="@style/Theme.App.Starting">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View File

@@ -1,10 +1,11 @@
package com.woka.audiobooks.adapters package com.woka.audiobooks.adapters
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView.ViewHolder import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.woka.R import com.woka.R
import com.woka.WokaApp.Companion.userPrefs import com.woka.WokaApp.Companion.userPrefs
@@ -14,21 +15,32 @@ import com.woka.databinding.ShowViewHolderBinding
import com.woka.utils.isNetworkConnected import com.woka.utils.isNetworkConnected
import com.woka.utils.show import com.woka.utils.show
import com.woka.utils.toast import com.woka.utils.toast
import java.util.concurrent.Executors
class AudioBooksAdapter( class AudioBooksAdapter(
private val context: Context, private val context: Context,
private var onBookClicked: (AudioBookData) -> Unit, private var onBookClicked: (AudioBookData) -> Unit,
private var onBookChanged: (id: Int) -> Unit private var onBookChanged: (id: Int) -> Unit
): RecyclerView.Adapter<AudioBooksAdapter.AudioBookViewHolder>() { ): ListAdapter<AudioBookData, AudioBooksAdapter.AudioBookViewHolder>(ASYNC_DIFF_UTIL) {
inner class AudioBookViewHolder(val binding: ShowViewHolderBinding): ViewHolder(binding.root) inner class AudioBookViewHolder(val binding: ShowViewHolderBinding): ViewHolder(binding.root)
var audioBookList: List<AudioBookData> = ArrayList() companion object{
val DIFF_UTIL = object : DiffUtil.ItemCallback<AudioBookData>(){
override fun areItemsTheSame(oldItem: AudioBookData, newItem: AudioBookData): Boolean = oldItem.id == newItem.id
@SuppressLint("NotifyDataSetChanged") override fun areContentsTheSame(oldItem: AudioBookData, newItem: AudioBookData): Boolean {
fun submitListShowList(it: List<AudioBookData>) { return oldItem.thumbnail_path == newItem.thumbnail_path &&
this.audioBookList = it oldItem.title == newItem.title &&
notifyDataSetChanged() oldItem.is_liked == newItem.is_liked &&
oldItem.mark_as_favourite == newItem.mark_as_favourite &&
oldItem.likes_count == newItem.likes_count
}
}
val ASYNC_DIFF_UTIL = AsyncDifferConfig.Builder(DIFF_UTIL)
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
.build()
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AudioBookViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AudioBookViewHolder {
@@ -41,10 +53,8 @@ class AudioBooksAdapter(
) )
} }
override fun getItemCount(): Int = audioBookList.size
override fun onBindViewHolder(holder: AudioBookViewHolder, position: Int) { override fun onBindViewHolder(holder: AudioBookViewHolder, position: Int) {
val audioBook = audioBookList[holder.absoluteAdapterPosition] val audioBook = getItem(holder.absoluteAdapterPosition)
holder.binding.apply { holder.binding.apply {
audioBook.thumbnail_path?.let { audioBook.thumbnail_path?.let {

View File

@@ -7,7 +7,6 @@ import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.InsetDrawable import android.graphics.drawable.InsetDrawable
import android.os.Bundle import android.os.Bundle
import android.text.Html import android.text.Html
import android.util.Log
import android.view.WindowManager import android.view.WindowManager
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
@@ -24,18 +23,14 @@ import com.woka.audiobooks.adapters.ContinueAudioAdapter
import com.woka.audiobooks.models.audiodata.AudioBookData import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.audiobooks.models.continuedata.ContinueAudioData import com.woka.audiobooks.models.continuedata.ContinueAudioData
import com.woka.databinding.ActivityAudioBooksBinding import com.woka.databinding.ActivityAudioBooksBinding
import com.woka.databinding.DialogAudioBookBinding import com.woka.databinding.DialogModuleShowerBinding
import com.woka.networking.ApiResult import com.woka.networking.ApiResult
import com.woka.players.models.VideoPlayList import com.woka.players.models.VideoPlayList
import com.woka.players.views.PlayerActivity import com.woka.players.views.PlayerActivity
import com.woka.utils.TAG
import com.woka.utils.WokaBaseActivity import com.woka.utils.WokaBaseActivity
import com.woka.utils.hide import com.woka.utils.hide
import com.woka.utils.show import com.woka.utils.show
import com.woka.webseries.WebSeriesRepository
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
@@ -46,7 +41,7 @@ class AudioBooksActivity : WokaBaseActivity() {
private lateinit var audioBookAdapter: AudioBooksAdapter private lateinit var audioBookAdapter: AudioBooksAdapter
private lateinit var continueAudioAdapter: ContinueAudioAdapter private lateinit var continueAudioAdapter: ContinueAudioAdapter
private lateinit var dialogBinding: DialogAudioBookBinding private lateinit var dialogBinding: DialogModuleShowerBinding
private lateinit var audioDialog: Dialog private lateinit var audioDialog: Dialog
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@@ -68,7 +63,7 @@ class AudioBooksActivity : WokaBaseActivity() {
continueAudioAdapter = continueAudioAdapter =
ContinueAudioAdapter(this, ::onContinueBookClicked, ::onContinueBookChanged) ContinueAudioAdapter(this, ::onContinueBookClicked, ::onContinueBookChanged)
dialogBinding = DialogAudioBookBinding.inflate(layoutInflater) dialogBinding = DialogModuleShowerBinding.inflate(layoutInflater)
audioDialog = Dialog(this) audioDialog = Dialog(this)
audioDialog.setContentView(dialogBinding.root) audioDialog.setContentView(dialogBinding.root)
@@ -163,7 +158,7 @@ class AudioBooksActivity : WokaBaseActivity() {
binding.rvAudioBooks.show() binding.rvAudioBooks.show()
binding.listenTxt.show() binding.listenTxt.show()
audioBookAdapter.submitListShowList(audioBookData) audioBookAdapter.submitList(audioBookData)
} }
} }
} }
@@ -253,8 +248,8 @@ class AudioBooksActivity : WokaBaseActivity() {
private fun onContinueBookChanged(id: Int) { private fun onContinueBookChanged(id: Int) {
// updating book list // updating book list
val position = audioBookAdapter.audioBookList.indexOfFirst { it.id == id } val position = audioBookAdapter.currentList.indexOfFirst { it.id == id }
if (position >= 0 && position < audioBookAdapter.audioBookList.size) { if (position >= 0 && position < audioBookAdapter.currentList.size) {
audioBookAdapter.notifyItemChanged(position) audioBookAdapter.notifyItemChanged(position)
} }
} }
@@ -311,6 +306,7 @@ class AudioBooksActivity : WokaBaseActivity() {
fav.isSelected = audioBookData.mark_as_favourite == true fav.isSelected = audioBookData.mark_as_favourite == true
like.isSelected = audioBookData.is_liked == true like.isSelected = audioBookData.is_liked == true
likeCount.text = "${audioBookData.likes_count}"
year.text = try { year.text = try {
audioBookData.release_date?.let { audioBookData.release_date?.let {
@@ -373,6 +369,7 @@ class AudioBooksActivity : WokaBaseActivity() {
onContinueBookChanged(it) onContinueBookChanged(it)
} }
like.isSelected = !like.isSelected like.isSelected = !like.isSelected
likeCount.text = "${audioBookData.likes_count}"
} }
fav.setOnClickListener { fav.setOnClickListener {

View File

@@ -33,6 +33,7 @@ import com.woka.utils.hide
import com.woka.utils.scaleAnimate import com.woka.utils.scaleAnimate
import com.woka.utils.show import com.woka.utils.show
import com.woka.webseries.views.WebSeriesActivity import com.woka.webseries.views.WebSeriesActivity
import com.woka.wokagames.views.GamesActivity
class Home1Fragment : Fragment(), Listener { class Home1Fragment : Fragment(), Listener {
@@ -186,6 +187,12 @@ class Home1Fragment : Fragment(), Listener {
startActivity(Intent(it, AudioBooksActivity::class.java)) startActivity(Intent(it, AudioBooksActivity::class.java))
} }
} }
play.setOnClickListener {
activity?.let {
startActivity(Intent(it, GamesActivity::class.java))
}
}
} }
} }

View File

@@ -2,12 +2,12 @@ package com.woka.home.fragments
import android.app.Dialog import android.app.Dialog
import android.content.Intent import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.InsetDrawable import android.graphics.drawable.InsetDrawable
import android.os.Bundle import android.os.Bundle
import android.text.Html import android.text.Html
import android.util.Log
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -24,25 +24,29 @@ import com.woka.R
import com.woka.WokaApp import com.woka.WokaApp
import com.woka.audiobooks.AudioBookRepository import com.woka.audiobooks.AudioBookRepository
import com.woka.audiobooks.models.audiodata.AudioBookData import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.databinding.DialogAudioBookBinding import com.woka.databinding.DialogModuleShowerBinding
import com.woka.databinding.FragmentMyListBinding import com.woka.databinding.FragmentMyListBinding
import com.woka.home.mylist.MyListRepository import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.adapters.FavAudioAdapter import com.woka.home.mylist.adapters.FavAudioAdapter
import com.woka.home.mylist.adapters.GamesAdapter import com.woka.home.mylist.adapters.FavGamesAdapter
import com.woka.home.mylist.adapters.KaraokeAdapter import com.woka.home.mylist.adapters.KaraokeAdapter
import com.woka.home.mylist.adapters.WebSeriesAdapter import com.woka.home.mylist.adapters.WebSeriesAdapter
import com.woka.home.mylist.models.PostType import com.woka.home.mylist.models.PostType
import com.woka.home.mylist.models.BookmarkedShowData import com.woka.home.mylist.models.BookmarkedShowData
import com.woka.home.mylist.models.FavAudioBookData import com.woka.home.mylist.models.FavAudioBookData
import com.woka.home.mylist.models.FavGameData
import com.woka.networking.ApiResult import com.woka.networking.ApiResult
import com.woka.players.models.VideoPlayList import com.woka.players.models.VideoPlayList
import com.woka.players.views.PlayerActivity import com.woka.players.views.PlayerActivity
import com.woka.utils.TAG
import com.woka.utils.hide import com.woka.utils.hide
import com.woka.utils.isNetworkConnected import com.woka.utils.isNetworkConnected
import com.woka.utils.show import com.woka.utils.show
import com.woka.utils.toast import com.woka.utils.toast
import com.woka.webseries.views.SeasonActivity import com.woka.webseries.views.SeasonActivity
import com.woka.wokagames.GamesRepository
import com.woka.wokagames.models.listing.GameData
import com.woka.wokagames.playerr.GamePlayerActivity
import com.woka.wokagames.playerr.GamePlayerData
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
@@ -56,12 +60,12 @@ class MyListFragment : Fragment() {
private lateinit var webSeriesHAdapter: WebSeriesAdapter private lateinit var webSeriesHAdapter: WebSeriesAdapter
private lateinit var audioBooksAdapter: FavAudioAdapter private lateinit var audioBooksAdapter: FavAudioAdapter
private lateinit var karaokeAdapter: KaraokeAdapter private lateinit var karaokeAdapter: KaraokeAdapter
private lateinit var gamesAdapter: GamesAdapter private lateinit var gamesAdapter: FavGamesAdapter
private var webShowIntentLauncher: ActivityResultLauncher<Intent>? = null private var webShowIntentLauncher: ActivityResultLauncher<Intent>? = null
private lateinit var dialogBinding: DialogAudioBookBinding private lateinit var dialogBinding: DialogModuleShowerBinding
private lateinit var audioDialog: Dialog private lateinit var moduleShowerDialog: Dialog
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
@@ -74,14 +78,14 @@ class MyListFragment : Fragment() {
webSeriesHAdapter = WebSeriesAdapter(requireContext(),"18", ::onListGotEmpty) webSeriesHAdapter = WebSeriesAdapter(requireContext(),"18", ::onListGotEmpty)
audioBooksAdapter = FavAudioAdapter(requireContext(), ::onListGotEmpty, ::onAudioBookClicked) audioBooksAdapter = FavAudioAdapter(requireContext(), ::onListGotEmpty, ::onAudioBookClicked)
karaokeAdapter = KaraokeAdapter(requireContext(), ::onListGotEmpty) karaokeAdapter = KaraokeAdapter(requireContext(), ::onListGotEmpty)
gamesAdapter = GamesAdapter(requireContext(), ::onListGotEmpty) gamesAdapter = FavGamesAdapter(requireContext(), ::onListGotEmpty, ::onGameClicked)
// dialogs // dialogs
dialogBinding = DialogAudioBookBinding.inflate(layoutInflater) dialogBinding = DialogModuleShowerBinding.inflate(layoutInflater)
audioDialog = Dialog(requireContext()) moduleShowerDialog = Dialog(requireContext())
audioDialog.setContentView(dialogBinding.root) moduleShowerDialog.setContentView(dialogBinding.root)
initAudioDialog() initModuleShowerDialog()
initViews() initViews()
@@ -118,7 +122,7 @@ class MyListFragment : Fragment() {
private fun clickEvents(){ private fun clickEvents(){
binding.apply { binding.apply {
backBtn.setOnClickListener { backBtn.setOnClickListener {
activity?.onBackPressed() activity?.onBackPressedDispatcher?.onBackPressed()
} }
} }
} }
@@ -242,78 +246,25 @@ class MyListFragment : Fragment() {
} }
} }
private fun initAudioDialog() { private fun initModuleShowerDialog() {
try { try {
val back = ColorDrawable(Color.TRANSPARENT) val back = ColorDrawable(Color.TRANSPARENT)
val inset = InsetDrawable(back, 50) val inset = InsetDrawable(back, 50)
audioDialog.window!!.setBackgroundDrawable(inset) moduleShowerDialog.window!!.setBackgroundDrawable(inset)
} catch (e: Exception) { } catch (e: Exception) {
// do nothing // do nothing
} }
try { try {
val layoutParams = audioDialog.window!!.attributes val layoutParams = moduleShowerDialog.window!!.attributes
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
audioDialog.window!!.setAttributes(layoutParams) moduleShowerDialog.window!!.setAttributes(layoutParams)
} catch (e: Exception) { } catch (e: Exception) {
// do nothing // do nothing
} }
dialogBinding.close.setOnClickListener { audioDialog.dismiss() } dialogBinding.close.setOnClickListener { moduleShowerDialog.dismiss() }
}
private fun onAudioItemChanged(id: Int, isRemoved: Boolean) {
// updating book list
val position = audioBooksAdapter.currentList.indexOfFirst { it.id == id }
if (position >= 0 && position < audioBooksAdapter.currentList.size) {
if (!isRemoved) audioBooksAdapter.notifyItemChanged(position)
else audioBooksAdapter.notifyItemRemoved(position)
}
}
private fun onAudioListenClicked(audioBookData: AudioBookData) {
var url: String? = null
var title = ""
audioBookData.content_more_details?.let {moreDetails ->
if (moreDetails.isNotEmpty()){
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetails.size > 1){
url = moreDetails[1]?.url
title = moreDetails[1]?.title?:""
}else{
url = moreDetails[0]?.url
title = moreDetails[0]?.title?:""
}
}else{
url = audioBookData.audio_url
title = audioBookData.title?:""
}
}
activity?.let {activity ->
url?.let {
startActivity(Intent(activity, PlayerActivity::class.java).apply {
putExtra(
PlayerActivity.EXTRA_PLAY_LIST,
VideoPlayList(
ArrayList<PlaylistItem>().apply {
add(
PlaylistItem.Builder()
.file(it)
.image(it)
.title(title)
.build()
)
},
null
)
)
putExtra(PlayerActivity.EXTRA_PLAY_INDEX, 0)
})
}
}
} }
private fun onListGotEmpty(postType: PostType, isEng: Boolean = true){ private fun onListGotEmpty(postType: PostType, isEng: Boolean = true){
@@ -364,7 +315,7 @@ class MyListFragment : Fragment() {
} }
// audio books // audio books
private fun onAudioBookClicked(audioBookData: AudioBookData, position: Int){ private fun onAudioBookClicked(audioBookData: FavAudioBookData, position: Int){
dialogBinding.apply { dialogBinding.apply {
audioBookData.content_more_details?.let { moreDetailsList -> audioBookData.content_more_details?.let { moreDetailsList ->
@@ -374,6 +325,7 @@ class MyListFragment : Fragment() {
fav.isSelected = audioBookData.mark_as_favourite == true fav.isSelected = audioBookData.mark_as_favourite == true
like.isSelected = audioBookData.is_liked == true like.isSelected = audioBookData.is_liked == true
likeCount.text = "${audioBookData.likes_count}"
year.text = try { year.text = try {
audioBookData.release_date?.let { audioBookData.release_date?.let {
@@ -421,6 +373,10 @@ class MyListFragment : Fragment() {
) )
} }
activity?.let {
watchCard.backgroundTintList = ColorStateList.valueOf(it.getColor(R.color.audio_grad_one))
}
watchCard.text = getString(R.string.listen_now)
watchCard.setOnClickListener { watchCard.setOnClickListener {
onAudioListenClicked(audioBookData) onAudioListenClicked(audioBookData)
} }
@@ -432,9 +388,10 @@ class MyListFragment : Fragment() {
) )
audioBookData.id?.let { audioBookData.id?.let {
onAudioItemChanged(it, false) onAudioItemChanged(it)
} }
like.isSelected = !like.isSelected like.isSelected = !like.isSelected
likeCount.text = "${audioBookData.likes_count}"
} }
fav.setOnClickListener { fav.setOnClickListener {
@@ -444,7 +401,7 @@ class MyListFragment : Fragment() {
} }
AudioBookRepository.updateFavShow( AudioBookRepository.updateFavShow(
audioBookData, AudioBookData(audioBookData),
!fav.isSelected !fav.isSelected
) )
@@ -458,18 +415,197 @@ class MyListFragment : Fragment() {
onListGotEmpty(PostType.AUDIO_BOOKS, true) onListGotEmpty(PostType.AUDIO_BOOKS, true)
} }
audioDialog.dismiss() moduleShowerDialog.dismiss()
} }
close.setOnClickListener { close.setOnClickListener {
audioDialog.dismiss() moduleShowerDialog.dismiss()
} }
audioDialog.show() moduleShowerDialog.show()
} }
} }
} }
private fun onAudioItemChanged(id: Int) {
// updating book list
val position = audioBooksAdapter.currentList.indexOfFirst { it.id == id }
if (position >= 0 && position < audioBooksAdapter.currentList.size) {
audioBooksAdapter.notifyItemChanged(position)
}
}
private fun onAudioListenClicked(audioBookData: FavAudioBookData) {
var url: String? = null
var title = ""
audioBookData.content_more_details?.let {moreDetails ->
if (moreDetails.isNotEmpty()){
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetails.size > 1){
url = moreDetails[1]?.url
title = moreDetails[1]?.title?:""
}else{
url = moreDetails[0]?.url
title = moreDetails[0]?.title?:""
}
}else{
url = audioBookData.audio_url
title = audioBookData.title?:""
}
}
activity?.let {activity ->
url?.let {
startActivity(Intent(activity, PlayerActivity::class.java).apply {
putExtra(
PlayerActivity.EXTRA_PLAY_LIST,
VideoPlayList(
ArrayList<PlaylistItem>().apply {
add(
PlaylistItem.Builder()
.file(it)
.image(it)
.title(title)
.build()
)
},
null
)
)
putExtra(PlayerActivity.EXTRA_PLAY_INDEX, 0)
})
}
}
}
// woka games
private fun onGameClicked(gameData: FavGameData, position: Int){
dialogBinding.apply {
gameData.content_more_details?.let { moreDetailsList ->
gameData.thumbnail_path?.let {
image.loadImage(it)
}
fav.isSelected = gameData.mark_as_favourite == true
like.isSelected = gameData.is_liked == true
likeCount.text = "${gameData.likes_count}"
year.text = try {
gameData.release_date?.let {
val cal = Calendar.getInstance()
cal.time =
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).parse(
gameData.release_date
)!!
"${cal.get(Calendar.YEAR)}"
} ?: throw Exception()
} catch (e: Exception) {
"${gameData.release_date}"
}
if (moreDetailsList.isNotEmpty()) {
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) {
moreDetailsList[1]?.let { data ->
title.text = data.title
description.text = Html.fromHtml(
data.description?.replace(
"<br>",
" "
), Html.FROM_HTML_MODE_LEGACY
)
}
} else {
moreDetailsList[0]?.let { data ->
title.text = data.title
description.text = Html.fromHtml(
data.description?.replace(
"<br>",
" "
), Html.FROM_HTML_MODE_LEGACY
)
}
}
} else {
title.text = gameData.title
description.text = Html.fromHtml(
gameData.description?.replace(
"<br>",
" "
), Html.FROM_HTML_MODE_LEGACY
)
}
activity?.let {
watchCard.backgroundTintList = ColorStateList.valueOf(it.getColor(R.color.game_grad_one))
}
watchCard.text = getString(R.string.play_now)
watchCard.setOnClickListener {
activity?.let {activity ->
gameData.game_url?.let {
startActivity(Intent(activity, GamePlayerActivity::class.java).apply {
putExtra(GamePlayerActivity.EXTRA_GAME_PLAYER_DATA, GamePlayerData(it, gameData.screen_orientation == "Landscape"))
})
}
}
}
like.setOnClickListener {
GamesRepository.likeUnLikeGame(
"${gameData.id}",
!like.isSelected
)
gameData.id?.let {
onGameChanged(it)
}
like.isSelected = !like.isSelected
likeCount.text = "${gameData.likes_count}"
}
fav.setOnClickListener {
if (context?.isNetworkConnected() == false){
toast(getString(R.string.no_internet))
return@setOnClickListener
}
GamesRepository.updateFavShow(
GameData(gameData),
!fav.isSelected
)
try {
gamesAdapter.notifyItemRemoved(position)
} catch (e: Exception) {
// do nothing
}
if (gamesAdapter.currentList.isEmpty()){
onListGotEmpty(PostType.GAMES, true)
}
moduleShowerDialog.dismiss()
}
close.setOnClickListener {
moduleShowerDialog.dismiss()
}
moduleShowerDialog.show()
}
}
}
private fun onGameChanged(id: Int) {
// updating continue book list
val position = gamesAdapter.currentList.indexOfFirst { it.id == id }
if (position >= 0 && position < gamesAdapter.currentList.size) {
gamesAdapter.notifyItemChanged(position)
}
}
companion object { companion object {
fun newInstance() = MyListFragment() fun newInstance() = MyListFragment()
} }

View File

@@ -21,7 +21,7 @@ import java.util.concurrent.Executors
class FavAudioAdapter(private val context: Context, class FavAudioAdapter(private val context: Context,
config: AsyncDifferConfig<FavAudioBookData>, config: AsyncDifferConfig<FavAudioBookData>,
private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit), private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit),
private var onBookClicked: (AudioBookData, Int) -> Unit): ListAdapter<FavAudioBookData, FavoriteViewHolder>(config) { private var onBookClicked: (FavAudioBookData, Int) -> Unit): ListAdapter<FavAudioBookData, FavoriteViewHolder>(config) {
companion object{ companion object{
private val DIFF_UTIL = object : DiffUtil.ItemCallback<FavAudioBookData>(){ private val DIFF_UTIL = object : DiffUtil.ItemCallback<FavAudioBookData>(){
@@ -41,7 +41,7 @@ class FavAudioAdapter(private val context: Context,
constructor(context: Context, constructor(context: Context,
onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit), onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit),
onBookClicked: (AudioBookData, Int) -> Unit): this(context, DIFF_CONFIG, onListEmptyListener, onBookClicked) onBookClicked: (FavAudioBookData, Int) -> Unit): this(context, DIFF_CONFIG, onListEmptyListener, onBookClicked)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteViewHolder {
return FavoriteViewHolder( return FavoriteViewHolder(
@@ -121,7 +121,7 @@ class FavAudioAdapter(private val context: Context,
} }
root.setOnClickListener { root.setOnClickListener {
onBookClicked(AudioBookData(audioBook), holder.absoluteAdapterPosition) onBookClicked(audioBook, holder.absoluteAdapterPosition)
} }
} }
} }

View File

@@ -0,0 +1,128 @@
package com.woka.home.mylist.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import com.woka.R
import com.woka.WokaApp
import com.woka.databinding.FavViewHolderBinding
import com.woka.home.mylist.models.FavGameData
import com.woka.home.mylist.models.PostType
import com.woka.utils.isNetworkConnected
import com.woka.utils.show
import com.woka.utils.toast
import com.woka.wokagames.GamesRepository
import com.woka.wokagames.models.listing.GameData
import java.util.concurrent.Executors
class FavGamesAdapter(private val context: Context,
config: AsyncDifferConfig<FavGameData>,
private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit),
private val onGameClicked: ((FavGameData, Int) -> Unit)):
ListAdapter<FavGameData, FavoriteViewHolder>(config) {
companion object{
private val DIFF_UTIL = object : DiffUtil.ItemCallback<FavGameData>(){
override fun areItemsTheSame(oldItem: FavGameData, newItem: FavGameData): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: FavGameData, newItem: FavGameData): Boolean {
return oldItem.title == newItem.title &&
oldItem.is_liked == newItem.is_liked &&
oldItem.likes_count == newItem.likes_count
}
}
private val DIFF_CONFIG = AsyncDifferConfig.Builder(DIFF_UTIL)
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
.build()
}
constructor(context: Context,
onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit),
onGameClicked: ((gameData: FavGameData, pos: Int) -> Unit)): this(context, DIFF_CONFIG, onListEmptyListener, onGameClicked)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteViewHolder {
return FavoriteViewHolder(
FavViewHolderBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: FavoriteViewHolder, pos: Int) {
val gameData = getItem(holder.absoluteAdapterPosition)
holder.binding.apply {
gameData.thumbnail_path?.let {
image.loadImage(it)
}
gameData.content_more_details?.let {moreDetailsList ->
title.text = if (moreDetailsList.isNotEmpty()){
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){
moreDetailsList[1]?.title
}else{
moreDetailsList[0]?.title
}
}else{
gameData.title
}
}
like.show()
likeCount.show()
fav.show()
gameData.likes_count?.let {
likeCount.text = "$it"
}
gameData.is_liked?.let {
like.isSelected = it
}
like.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
GamesRepository.likeUnLikeGame(
"${gameData.id}",
!like.isSelected
)
like.isSelected = !like.isSelected
likeCount.text = "${gameData.likes_count}"
}
fav.isSelected = gameData.mark_as_favourite == true
fav.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
GamesRepository.updateFavShow(
GameData(gameData),
!fav.isSelected
)
notifyItemRemoved(holder.absoluteAdapterPosition)
if (currentList.isEmpty()){
onListEmptyListener(PostType.GAMES, true)
}
}
root.setOnClickListener {
onGameClicked(gameData, holder.absoluteAdapterPosition)
}
}
}
}

View File

@@ -1,91 +0,0 @@
package com.woka.home.mylist.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import com.bumptech.glide.Glide
import com.woka.R
import com.woka.databinding.FavViewHolderBinding
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.GameData
import com.woka.home.mylist.models.PostType
import com.woka.utils.isNetworkConnected
import com.woka.utils.toast
import java.util.concurrent.Executors
import kotlin.math.max
class GamesAdapter(private val context: Context,
config: AsyncDifferConfig<GameData>,
private val onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit)): ListAdapter<GameData, FavoriteViewHolder>(config) {
companion object{
private val DIFF_UTIL = object : DiffUtil.ItemCallback<GameData>(){
override fun areItemsTheSame(oldItem: GameData, newItem: GameData): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: GameData, newItem: GameData): Boolean {
return oldItem.title == newItem.title &&
oldItem.is_liked == newItem.is_liked &&
oldItem.likes_count == newItem.likes_count
}
}
private val DIFF_CONFIG = AsyncDifferConfig.Builder(DIFF_UTIL)
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
.build()
}
constructor(context: Context,
onListEmptyListener: ((postType: PostType, isEng: Boolean) -> Unit)): this(context, DIFF_CONFIG, onListEmptyListener)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavoriteViewHolder {
return FavoriteViewHolder(
FavViewHolderBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: FavoriteViewHolder, pos: Int) {
val gameData = getItem(holder.absoluteAdapterPosition)
holder.binding.apply {
gameData.thumbnail_path?.let {
image.loadImage(it)
}
title.text = gameData.title
gameData.likes_count?.let {
likeCount.text = "$it"
}
gameData.is_liked?.let {
like.isSelected = it
}
like.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
}
fav.isSelected = true
fav.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
}
}
}
}

View File

@@ -0,0 +1,46 @@
package com.woka.home.mylist.models
import com.woka.wokagames.models.listing.ContentMoreDetail
import com.woka.wokagames.models.listing.GameData
data class FavGameData(
val age_range_master_id: String?,
val bookmark_category_ids: String?,
val bookmark_count: Int?,
val category_master_id: String?,
val content_more_details: List<ContentMoreDetail?>?,
val description: String?,
val game_url: String?,
val gender_master_id: String?,
val id: Int?,
var is_liked: Boolean?,
val language_master_id: Int?,
var likes_count: Int?,
val mark_as_favourite: Boolean?,
val release_date: String?,
val screen_orientation: String?,
val thumbnail_path: String?,
val title: String?,
val views_count: Int?
){
constructor(gameData: GameData): this(
gameData.age_range_master_id,
null,
gameData.bookmark_count,
gameData.category_master_id,
gameData.content_more_details,
gameData.description,
gameData.game_url,
gameData.gender_master_id,
gameData.id,
gameData.is_liked,
gameData.language_master_id,
gameData.likes_count,
gameData.mark_as_favourite,
gameData.release_date,
gameData.screen_orientation,
gameData.thumbnail_path,
gameData.title,
null
)
}

View File

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

View File

@@ -0,0 +1,14 @@
package com.woka.karaoke
import com.woka.karaoke.models.listing.KaraokeResponse
import com.woka.networking.ApiResponse
import okhttp3.FormBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
interface KaraokeApiService {
@POST("sing_karaoke_listing")
suspend fun karaokeListing(@Body formBody: FormBody): Response<ApiResponse<KaraokeResponse>>
}

View File

@@ -0,0 +1,123 @@
package com.woka.karaoke
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.PostType
import com.woka.karaoke.models.listing.KaraokeResponse
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.networking.RetrofitHelper.handleApiCall
import com.woka.userdata.UserActionApiService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.FormBody
import kotlin.math.max
object KaraokeRepository {
// api services
private val apiService = RetrofitHelper.getRetrofit().create(KaraokeApiService::class.java)
private val userActionApiService = RetrofitHelper.getRetrofit().create(UserActionApiService::class.java)
// live data
// audio books data (loose caching)
private val _karaokeLiveData = MutableLiveData<ApiResult<KaraokeResponse>>()
val karaokeLiveData: LiveData<ApiResult<KaraokeResponse>>
get() = _karaokeLiveData
private var karaokeData: KaraokeResponse? = null
fun loadGames(){
if (karaokeData != null){
_karaokeLiveData.postValue(ApiResult.Success(karaokeData))
return
}
CoroutineScope(Dispatchers.IO).launch{
_karaokeLiveData.postValue(ApiResult.Loading())
val response = RetrofitHelper.handleApiCall {
apiService.karaokeListing(
FormBody.Builder()
.build()
)
}
when (response){
is ApiResult.Error -> _karaokeLiveData.postValue(ApiResult.Error(response.errorMessage, response.error))
is ApiResult.Loading -> _karaokeLiveData.postValue(ApiResult.Loading())
is ApiResult.Success -> {
response.data?.let {
karaokeData = it
_karaokeLiveData.postValue(ApiResult.Success(it))
}?:{
_karaokeLiveData.postValue(ApiResult.Error())
}
}
}
}
}
fun likeUnLikeGame(postId: String, likeIt: Boolean){
CoroutineScope(Dispatchers.IO).launch {
handleApiCall {
if (likeIt){
userActionApiService.likePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", PostType.KARAOKE.value)
.build()
)
}else{
userActionApiService.unLikePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", PostType.KARAOKE.value)
.build()
)
}
}
}
changeLikeLocally(postId, likeIt)
}
private fun changeLikeLocally(id: String, isLiked: Boolean){
// changing in karaoke locally
karaokeData?.karaoke_data?.let {audioBooks ->
for (audio in audioBooks){
var found = false
audio?.let {data ->
if ("${data.id}" == id){
data.is_liked = isLiked
data.likes_count?.let { count ->
data.likes_count = if (isLiked) count + 1
else max(0, count - 1)
}
found = true
}
}
if (found) break
}
}
// changing in fav list locally
MyListRepository.myFavData.result?.sing_karaoke_data?.let {
for (audioData in it){
if ("${audioData.id}" == id){
audioData.is_liked = isLiked
audioData.likes_count?.let { count ->
audioData.likes_count = if (isLiked) count + 1
else max(0, count - 1)
}
break
}
}
}
}
}

View File

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

View File

@@ -1,13 +1,15 @@
package com.woka.home.mylist.models package com.woka.karaoke.models.listing
data class GameData( data class KaraokeData(
val age_range_data: List<Any?>?,
val age_range_master_id: String?, val age_range_master_id: String?,
val bookmark_category_ids: String?,
val bookmark_count: Int?, val bookmark_count: Int?,
val category_data: List<Any?>?,
val category_master_id: String?, val category_master_id: String?,
// val content_more_details: List<ContentMore>?, val content_more_details: List<ContentMoreDetail?>?,
val description: String?, val description: String?,
val game_url: String?, val duration: String?,
val gender_data: List<Any?>?,
val gender_master_id: String?, val gender_master_id: String?,
val id: Int?, val id: Int?,
var is_liked: Boolean?, var is_liked: Boolean?,
@@ -15,8 +17,8 @@ data class GameData(
var likes_count: Int?, var likes_count: Int?,
val mark_as_favourite: Boolean?, val mark_as_favourite: Boolean?,
val release_date: String?, val release_date: String?,
val screen_orientation: String?,
val thumbnail_path: String?, val thumbnail_path: String?,
val title: String?, val title: String?,
val video_url: String?,
val views_count: Int? val views_count: Int?
) )

View File

@@ -0,0 +1,6 @@
package com.woka.karaoke.models.listing
data class KaraokeResponse(
val karaoke_data: List<KaraokeData?>?,
val total_records: Int?
)

View File

@@ -0,0 +1,169 @@
package com.woka.wokagames
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woka.audiobooks.AudioBookRepository
import com.woka.audiobooks.models.audiodata.AudioBookData
import com.woka.home.mylist.MyListRepository
import com.woka.home.mylist.models.FavAudioBookData
import com.woka.home.mylist.models.FavGameData
import com.woka.home.mylist.models.PostType
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.networking.RetrofitHelper.handleApiCall
import com.woka.userdata.UserActionApiService
import com.woka.wokagames.models.listing.GameData
import com.woka.wokagames.models.listing.GamesResponse
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.FormBody
import kotlin.math.max
object GamesRepository {
// api services
private val apiService = RetrofitHelper.getRetrofit().create(WokaGamesApiService::class.java)
private val userActionApiService = RetrofitHelper.getRetrofit().create(UserActionApiService::class.java)
// live data
// audio books data (loose caching)
private val _gamesLiveData = MutableLiveData<ApiResult<GamesResponse>>()
val gamesLiveData: LiveData<ApiResult<GamesResponse>>
get() = _gamesLiveData
private var gamesData: GamesResponse? = null
fun loadGames(){
if (gamesData != null){
_gamesLiveData.postValue(ApiResult.Success(gamesData))
return
}
CoroutineScope(Dispatchers.IO).launch{
_gamesLiveData.postValue(ApiResult.Loading())
val response = RetrofitHelper.handleApiCall {
apiService.gamesListing(
FormBody.Builder()
.build()
)
}
when (response){
is ApiResult.Error -> _gamesLiveData.postValue(ApiResult.Error(response.errorMessage, response.error))
is ApiResult.Loading -> _gamesLiveData.postValue(ApiResult.Loading())
is ApiResult.Success -> {
response.data?.let {
gamesData = it
_gamesLiveData.postValue(ApiResult.Success(it))
}?:{
_gamesLiveData.postValue(ApiResult.Error())
}
}
}
}
}
fun likeUnLikeGame(postId: String, likeIt: Boolean){
CoroutineScope(Dispatchers.IO).launch {
handleApiCall {
if (likeIt){
userActionApiService.likePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", PostType.GAMES.value)
.build()
)
}else{
userActionApiService.unLikePost(
FormBody.Builder()
.add("post_id", postId)
.add("post_type", PostType.GAMES.value)
.build()
)
}
}
}
changeLikeLocally(postId, likeIt)
}
private fun changeLikeLocally(id: String, isLiked: Boolean){
// changing in games locally
gamesData?.game_data?.let {audioBooks ->
for (audio in audioBooks){
var found = false
audio?.let {data ->
if ("${data.id}" == id){
data.is_liked = isLiked
data.likes_count?.let { count ->
data.likes_count = if (isLiked) count + 1
else max(0, count - 1)
}
found = true
}
}
if (found) break
}
}
// changing in fav list locally
MyListRepository.myFavData.result?.game_data?.let {
for (audioData in it){
if ("${audioData.id}" == id){
audioData.is_liked = isLiked
audioData.likes_count?.let { count ->
audioData.likes_count = if (isLiked) count + 1
else max(0, count - 1)
}
break
}
}
}
}
fun updateFavShow(gameData: GameData, addToBookmark: Boolean){
CoroutineScope(Dispatchers.IO).launch {
handleApiCall {
if (addToBookmark){
userActionApiService.addToFav(
FormBody.Builder()
.add("post_id", "${gameData.id}")
.add("post_type", PostType.GAMES.value)
.build()
)
}else{
userActionApiService.removeFromFav(
FormBody.Builder()
.add("id", "${gameData.id}")
.add("post_type", PostType.GAMES.value)
.build()
)
}
}
}
MyListRepository.myFavData.result?.game_data?.let {favAudioData ->
gameData.mark_as_favourite = addToBookmark
if (addToBookmark){
favAudioData.add(FavGameData(gameData))
}else{
favAudioData.removeIf{it.id == gameData.id}
}
}
gamesData?.game_data?.let {
for (game in it){
if (game?.id == gameData.id){
game?.mark_as_favourite = addToBookmark
break
}
}
}
}
}

View File

@@ -0,0 +1,14 @@
package com.woka.wokagames
import com.woka.networking.ApiResponse
import com.woka.wokagames.models.listing.GamesResponse
import okhttp3.FormBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
interface WokaGamesApiService {
@POST("game_listing")
suspend fun gamesListing(@Body formBody: FormBody): Response<ApiResponse<GamesResponse>>
}

View File

@@ -0,0 +1,121 @@
package com.woka.wokagames.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.woka.R
import com.woka.WokaApp
import com.woka.databinding.ShowViewHolderBinding
import com.woka.utils.isNetworkConnected
import com.woka.utils.show
import com.woka.utils.toast
import com.woka.wokagames.GamesRepository
import com.woka.wokagames.models.listing.GameData
import java.util.concurrent.Executors
class GamesAdapter(var context: Context,
private var onGameClicked: (GameData) -> Unit): ListAdapter<GameData, GamesAdapter.GameViewHolder>(
ASYNC_DIFF_UTIL) {
inner class GameViewHolder(var binding: ShowViewHolderBinding): ViewHolder(binding.root)
companion object{
val DIFF_UTIL = object : DiffUtil.ItemCallback<GameData>(){
override fun areItemsTheSame(oldItem: GameData, newItem: GameData): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: GameData, newItem: GameData): Boolean {
return oldItem.thumbnail_path == newItem.thumbnail_path &&
oldItem.title == newItem.title &&
oldItem.is_liked == newItem.is_liked &&
oldItem.mark_as_favourite == newItem.mark_as_favourite &&
oldItem.likes_count == newItem.likes_count
}
}
val ASYNC_DIFF_UTIL = AsyncDifferConfig.Builder(DIFF_UTIL)
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
.build()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameViewHolder {
return GameViewHolder(
ShowViewHolderBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: GameViewHolder, position: Int) {
val gameData = getItem(holder.absoluteAdapterPosition)
holder.binding.apply {
gameData.thumbnail_path?.let {
image.loadImage(it)
}
gameData.content_more_details?.let {moreDetailsList ->
title.text = if (moreDetailsList.isNotEmpty()){
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1){
moreDetailsList[1]?.title
}else{
moreDetailsList[0]?.title
}
}else{
gameData.title
}
}
like.show()
likeCount.show()
fav.show()
gameData.likes_count?.let {
likeCount.text = "$it"
}
gameData.is_liked?.let {
like.isSelected = it
}
like.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
GamesRepository.likeUnLikeGame(
"${gameData.id}",
!like.isSelected
)
like.isSelected = !like.isSelected
likeCount.text = "${gameData.likes_count}"
}
fav.isSelected = gameData.mark_as_favourite == true
fav.setOnClickListener {
if (!context.isNetworkConnected()){
context.toast(context.getString(R.string.no_internet))
return@setOnClickListener
}
GamesRepository.updateFavShow(
gameData,
!fav.isSelected
)
fav.isSelected = gameData.mark_as_favourite == true
}
root.setOnClickListener {
onGameClicked(gameData)
}
}
}
}

View File

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

View File

@@ -0,0 +1,47 @@
package com.woka.wokagames.models.listing
import com.woka.home.mylist.models.FavGameData
data class GameData(
val age_range_data: List<Any?>?,
val age_range_master_id: String?,
val bookmark_count: Int?,
val category_data: List<Any?>?,
val category_master_id: String?,
val content_more_details: List<ContentMoreDetail?>?,
val description: String?,
val game_url: String?,
val gender_data: List<Any?>?,
val gender_master_id: String?,
val id: Int?,
var is_liked: Boolean?,
val language_master_id: Int?,
var likes_count: Int?,
var mark_as_favourite: Boolean?,
val release_date: String?,
val screen_orientation: String?,
val thumbnail_path: String?,
val title: String?
){
constructor(favGame: FavGameData): this(
null,
favGame.age_range_master_id,
favGame.bookmark_count,
null,
favGame.category_master_id,
favGame.content_more_details,
favGame.description,
favGame.game_url,
null,
favGame.gender_master_id,
favGame.id,
favGame.is_liked,
favGame.language_master_id,
favGame.likes_count,
favGame.mark_as_favourite,
favGame.release_date,
favGame.screen_orientation,
favGame.thumbnail_path,
favGame.title
)
}

View File

@@ -0,0 +1,6 @@
package com.woka.wokagames.models.listing
data class GamesResponse(
val game_data: List<GameData?>?,
val total_records: Int?
)

View File

@@ -0,0 +1,107 @@
package com.woka.wokagames.playerr
import android.annotation.SuppressLint
import android.content.pm.ActivityInfo
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.WindowManager
import android.webkit.WebSettings
import android.webkit.WebViewClient
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import com.woka.R
import com.woka.databinding.ActivityGamePlayerBinding
import com.woka.utils.DecisionDialog
import com.woka.utils.WokaBaseActivity
import com.woka.utils.lightStatusBar
class GamePlayerActivity : WokaBaseActivity() {
companion object{
const val EXTRA_GAME_PLAYER_DATA = "extra_game_url"
}
private lateinit var binding: ActivityGamePlayerBinding
private lateinit var decisionDialog: DecisionDialog
private var gamePlayerData: GamePlayerData? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityGamePlayerBinding.inflate(layoutInflater)
setContentView(binding.root)
val windowInsetsController =
WindowCompat.getInsetsController(window, window.decorView)
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
decisionDialog = DecisionDialog(this).apply {
title = getString(R.string.warning)
message = getString(R.string.back_warning_text)
}
intent.getParcelableExtra<GamePlayerData?>(EXTRA_GAME_PLAYER_DATA)?.let {
gamePlayerData = it
requestedOrientation = if (it.landscape){
ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
}else{
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
initWebView(it.gameUrl)
}
}
override fun onStart() {
super.onStart()
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
override fun onStop() {
super.onStop()
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
override fun onResume() {
super.onResume()
binding.webView.onResume()
}
override fun onPause() {
super.onPause()
binding.webView.onPause()
}
override fun onDestroy() {
super.onDestroy()
binding.webView.destroy()
}
@SuppressLint("SetJavaScriptEnabled")
private fun initWebView(it: String){
val webSettings: WebSettings = binding.webView.getSettings()
webSettings.javaScriptEnabled = true
webSettings.allowFileAccess = false;
webSettings.allowContentAccess = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
webSettings.safeBrowsingEnabled = true
};
binding.webView.setWebViewClient(WebViewClient())
binding.webView.loadUrl(it)
}
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
decisionDialog.setPositiveButton(getString(R.string.ok_caps)){
super.onBackPressed()
}
decisionDialog.setNegativeButton(getString(R.string.cancel_caps)){
decisionDialog.dismiss()
}
decisionDialog.show()
}
}

View File

@@ -0,0 +1,10 @@
package com.woka.wokagames.playerr
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class GamePlayerData(
val gameUrl: String,
val landscape: Boolean = false
): Parcelable

View File

@@ -0,0 +1,317 @@
package com.woka.wokagames.views
import android.app.Dialog
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.InsetDrawable
import android.os.Bundle
import android.text.Html
import android.view.WindowManager
import androidx.activity.enableEdgeToEdge
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.SimpleItemAnimator
import com.google.android.material.appbar.CollapsingToolbarLayout
import com.woka.R
import com.woka.WokaApp
import com.woka.databinding.ActivityGamesBinding
import com.woka.databinding.DialogModuleShowerBinding
import com.woka.networking.ApiResult
import com.woka.utils.WokaBaseActivity
import com.woka.utils.hide
import com.woka.utils.show
import com.woka.wokagames.GamesRepository
import com.woka.wokagames.adapters.GamesAdapter
import com.woka.wokagames.models.listing.GameData
import com.woka.wokagames.playerr.GamePlayerActivity
import com.woka.wokagames.playerr.GamePlayerActivity.Companion.EXTRA_GAME_PLAYER_DATA
import com.woka.wokagames.playerr.GamePlayerData
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class GamesActivity : WokaBaseActivity() {
private lateinit var binding: ActivityGamesBinding
private lateinit var gameAdapter: GamesAdapter
private lateinit var dialogBinding: DialogModuleShowerBinding
private lateinit var gameDialog: Dialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityGamesBinding.inflate(layoutInflater)
enableEdgeToEdge()
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
}
window.apply {
navigationBarColor = getColor(R.color.color_primary_dark)
}
gameAdapter = GamesAdapter(this, ::onGameClicked)
dialogBinding = DialogModuleShowerBinding.inflate(layoutInflater)
gameDialog = Dialog(this)
gameDialog.setContentView(dialogBinding.root)
initViews()
initGameDialog()
clickEvents()
setObservers()
GamesRepository.loadGames()
}
private fun initViews() {
binding.apply {
adjustTrailerImage()
toolbar.title.text = getString(R.string.games)
rvGames.adapter = gameAdapter
(rvGames.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
}
}
private fun initGameDialog() {
try {
val back = ColorDrawable(Color.TRANSPARENT)
val inset = InsetDrawable(back, 50)
gameDialog.window!!.setBackgroundDrawable(inset)
} catch (e: Exception) {
// do nothing
}
try {
val layoutParams = gameDialog.window!!.attributes
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
gameDialog.window!!.setAttributes(layoutParams)
} catch (e: Exception) {
// do nothing
}
dialogBinding.close.setOnClickListener { gameDialog.dismiss() }
dialogBinding.watchCard.backgroundTintList = ColorStateList.valueOf(getColor(R.color.game_grad_one))
dialogBinding.watchCard.text = getString(R.string.play_now)
}
private fun clickEvents() {
binding.apply {
toolbar.backBtn.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
retryBtn.setOnClickListener {
GamesRepository.loadGames()
}
}
}
private fun onGameClicked(gameData: GameData) {
loadTrailerData(gameData)
showGameDialog(gameData)
}
private fun loadTrailerData(gameData: GameData) {
binding.apply {
trailerView.show()
adjustTrailerImage()
gameData.thumbnail_path?.let {
trailerImage.loadImage(it)
}
gameData.content_more_details?.let { moreDetailsList ->
trailerName.text = if (moreDetailsList.isNotEmpty()) {
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) {
moreDetailsList[1]?.title
} else {
moreDetailsList[0]?.title
}
} else {
gameData.title
}
}
trailerBtn.setOnClickListener {
gameData.game_url?.let {
startActivity(Intent(this@GamesActivity, GamePlayerActivity::class.java).apply {
putExtra(EXTRA_GAME_PLAYER_DATA, GamePlayerData(it, gameData.screen_orientation == "Landscape"))
})
}
}
}
}
private fun adjustTrailerImage() {
// making space for Trailer image
binding.apply {
topPinnedView.post {
val imgParams = trailerImage.layoutParams as CollapsingToolbarLayout.LayoutParams
imgParams.setMargins(0, 0, 0, topPinnedView.height)
trailerImage.layoutParams = imgParams
}
}
}
private fun showGameDialog(gameData: GameData) {
dialogBinding.apply {
gameData.content_more_details?.let { moreDetailsList ->
gameData.thumbnail_path?.let {
image.loadImage(it)
}
fav.isSelected = gameData.mark_as_favourite == true
like.isSelected = gameData.is_liked == true
likeCount.text = "${gameData.likes_count}"
year.text = try {
gameData.release_date?.let {
val cal = Calendar.getInstance()
cal.time =
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).parse(
gameData.release_date
)!!
"${cal.get(Calendar.YEAR)}"
} ?: throw Exception()
} catch (e: Exception) {
"${gameData.release_date}"
}
if (moreDetailsList.isNotEmpty()) {
if (WokaApp.userPrefs?.appLanguage == "hi" && moreDetailsList.size > 1) {
moreDetailsList[1]?.let { data ->
title.text = data.title
description.text = Html.fromHtml(
data.description?.replace(
"<br>",
" "
), Html.FROM_HTML_MODE_LEGACY
)
}
} else {
moreDetailsList[0]?.let { data ->
title.text = data.title
description.text = Html.fromHtml(
data.description?.replace(
"<br>",
" "
), Html.FROM_HTML_MODE_LEGACY
)
}
}
} else {
title.text = gameData.title
description.text = Html.fromHtml(
gameData.description?.replace(
"<br>",
" "
), Html.FROM_HTML_MODE_LEGACY
)
}
watchCard.setOnClickListener {
gameData.game_url?.let {
startActivity(Intent(this@GamesActivity, GamePlayerActivity::class.java).apply {
putExtra(EXTRA_GAME_PLAYER_DATA, GamePlayerData(it, gameData.screen_orientation == "Landscape"))
})
}
}
like.setOnClickListener {
GamesRepository.likeUnLikeGame(
"${gameData.id}",
!like.isSelected
)
gameData.id?.let {
onGameChanged(it)
}
like.isSelected = !like.isSelected
likeCount.text = "${gameData.likes_count}"
}
fav.setOnClickListener {
GamesRepository.updateFavShow(
gameData,
!fav.isSelected
)
gameData.id?.let {
onGameChanged(it)
}
fav.isSelected = !fav.isSelected
}
close.setOnClickListener {
gameDialog.dismiss()
}
gameDialog.show()
}
}
}
private fun onGameChanged(id: Int) {
// updating continue book list
val position = gameAdapter.currentList.indexOfFirst { it.id == id }
if (position >= 0 && position < gameAdapter.currentList.size) {
gameAdapter.notifyItemChanged(position)
}
}
private fun setObservers(){
GamesRepository.gamesLiveData.observe(this) {
when (it) {
is ApiResult.Error -> {
binding.shimmer.hide()
binding.rvGames.hide()
binding.listenTxt.hide()
binding.trailerView.hide()
binding.errorView.show()
}
is ApiResult.Loading -> {
binding.shimmer.show()
binding.rvGames.hide()
binding.listenTxt.hide()
binding.trailerView.hide()
binding.errorView.hide()
}
is ApiResult.Success -> {
it.data?.game_data?.filterNotNull()?.let { gameData ->
if (gameData.isNotEmpty()) {
binding.shimmer.hide()
binding.errorView.hide()
loadTrailerData(gameData[0])
binding.rvGames.show()
binding.listenTxt.show()
gameAdapter.submitList(gameData)
}
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#F38600"
android:endColor="#9742E4"
android:centerColor="#9742E4"
android:centerX="0.3"
android:angle="-45"
/>
</shape>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#F38600"/>
<corners android:radius="50dp" />
</shape>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:fitsSystemWindows="true"
tools:context=".wokagames.playerr.GamePlayerActivity"/>

View File

@@ -0,0 +1,255 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/gradient_woka_games"
android:orientation="vertical"
tools:context=".webseries.views.WebSeriesActivity">
<include android:id="@+id/toolbar"
layout="@layout/layout_toolbar"/>
<RelativeLayout
android:id="@+id/shimmer"
android:visibility="gone"
android:background="@color/color_primary_dark"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.facebook.shimmer.ShimmerFrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:shimmer_auto_start="true"
app:shimmer_duration="1500"
app:shimmer_highlight_alpha="0.5"
>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="@dimen/_160sdp"
android:background="@color/white_50"
/>
<View
android:layout_width="@dimen/_100sdp"
android:layout_height="@dimen/_37sdp"
android:background="@color/white_50"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="10dp"
android:layout_gravity="center_horizontal"
/>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/_140sdp"
android:background="@color/white_50"
android:layout_marginHorizontal="15dp"
/>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/_140sdp"
android:background="@color/white_50"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="15dp"
/>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/_140sdp"
android:background="@color/white_50"
android:layout_marginVertical="15dp"
android:layout_marginHorizontal="15dp"
/>
</LinearLayout>
</ScrollView>
</com.facebook.shimmer.ShimmerFrameLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/error_view"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_primary_dark"
android:orientation="vertical"
android:gravity="center"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/something_went_wrong"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/white"
android:textSize="@dimen/_14ssp"
/>
<Button
android:id="@+id/retry_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/retry"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/white"
android:textSize="@dimen/_14ssp"
android:paddingHorizontal="25dp"
android:layout_marginTop="15dp"
android:background="@drawable/grad_btn_bg_4"
/>
</LinearLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_primary_dark"
>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/trailer_view"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|snap|exitUntilCollapsed">
<com.woka.utils.AdiImageView
android:id="@+id/trailer_image"
android:layout_width="match_parent"
android:layout_height="@dimen/_160sdp"
android:contentDescription="@string/image"
android:src="@drawable/img_masila_full"
android:scaleType="fitXY"
app:layout_collapseMode="parallax"
android:layout_gravity="top"
/>
<androidx.appcompat.widget.Toolbar
android:id="@+id/top_pinned_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_primary_dark"
app:layout_collapseMode="pin"
app:contentInsetStart="0dp"
app:contentInsetLeft="0dp"
app:contentInsetStartWithNavigation="0dp"
android:layout_gravity="bottom">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="15dp"
android:gravity="center"
>
<TextView
android:id="@+id/trailer_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="@string/masila"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/white"
android:textSize="@dimen/_16ssp"
/>
<Button
android:id="@+id/trailer_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/play"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/white"
android:textSize="@dimen/_12ssp"
android:paddingHorizontal="25dp"
android:layout_marginTop="15dp"
android:background="@drawable/play_btn_bg"
/>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_primary_dark"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/listen_txt"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/have_a_fun_time"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/white"
android:textSize="@dimen/_14ssp"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_games"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/show_view_holder"
/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View File

@@ -60,18 +60,63 @@
/> />
<TextView
android:id="@+id/year"
android:layout_width="wrap_content" <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:text="2022"
android:fontFamily="@font/exo_2"
android:textColor="@color/color_primary"
android:layout_marginHorizontal="15dp" android:layout_marginHorizontal="15dp"
android:layout_marginTop="5dp" android:layout_marginTop="2dp">
/>
<TextView
android:id="@+id/year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="2022"
android:fontFamily="@font/exo_2"
android:textColor="@color/color_primary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginTop="3dp"
/>
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:contentDescription="@string/image"
android:src="@drawable/ic_like_filled"
app:layout_constraintTop_toTopOf="@id/like_count"
app:layout_constraintBottom_toBottomOf="@id/like_count"
app:layout_constraintEnd_toStartOf="@id/like_count"
android:layout_marginBottom="3dp"
android:layout_marginEnd="3dp"
/>
<TextView
android:id="@+id/like_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="10"
android:fontFamily="@font/exo_2_semibold"
android:textColor="@color/color_primary"
android:includeFontPadding="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<ScrollView <ScrollView
android:id="@+id/scrollView" android:id="@+id/scrollView"
@@ -106,7 +151,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/round_bg_25" android:background="@drawable/round_bg_25"
android:backgroundTint="#007AC0" android:backgroundTint="@color/audio_grad_one"
android:drawableStart="@drawable/ic_play_filled" android:drawableStart="@drawable/ic_play_filled"
android:drawablePadding="15dp" android:drawablePadding="15dp"

View File

@@ -0,0 +1,6 @@
<resources>
<declare-styleable name="FullscreenAttrs">
<attr name="fullscreenBackgroundColor" format="color" />
<attr name="fullscreenTextColor" format="color" />
</declare-styleable>
</resources>

View File

@@ -20,4 +20,11 @@
<color name="more_bg">#cbe16f</color> <color name="more_bg">#cbe16f</color>
<color name="orders_bg">#D3EFF8</color> <color name="orders_bg">#D3EFF8</color>
<color name="game_grad_one">#CC4B1D</color>
<color name="audio_grad_one">#007AC0</color>
<color name="light_blue_600">#FF039BE5</color>
<color name="light_blue_900">#FF01579B</color>
<color name="light_blue_A200">#FF40C4FF</color>
<color name="light_blue_A400">#FF00B0FF</color>
<color name="black_overlay">#66000000</color>
</resources> </resources>

View File

@@ -189,4 +189,13 @@
<string name="listen_and_enjoy">LISTEN and ENJOY</string> <string name="listen_and_enjoy">LISTEN and ENJOY</string>
<string name="continue_audio_book">CONTINUE AUDIO BOOK</string> <string name="continue_audio_book">CONTINUE AUDIO BOOK</string>
<string name="listen_now">LISTEN NOW</string> <string name="listen_now">LISTEN NOW</string>
<string name="have_a_fun_time">HAVE A FUN TIME</string>
<string name="play_now">PLAY NOW</string>
<string name="title_activity_game_player">GamePlayerActivity</string>
<string name="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="warning">Warning</string>
<string name="back_warning_text">Clicking \"OK\" will exit you from the game.\nAre you sure you want to proceed?</string>
<string name="cancel_caps">CANCEL</string>
<string name="ok_caps">OK</string>
</resources> </resources>

View File

@@ -0,0 +1,11 @@
<resources>
<style name="Widget.Theme.Woka.ActionBar.Fullscreen" parent="Widget.AppCompat.ActionBar">
<item name="android:background">@color/black_overlay</item>
</style>
<style name="Widget.Theme.Woka.ButtonBar.Fullscreen" parent="">
<item name="android:background">@color/black_overlay</item>
<item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item>
</style>
</resources>

View File

@@ -14,7 +14,7 @@
<item name="postSplashScreenTheme">@style/Theme.Woka</item> <item name="postSplashScreenTheme">@style/Theme.Woka</item>
</style> </style>
<style name="MyDatePicker" > <style name="MyDatePicker">
<!-- Text color --> <!-- Text color -->
<item name="android:textColorPrimary">@color/color_primary</item> <item name="android:textColorPrimary">@color/color_primary</item>
<!-- Divider color --> <!-- Divider color -->
@@ -30,12 +30,14 @@
<item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentStatus">true</item>
</style> </style>
<!-- full screen view--> <!-- full screen view-->
<style name="FullScreenTheme" parent="Theme.Material3.Light.NoActionBar"> <style name="FullScreenTheme" parent="Theme.Material3.Light.NoActionBar">
<item name="android:windowFullscreen">true</item> <item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item> <item name="android:windowContentOverlay">@null</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item> <item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges
</item>
<item name="android:windowDisablePreview">true</item> <item name="android:windowDisablePreview">true</item>
<item name="android:windowBackground">@color/black</item>
</style> </style>
<style name="Theme.Woka" parent="Base.Theme.Woka" /> <style name="Theme.Woka" parent="Base.Theme.Woka" />