Addchild key when parent adding child

Logging-out user when success is 4 for session expired

WebView for Terms and conditions and privacy policy

DisclaimerActivity and showing static content

Notification count view and showing count from user data

MoreActivity - Song api integration and showing songs
This commit is contained in:
2024-06-07 20:35:58 +05:30
parent 8cf0ee1c28
commit e4c050eec7
30 changed files with 742 additions and 82 deletions

View File

@@ -39,6 +39,9 @@ import com.woka.home.sidebar.aboutwoka.AboutActivity
import com.woka.home.sidebar.faqs.FaqActivity
import com.woka.home.sidebar.profile.UserProfileActivity
import com.woka.home.sidebar.support.SupportActivity
import com.woka.modules.disclaimer.DisclaimerActivity
import com.woka.modules.webview.WebViewActivity
import com.woka.modules.webview.WebViewActivity.Companion.WEB_VIEW_URL
import com.woka.userdata.userDataModels.UserDataResponse
import com.woka.networking.ApiResult
import com.woka.onboard.OnboardActivity
@@ -48,8 +51,10 @@ import com.woka.onboard.OnboardActivity.Companion.ONBOARD_ACTIVITY_INTENT
import com.woka.utils.DecisionDialog
import com.woka.utils.LOCALE_ENGLISH
import com.woka.utils.LOCALE_HINDI
import com.woka.utils.PRIVACY_N_POLICY_URL
import com.woka.utils.ProgressView
import com.woka.utils.TAG
import com.woka.utils.TERMS_N_CONDITIONS_URL
import com.woka.utils.UserType
import com.woka.utils.WokaBaseActivity
import com.woka.utils.changeLocale
@@ -57,6 +62,7 @@ import com.woka.utils.hide
import com.woka.utils.lightStatusBar
import com.woka.utils.show
import com.woka.utils.toast
import kotlin.math.min
class HomeActivity : WokaBaseActivity(),
Observer<ApiResult<UserDataResponse>?>,
@@ -331,6 +337,28 @@ class HomeActivity : WokaBaseActivity(),
}
}
sbTermsNConditionsCard.setOnClickListener {
startActivity(
Intent(this@HomeActivity, WebViewActivity::class.java).apply {
putExtra(WEB_VIEW_URL, TERMS_N_CONDITIONS_URL)
}
)
}
sbPrivacyNPolicyCard.setOnClickListener {
startActivity(
Intent(this@HomeActivity, WebViewActivity::class.java).apply {
putExtra(WEB_VIEW_URL, PRIVACY_N_POLICY_URL)
}
)
}
sbDisclaimerCard.setOnClickListener {
startActivity(
Intent(this@HomeActivity, DisclaimerActivity::class.java)
)
}
}
}
@@ -504,6 +532,15 @@ class HomeActivity : WokaBaseActivity(),
sbBtn.text = getString(R.string.logout)
}
}
value.data?.userNotificationsCount?.let {
if (it == 0){
binding.notiCountView.hide()
}else{
binding.notiCountView.show()
binding.notiCount.text = "${min(it, 99)}"
}
}?:binding.notiCountView.hide()
}
null -> {}

View File

@@ -7,16 +7,19 @@ import android.view.WindowManager
import androidx.activity.enableEdgeToEdge
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.ViewModelProvider
import com.google.android.exoplayer2.ExoPlayer
import com.woka.R
import com.woka.databinding.ActivityMoreHomeBinding
import com.woka.modules.blogs.BlogsAdapter
import com.woka.modules.blogs.BlogsRepository
import com.woka.modules.wokasongs.WokaSongsAdapter
import com.woka.modules.wokasongs.WokaSongsRepository
import com.woka.networking.ApiResult
import com.woka.utils.WokaBaseActivity
import com.woka.utils.hide
import com.woka.utils.lightStatusBar
import com.woka.utils.show
import com.woka.utils.toast
class MoreHomeActivity : WokaBaseActivity() {
@@ -24,6 +27,12 @@ class MoreHomeActivity : WokaBaseActivity() {
private lateinit var blogsAdapter: BlogsAdapter
private lateinit var viewModel: MoreViewModel
private lateinit var songsAdapter: WokaSongsAdapter
private var player: ExoPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
with(window){
@@ -45,7 +54,10 @@ class MoreHomeActivity : WokaBaseActivity() {
lightStatusBar()
}
viewModel = ViewModelProvider(this)[MoreViewModel::class.java]
blogsAdapter = BlogsAdapter()
songsAdapter = WokaSongsAdapter()
initViews()
@@ -65,6 +77,7 @@ class MoreHomeActivity : WokaBaseActivity() {
private fun initViews(){
binding.apply {
rvBlogs.adapter = blogsAdapter
rvWokaSongs.adapter = songsAdapter
}
}
@@ -72,7 +85,6 @@ class MoreHomeActivity : WokaBaseActivity() {
BlogsRepository.blogsLiveData.observe(this){
when(it){
is ApiResult.Error -> {
toast(it.errorMessage)
binding.blogsTxt.hide()
binding.rvBlogs.hide()
}
@@ -91,5 +103,27 @@ class MoreHomeActivity : WokaBaseActivity() {
null -> {}
}
}
WokaSongsRepository.wokaSongsLiveData.observe(this){
when(it){
is ApiResult.Error -> {
binding.wokaSongsTxt.hide()
binding.rvWokaSongs.hide()
}
is ApiResult.Loading -> {
binding.wokaSongsTxt.hide()
binding.rvWokaSongs.hide()
}
is ApiResult.Success -> {
it.data?.paint_data?.let {songList ->
binding.wokaSongsTxt.show()
binding.rvWokaSongs.show()
songsAdapter.submitList(songList)
}
}
}
}
}
}

View File

@@ -0,0 +1,7 @@
package com.woka.home
import androidx.lifecycle.ViewModel
class MoreViewModel: ViewModel() {
}

View File

@@ -16,6 +16,7 @@ import com.woka.userdata.userDataModels.UserData
import com.woka.networking.ApiResult
import com.woka.utils.Gender
import com.woka.utils.ProgressView
import com.woka.utils.UserType
import com.woka.utils.WokaBaseActivity
import com.woka.utils.hide
import com.woka.utils.toast
@@ -44,11 +45,23 @@ class UserProfileActivity : WokaBaseActivity() {
viewModel = ViewModelProvider(this)[ProfileViewModel::class.java]
progressView = ProgressView(this, getString(R.string.please_wait))
initViews()
clickEvents()
setObservers()
}
private fun initViews() {
binding.apply {
genderMTxt.text = if (userPrefs?.userType == UserType.GUARDIAN) getString(R.string.male)
else getString(R.string.boy)
genderFTxt.text = if (userPrefs?.userType == UserType.GUARDIAN) getString(R.string.female)
else getString(R.string.girl)
}
}
private fun clickEvents() {
binding.apply {
genderM.setOnClickListener { selectGender(Gender.MALE) }

View File

@@ -2,6 +2,7 @@ package com.woka.modules
import com.woka.modules.blogs.models.BlogsResponse
import com.woka.modules.faqs.models.FaqResponse
import com.woka.modules.wokasongs.models.WokaSongsResponse
import com.woka.networking.ApiResponse
import okhttp3.FormBody
import retrofit2.Response
@@ -22,4 +23,7 @@ interface ModuleApiService {
@POST("user_queries_store")
suspend fun supportForUser(@Body body: FormBody): Response<ApiResponse<Any>>
@POST("song_listing")
suspend fun getWokaSongs(): Response<ApiResponse<WokaSongsResponse>>
}

View File

@@ -0,0 +1,30 @@
package com.woka.modules.disclaimer
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.woka.R
import com.woka.databinding.ActivityDisclaimerBinding
import com.woka.utils.WokaBaseActivity
class DisclaimerActivity : WokaBaseActivity() {
private lateinit var binding: ActivityDisclaimerBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityDisclaimerBinding.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
}
binding.backBtn.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
}
}

View File

@@ -0,0 +1,77 @@
package com.woka.modules.webview
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.ProgressBar
import androidx.activity.enableEdgeToEdge
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.woka.R
import com.woka.databinding.ActivityWebViewBinding
import com.woka.utils.WEBSITE_BASE_URL
import com.woka.utils.WokaBaseActivity
import com.woka.utils.hide
import com.woka.utils.show
class WebViewActivity : WokaBaseActivity() {
companion object{
const val WEB_VIEW_URL = "web_view_url"
}
private lateinit var binding: ActivityWebViewBinding
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityWebViewBinding.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
}
intent.getStringExtra(WEB_VIEW_URL)?.let {
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(SecureWebViewClient(binding.progressBar))
binding.webView.loadUrl(it)
}
}
private class SecureWebViewClient(val progressBar: ProgressBar) : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
progressBar.show()
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
progressBar.hide()
}
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
val url = request.url.toString()
return !url.startsWith(WEBSITE_BASE_URL)
}
}
}

View File

@@ -0,0 +1,46 @@
package com.woka.modules.wokasongs
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.databinding.WokaSongViewHolderBinding
import com.woka.modules.wokasongs.models.SongData
import java.util.concurrent.Executors
class WokaSongsAdapter(config: AsyncDifferConfig<SongData>): ListAdapter<SongData, WokaSongsAdapter.SongViewHolder>(config) {
inner class SongViewHolder(val binding: WokaSongViewHolderBinding): ViewHolder(binding.root)
companion object{
private val DIFF_UTILS = object : DiffUtil.ItemCallback<SongData>(){
override fun areItemsTheSame(oldItem: SongData, newItem: SongData): Boolean =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: SongData, newItem: SongData): Boolean =
oldItem == newItem
}
private val ASYNC_DIFF_CONFIG = AsyncDifferConfig.Builder(DIFF_UTILS)
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
.build()
}
constructor(): this(ASYNC_DIFF_CONFIG)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
return SongViewHolder(
WokaSongViewHolderBinding.inflate(LayoutInflater.from(parent.context),
parent, false)
)
}
override fun onBindViewHolder(holder: SongViewHolder, position: Int) {
val songData = getItem(position)
holder.binding.apply {
title.text = songData.title
}
}
}

View File

@@ -0,0 +1,37 @@
package com.woka.modules.wokasongs
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woka.modules.ModuleApiService
import com.woka.modules.wokasongs.models.WokaSongsResponse
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
object WokaSongsRepository {
private val apiService = RetrofitHelper.getRetrofit().create(ModuleApiService::class.java)
private val _wokaSongsLiveData = MutableLiveData<ApiResult<WokaSongsResponse>>()
val wokaSongsLiveData: LiveData<ApiResult<WokaSongsResponse>>
get() = _wokaSongsLiveData
init {
loadWokaSongs()
}
private suspend fun getWokaSongs(): ApiResult<WokaSongsResponse>{
return RetrofitHelper.handleApiCall {
apiService.getWokaSongs()
}
}
private fun loadWokaSongs(){
CoroutineScope(Dispatchers.IO).launch {
_wokaSongsLiveData.postValue(ApiResult.Loading())
_wokaSongsLiveData.postValue(getWokaSongs())
}
}
}

View File

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

View File

@@ -0,0 +1,23 @@
package com.woka.modules.wokasongs.models
data class SongData(
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 gender_data: List<Any?>?,
val gender_master_id: String?,
val id: Int?,
val is_liked: Boolean?,
val language_master_id: Int?,
val likes_count: Int?,
val mark_as_favourite: Boolean?,
val release_date: String?,
val song_duration: String?,
val tags_keyword: String?,
val thumbnail_image: String?,
val title: String?
)

View File

@@ -0,0 +1,6 @@
package com.woka.modules.wokasongs.models
data class WokaSongsResponse(
val paint_data: List<SongData?>?,
val total_records: Int?
)

View File

@@ -83,10 +83,17 @@ object RetrofitHelper {
fun <T>handleApiResponse(response: Response<ApiResponse<T>>): ApiResult<T> {
if (response.isSuccessful) {
val body = response.body() ?: return ApiResult.Error(errorMessage = "Empty Response")
return if (body.success == 1) {
ApiResult.Success(body.data, body.message)
} else {
ApiResult.Error(errorMessage = body.message, error = NoSuccessError())
return when (body.success) {
1 -> {
ApiResult.Success(body.data, body.message)
}
4 -> {
userPrefs?.logout(true)
ApiResult.Error(errorMessage = body.message, error = SessionExpiredError())
}
else -> {
ApiResult.Error(errorMessage = body.message, error = NoSuccessError())
}
}
} else {
return ApiResult.Error(errorMessage = response.message())

View File

@@ -0,0 +1,3 @@
package com.woka.networking
class SessionExpiredError: Throwable()

View File

@@ -78,7 +78,7 @@ class SelectAvatarFragment : Fragment() {
val registerRequestData = with(viewModel){
RegisterRequestData(
add_child = "0",
add_child = if (viewModel.addChildIntent) "1" else "0",
avtar = adapter?.avatarList?.get(selectedAvatarPos!!)?.avatar_name,
birthdate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(selectedDOB.time),
email = email,

View File

@@ -132,6 +132,7 @@ class SignUpFragment : Fragment() {
passwordTitle.text = getString(R.string.password)
viewModel.email = email
viewModel.addChildIntent = true
}
}
}

View File

@@ -95,9 +95,13 @@ class SplashFragment : Fragment(), Observer<ApiResult<UserDataResponse>?> {
if (userPrefs?.userType == UserType.NONE){
// none of the user is logged in
// going through normal onboard process
val extras = FragmentNavigatorExtras(binding.logo to "logo")
findNavController().navigate(R.id.action_splashFragment_to_languageFragment,
null, null, extras)
try {
val extras = FragmentNavigatorExtras(binding.logo to "logo")
findNavController().navigate(R.id.action_splashFragment_to_languageFragment,
null, null, extras)
} catch (e: Exception) {
// do nothing
}
}else{
// going to home activity as any of the user is logged in
activity?.let {

View File

@@ -36,6 +36,8 @@ class OnboardViewModel: ViewModel(){
var name: String? = null
var password: String? = null
var addChildIntent: Boolean = false
var childList: List<Child>? = null
val interestTopics = mutableSetOf<Int>()

View File

@@ -3,12 +3,14 @@ package com.woka.userPreference
import android.annotation.SuppressLint
import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.content.Intent
import android.content.SharedPreferences
import android.provider.Settings.Secure
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woka.home.Theme
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
@@ -17,7 +19,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class UserPreference(context: Context) {
class UserPreference(val context: Context) {
companion object {
private const val USER_PREFERENCE = "woka_user_preferences"
@@ -95,9 +97,15 @@ class UserPreference(context: Context) {
}
}
fun logout(){
fun logout(openLoginScreen: Boolean = false){
accessToken = null
userType = if (guestUserName == null) UserType.NONE else UserType.GUEST
_userLiveData.postValue(null)
if (openLoginScreen){
context.startActivity(Intent(context, OnboardActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
})
}
}
}

View File

@@ -11,4 +11,9 @@ const val UNKNOWN_ERROR_MESSAGE = "An unknown error occurred"
// language code
const val LOCALE_HINDI = "hi"
const val LOCALE_ENGLISH = "en"
const val LOCALE_ENGLISH = "en"
// website urls
const val WEBSITE_BASE_URL = "https://www.wokaland.com/"
const val TERMS_N_CONDITIONS_URL = "https://www.wokaland.com/terms/"
const val PRIVACY_N_POLICY_URL = "https://www.wokaland.com/privacy-policy/"