Exit dialog for home screen

Update button only enabled when their is change in the full name input box in UserProfileActivity.kt

MoreActivity songs list and api integration of songs and playing all songs
one by one.
This commit is contained in:
2024-06-10 21:02:16 +05:30
parent e4c050eec7
commit 599f817e73
20 changed files with 324 additions and 49 deletions

View File

@@ -10,12 +10,12 @@
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$PROJECT_DIR$/../.android/avd/Pixel_7_Pro_API_33.avd" />
<value value="$PROJECT_DIR$/../.android/avd/Pixel_6_API_27.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-06-05T11:43:41.893398Z" />
<timeTargetWasSelectedWithDropDown value="2024-06-10T10:52:42.278299Z" />
<targetsSelectedWithDialog>
<Target>
<type value="QUICK_BOOT_TARGET" />

View File

@@ -15,6 +15,10 @@
android:supportsRtl="true"
android:theme="@style/Theme.Woka"
tools:targetApi="31">
<activity
android:name=".shop.MyOrdersActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".modules.disclaimer.DisclaimerActivity"
android:exported="false"

View File

@@ -48,6 +48,7 @@ import com.woka.onboard.OnboardActivity
import com.woka.onboard.OnboardActivity.Companion.ADD_CHILD_INTENT
import com.woka.onboard.OnboardActivity.Companion.LOG_IN_INTENT
import com.woka.onboard.OnboardActivity.Companion.ONBOARD_ACTIVITY_INTENT
import com.woka.shop.MyOrdersActivity
import com.woka.utils.DecisionDialog
import com.woka.utils.LOCALE_ENGLISH
import com.woka.utils.LOCALE_HINDI
@@ -128,7 +129,16 @@ class HomeActivity : WokaBaseActivity(),
}else if (binding.bottomNav.getSelectedTab() != HOME){
binding.bottomNav.selectTab(HOME)
}else {
super.onBackPressed()
decisionDialog.title = getString(R.string.app_name_caps)
decisionDialog.message = getString(R.string.do_you_want_to_exit_from_the_woka_app)
decisionDialog.setPositiveButton(getString(R.string.yes)){
super.onBackPressed()
}
decisionDialog.setNegativeButton(getString(R.string.no))
decisionDialog.show()
}
}
@@ -359,6 +369,12 @@ class HomeActivity : WokaBaseActivity(),
)
}
sbMyOrdersCard.setOnClickListener {
startActivity(
Intent(this@HomeActivity, MyOrdersActivity::class.java)
)
}
}
}

View File

@@ -8,7 +8,8 @@ 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 androidx.recyclerview.widget.SimpleItemAnimator
import com.google.android.exoplayer2.MediaItem
import com.woka.R
import com.woka.databinding.ActivityMoreHomeBinding
import com.woka.modules.blogs.BlogsAdapter
@@ -21,6 +22,7 @@ import com.woka.utils.hide
import com.woka.utils.lightStatusBar
import com.woka.utils.show
class MoreHomeActivity : WokaBaseActivity() {
private lateinit var binding: ActivityMoreHomeBinding
@@ -31,11 +33,9 @@ class MoreHomeActivity : WokaBaseActivity() {
private lateinit var songsAdapter: WokaSongsAdapter
private var player: ExoPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
with(window){
with(window) {
enterTransition = Fade()
}
enableEdgeToEdge()
@@ -47,7 +47,7 @@ class MoreHomeActivity : WokaBaseActivity() {
insets
}
with(window){
with(window) {
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
statusBarColor = Color.TRANSPARENT
navigationBarColor = getColor(R.color.more_bg)
@@ -57,7 +57,7 @@ class MoreHomeActivity : WokaBaseActivity() {
viewModel = ViewModelProvider(this)[MoreViewModel::class.java]
blogsAdapter = BlogsAdapter()
songsAdapter = WokaSongsAdapter()
songsAdapter = WokaSongsAdapter(this)
initViews()
@@ -66,6 +66,11 @@ class MoreHomeActivity : WokaBaseActivity() {
setObservers()
}
override fun onDestroy() {
super.onDestroy()
songsAdapter.releasePlayer()
}
private fun clickEvents() {
binding.apply {
more.setOnClickListener {
@@ -74,53 +79,68 @@ class MoreHomeActivity : WokaBaseActivity() {
}
}
private fun initViews(){
private fun initViews() {
binding.apply {
rvBlogs.adapter = blogsAdapter
rvWokaSongs.adapter = songsAdapter
(rvWokaSongs.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
}
}
private fun setObservers() {
BlogsRepository.blogsLiveData.observe(this){
when(it){
BlogsRepository.blogsLiveData.observe(this) {
when (it) {
is ApiResult.Error -> {
binding.blogsTxt.hide()
binding.rvBlogs.hide()
}
is ApiResult.Loading -> {
binding.blogsTxt.hide()
binding.rvBlogs.hide()
}
is ApiResult.Success -> {
it.data?.blogs?.let {blogList ->
it.data?.blogs?.let { blogList ->
binding.blogsTxt.show()
binding.rvBlogs.show()
blogsAdapter.submitList(blogList)
}
}
null -> {}
}
}
WokaSongsRepository.wokaSongsLiveData.observe(this){
when(it){
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 ->
it.data?.paint_data?.let { songList ->
binding.wokaSongsTxt.show()
binding.rvWokaSongs.show()
songsAdapter.submitList(songList)
val mediaItems = mutableListOf<MediaItem>()
for (song in songList) {
song?.content_more_details?.get(0)?.url?.let { url ->
mediaItems.add(MediaItem.fromUri(url))
}
}
songsAdapter.submitSongList(songList, mediaItems)
}
}
}

View File

@@ -10,6 +10,8 @@ import kotlinx.coroutines.launch
class ProfileViewModel: ViewModel() {
var currentFullName: String? = null
private val _updateProfileLiveData = MutableLiveData<ApiResult<Any>>()
val updateProfileLiveData: LiveData<ApiResult<Any>>
get() = _updateProfileLiveData

View File

@@ -5,8 +5,10 @@ import android.os.Bundle
import android.transition.Slide
import android.view.Gravity.END
import androidx.activity.enableEdgeToEdge
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.ViewModelProvider
import com.bumptech.glide.Glide
import com.woka.R
@@ -88,6 +90,10 @@ class UserProfileActivity : WokaBaseActivity() {
}
private fun setObservers() {
binding.fullName.addTextChangedListener {
enableUpdateBtn(viewModel.currentFullName != it.toString())
}
userPrefs?.userLiveData?.observe(this){
when(it){
is ApiResult.Error -> {
@@ -97,6 +103,7 @@ class UserProfileActivity : WokaBaseActivity() {
is ApiResult.Loading -> {}
is ApiResult.Success -> {
it.data?.result?.let { userData ->
viewModel.currentFullName = userData.fullname
updateUserData(userData)
}
}
@@ -162,6 +169,8 @@ class UserProfileActivity : WokaBaseActivity() {
birthdate.text = userData.birthdate
enableUpdateBtn(viewModel.currentFullName != fullName.text.toString())
}
}
@@ -196,4 +205,9 @@ class UserProfileActivity : WokaBaseActivity() {
selectedGender = gender
}
private fun enableUpdateBtn(enable: Boolean){
binding.update.isEnabled = enable
binding.update.alpha = if (enable) 1f else 0.5f
}
}

View File

@@ -1,34 +1,50 @@
package com.woka.modules.wokasongs
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
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.PlaybackException
import com.google.android.exoplayer2.Player
import com.woka.R
import com.woka.databinding.WokaSongViewHolderBinding
import com.woka.modules.wokasongs.models.SongData
import java.util.concurrent.Executors
import com.woka.utils.hide
import com.woka.utils.show
class WokaSongsAdapter(config: AsyncDifferConfig<SongData>): ListAdapter<SongData, WokaSongsAdapter.SongViewHolder>(config) {
class WokaSongsAdapter(context: Context): RecyclerView.Adapter<WokaSongsAdapter.SongViewHolder>() {
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
private var player: ExoPlayer
private var currentPlayingPos = -1
override fun areContentsTheSame(oldItem: SongData, newItem: SongData): Boolean =
oldItem == newItem
}
private var songList = mutableListOf<SongData>()
private val ASYNC_DIFF_CONFIG = AsyncDifferConfig.Builder(DIFF_UTILS)
.setBackgroundThreadExecutor(Executors.newSingleThreadExecutor())
.build()
init {
player = ExoPlayer.Builder(context).build()
player.addListener(object : Player.Listener{
override fun onEvents(player: Player, events: Player.Events) {
super.onEvents(player, events)
if (currentPlayingPos >= 0)
notifyItemChanged(currentPlayingPos)
}
override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error)
if (currentPlayingPos >= 0)
notifyItemChanged(currentPlayingPos)
}
})
}
constructor(): this(ASYNC_DIFF_CONFIG)
fun releasePlayer(){
player.stop()
player.release()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
return SongViewHolder(
@@ -37,10 +53,76 @@ class WokaSongsAdapter(config: AsyncDifferConfig<SongData>): ListAdapter<SongDat
)
}
override fun getItemCount(): Int = songList.size
override fun onBindViewHolder(holder: SongViewHolder, position: Int) {
val songData = getItem(position)
if (position >= songList.size) return
val songData = songList[position]
holder.binding.apply {
title.text = songData.title
totalTime.text = try {
if (songData.song_duration?.split(":")?.get(0)?.toInt() == 0)
songData.song_duration.substring(3)
else
songData.song_duration
}catch (e: Exception){
songData.song_duration
}
root.setOnClickListener {
if (currentPlayingPos == holder.absoluteAdapterPosition){
if (player.isLoading){
return@setOnClickListener
}
if (player.isPlaying){
player.pause()
}else{
player.play()
}
}else{
player.pause()
if (currentPlayingPos >= 0) notifyItemChanged(currentPlayingPos)
currentPlayingPos = holder.absoluteAdapterPosition
player.seekTo(holder.absoluteAdapterPosition, 0)
player.play()
}
}
if (currentPlayingPos == holder.absoluteAdapterPosition){
if (player.isLoading){
progressBar.show()
playBtn.hide()
}else if (player.isPlaying){
progressBar.hide()
playBtn.show()
playBtn.setImageResource(R.drawable.ic_pause)
}else{
progressBar.hide()
playBtn.show()
playBtn.setImageResource(R.drawable.ic_play)
}
}else{
progressBar.hide()
playBtn.show()
playBtn.setImageResource(R.drawable.ic_play)
}
}
}
fun submitSongList(list: List<SongData?>, mediaItems: MutableList<MediaItem>) {
songList.clear()
for (song in list){
song?.let {
songList.add(it)
}
}
player.addMediaItems(mediaItems)
player.prepare()
notifyDataSetChanged()
}
}

View File

@@ -0,0 +1,41 @@
package com.woka.shop
import android.graphics.Color
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.ActivityMyOrdersBinding
import com.woka.utils.WokaBaseActivity
import com.woka.utils.lightStatusBar
class MyOrdersActivity : WokaBaseActivity() {
private lateinit var binding: ActivityMyOrdersBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityMyOrdersBinding.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
}
window.navigationBarColor = getColor(R.color.my_orders_img_color)
window.lightStatusBar(true)
clickEvents()
}
private fun clickEvents() {
binding.apply {
backBtn.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -0,0 +1,66 @@
<?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"
android:background="#D3EFF8"
tools:context=".shop.MyOrdersActivity">
<ImageView
android:id="@+id/back_btn"
android:layout_width="@dimen/_27sdp"
android:layout_height="@dimen/_25sdp"
android:contentDescription="@string/back_btn"
android:src="@drawable/ic_arrow_back_full"
android:scaleType="fitXY"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:translationZ="1dp"
android:layout_marginStart="15dp"
android:layout_marginTop="20dp"
app:tint="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:translationZ="1dp"
android:text="@string/my_orders"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/black"
android:textSize="@dimen/_13ssp"
android:layout_marginStart="10dp"
app:layout_constraintStart_toEndOf="@id/back_btn"
app:layout_constraintTop_toTopOf="@id/back_btn"
app:layout_constraintBottom_toBottomOf="@id/back_btn"
/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/g1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.7"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:contentDescription="@string/image"
android:src="@drawable/img_my_orders_ng"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/g1"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -340,6 +340,8 @@
android:textSize="@dimen/_14ssp"
android:background="@drawable/gradient_btn_bg"
android:alpha="0.5"
android:enabled="false"
android:layout_marginHorizontal="15dp"
android:layout_marginBottom="25dp"

View File

@@ -27,34 +27,56 @@
android:layout_marginVertical="12dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/play_btn"
android:layout_width="25dp"
android:layout_height="25dp"
android:contentDescription="@string/image"
android:src="@drawable/ic_play"
android:scaleType="fitXY"
<RelativeLayout
android:id="@+id/view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
/>
>
<ImageView
android:id="@+id/play_btn"
android:layout_width="25dp"
android:layout_height="25dp"
android:contentDescription="@string/image"
android:src="@drawable/ic_play"
android:scaleType="fitXY"
android:visibility="visible"
/>
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="25dp"
android:layout_height="25dp"
android:indeterminate="true"
android:indeterminateTint="@color/white"
android:visibility="gone"
/>
</RelativeLayout>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/play_btn"
android:layout_centerVertical="true"
tools:text="AA ZARA"
android:textColor="@color/white"
android:fontFamily="@font/exo_2_medium"
android:layout_marginStart="10dp"
/>
android:layout_toStartOf="@+id/ll"
android:layout_toEndOf="@id/view"
android:fontFamily="@font/exo_2_medium"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/white"
tools:text="AA ZARA" />
<LinearLayout
android:id="@+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"

View File

@@ -127,4 +127,6 @@
<string name="add_child_account">बच्चे का खाता जोड़ें</string>
<string name="child_name">बच्चे का नाम</string>
<string name="enter_your_child_s_name">अपने बच्चे का नाम दर्ज करें</string>
<string name="woka_songs">वोका गाने</string>
<string name="do_you_want_to_exit_from_the_woka_app">क्या आप WOKA ऐप से बाहर निकलना चाहते हैं?</string>
</resources>

View File

@@ -8,6 +8,8 @@
<color name="color_primary_dark">#050038</color>
<color name="woka_sky_blue">#6ed5fe</color>
<color name="my_orders_img_color">#8081D6F7</color>
<color name="age_box_color">#9909005D</color>
<color name="white_60">#99FFFFFF</color>

View File

@@ -161,4 +161,6 @@
<string name="disclaimer_txt" translatable="false">THE USER AGREES AND UNDERSTANDS THAT THE PLATFORM IS PROVIDED BY US ON AN “AS IS” AND “AS AVAILABLE” BASIS AND WE MAKE NO REPRESENTATIONS OR WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, AS TO THE OPERATION OF THE PLATFORM OR THE INFORMATION AND CONTENT INCLUDED ON THE PLATFORM. YOU EXPRESSLY AGREE THAT YOUR USE OF THE PLATFORM IS AT YOUR SOLE RISK.\n\nTO THE FULLEST EXTENT PERMISSIBLE BY APPLICABLE LAW, WE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED. WE DO NOT WARRANT THAT THE PLATFORM, ITS SERVERS, OR EMAIL/OTHER COMMUNICATION SENT FROM THE PLATFORM ARE FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS. WE WILL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND ARISING FROM THE USE OF THE PLATFORM, INCLUDING, BUT NOT LIMITED TO DIRECT, INDIRECT, INCIDENTAL, PUNITIVE, AND CONSEQUENTIAL DAMAGES.\n\nALL INTERACTION, COMMUNICATION, DEALING, OR TRANSACTION BETWEEN THE USERS AND THE THIRD-PARTY PROVIDER IN RESPECT OF ANY PRODUCTS/SERVICES OFFERED BY THE THIRD-PARTY PROVIDER IS A SEPARATE AND INDEPENDENT TRANSACTION BETWEEN THE USER AND SUCH THIRD-PARTY PROVIDER WITHOUT ANY LIABILITY ACCRUING TO OR ON US FOR ANY MATTERS ARISING OUT OF OR IN RELATION TO THE SAME. THE USER EXPRESSLY AGREES AND ACKNOWLEDGES TO HOLD HARMLESS US IN RESPECT OF ANY COST, CLAIMS, DAMAGE, LOSS, OR EXPENSES ACCRUED, SUFFERED, INCURRED BY US OR ANY THIRD PARTY ARISING OUT OF OR IN CONNECTION WITH ANY SUCH COMMUNICATION, INTERACTION, DEALINGS, AND TRANSACTIONS BETWEEN THE USER AND THIRD-PARTY PROVIDERS. THE USER ACKNOWLEDGES THAT WE DO NOT HAVE ANY CONTROL OVER SUCH DEALINGS AND TRANSACTIONS AND PLAYS NO DETERMINATIVE ROLE IN THE PERFORMANCE IN RESPECT OF THE SAME AND WE SHALL NOT BE LIABLE FOR THE OUTCOMES OF SUCH COMMUNICATION, INTERACTION, DEALINGS, AND TRANSACTIONS BETWEEN THE USERS AND THE THIRD-PARTY PROVIDERS.\n\nWE DO NOT WARRANT, ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR ANY PRODUCT OR SERVICE ADVERTISED OR OFFERED BY A THIRD-PARTY PROVIDER IN ANY MANNER AND WE WILL NOT BE A PARTY TO OR IN ANY WAY BE RESPONSIBLE FOR ANY TRANSACTION BETWEEN YOU AND SUCH PARTY PROVIDER. AS WITH THE PURCHASE OF A PRODUCT OR SERVICE THROUGH ANY MEDIUM THROUGH SUCH THIRD-PARTY PROVIDER, YOU SHOULD USE YOUR BEST JUDGMENT AND EXERCISE CAUTION WHERE APPROPRIATE.</string>
<string name="woka_songs">WOKA Songs</string>
<string name="app_name_caps" translatable="false">WOKA</string>
<string name="do_you_want_to_exit_from_the_woka_app">Do you want to exit from the WOKA app?</string>
</resources>