MainActivity: Move navigation drawer items into dialogfragment

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2024-04-15 14:07:46 +05:30
parent 37fa494583
commit c3963519e0
20 changed files with 445 additions and 284 deletions

View File

@@ -25,6 +25,11 @@ object Constants {
const val APP_ID = "com.aurora.store"
const val URL_TOS = "https://play.google.com/about/play-terms/"
const val URL_LICENSE = "https://gitlab.com/AuroraOSS/AuroraStore/blob/master/LICENSE"
const val URL_DISCLAIMER = "https://gitlab.com/AuroraOSS/AuroraStore/blob/master/DISCLAIMER.md"
const val URL_POLICY = "https://gitlab.com/AuroraOSS/AuroraStore/-/blob/master/POLICY.md"
const val EXODUS_SUBMIT_PAGE = "https://reports.exodus-privacy.eu.org/analysis/submit/#"
const val EXODUS_REPORT_URL = "https://reports.exodus-privacy.eu.org/reports/"
const val SHARE_URL = "https://play.google.com/store/apps/details?id="

View File

@@ -20,32 +20,17 @@
package com.aurora.store
import android.content.Intent
import android.content.res.ColorStateList
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.addCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.core.graphics.ColorUtils
import androidx.drawerlayout.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED
import androidx.drawerlayout.widget.DrawerLayout.LOCK_MODE_UNLOCKED
import androidx.lifecycle.lifecycleScope
import androidx.navigation.FloatingWindow
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import coil.load
import coil.transform.RoundedCornersTransformation
import com.aurora.Constants
import com.aurora.extensions.accentColor
import com.aurora.extensions.applyThemeAccent
@@ -56,7 +41,6 @@ import com.aurora.store.util.Log
import com.aurora.store.util.Preferences
import com.aurora.store.util.Preferences.PREFERENCE_DEFAULT_SELECTED_TAB
import com.aurora.store.view.ui.sheets.NetworkDialogSheet
import com.google.android.material.bottomnavigation.BottomNavigationView
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
@@ -65,7 +49,6 @@ class MainActivity : AppCompatActivity() {
private lateinit var B: ActivityMainBinding
private lateinit var navController: NavController
private lateinit var appConfig: AppBarConfiguration
// TopLevelFragments
private val topLevelFrags = listOf(
@@ -111,11 +94,11 @@ class MainActivity : AppCompatActivity() {
}
}
// Toolbar
setSupportActionBar(B.toolbar)
attachNavigation()
attachDrawer()
B.navView.apply {
val alphaColor = ColorUtils.setAlphaComponent(this@MainActivity.accentColor(), 100)
setupWithNavController(navController)
itemActiveIndicatorColor = ColorStateList.valueOf(alphaColor)
}
// Handle quick exit from back actions
val defaultTab = when (Preferences.getInteger(this, PREFERENCE_DEFAULT_SELECTED_TAB)) {
@@ -124,21 +107,17 @@ class MainActivity : AppCompatActivity() {
else -> R.id.appsContainerFragment
}
onBackPressedDispatcher.addCallback(this) {
if (!B.drawerLayout.isOpen) {
if (navController.currentDestination?.id in topLevelFrags) {
if (navController.currentDestination?.id == defaultTab) {
finish()
} else {
navController.navigate(defaultTab)
}
} else if (navHostFragment.childFragmentManager.backStackEntryCount == 0) {
// We are on either on onboarding or splash fragment
if (navController.currentDestination?.id in topLevelFrags) {
if (navController.currentDestination?.id == defaultTab) {
finish()
} else {
navController.navigateUp()
navController.navigate(defaultTab)
}
} else if (navHostFragment.childFragmentManager.backStackEntryCount == 0) {
// We are on either on onboarding or splash fragment
finish()
} else {
B.drawerLayout.close()
navController.navigateUp()
}
}
@@ -152,84 +131,13 @@ class MainActivity : AppCompatActivity() {
navController.addOnDestinationChangedListener { _, navDestination, _ ->
if (navDestination !is FloatingWindow) {
when (navDestination.id) {
in topLevelFrags -> {
B.navView.visibility = View.VISIBLE
B.toolbar.visibility = View.VISIBLE
B.drawerLayout.setDrawerLockMode(LOCK_MODE_UNLOCKED)
}
else -> {
hideTopLevelOnlyViews()
}
in topLevelFrags -> B.navView.visibility = View.VISIBLE
else -> B.navView.visibility = View.GONE
}
}
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_download_manager -> {
navController.navigate(R.id.downloadFragment)
return true
}
}
return super.onOptionsItemSelected(item)
}
private fun hideTopLevelOnlyViews() {
B.navView.visibility = View.GONE
B.toolbar.visibility = View.GONE
B.drawerLayout.setDrawerLockMode(LOCK_MODE_LOCKED_CLOSED)
}
private fun attachNavigation() {
val bottomNavigationView: BottomNavigationView = B.navView
bottomNavigationView.setupWithNavController(navController)
bottomNavigationView.apply {
val alphaColor = ColorUtils.setAlphaComponent(this@MainActivity.accentColor(), 100)
itemActiveIndicatorColor = ColorStateList.valueOf(alphaColor)
}
}
private fun attachDrawer() {
val headerView: View = B.navigation.getHeaderView(0)
headerView.let {
it.findViewById<ImageView>(R.id.img)?.load(R.mipmap.ic_launcher) {
transformations(RoundedCornersTransformation(8F))
}
it.findViewById<TextView>(R.id.txt_name)?.text = getString(R.string.app_name)
it.findViewById<TextView>(R.id.txt_email)?.text = getString(
R.string.version,
BuildConfig.VERSION_NAME,
BuildConfig.VERSION_CODE
)
}
appConfig = AppBarConfiguration.Builder(topLevelFrags.toSet())
.setOpenableLayout(B.root)
.build()
setupActionBarWithNavController(navController, appConfig)
B.navigation.setupWithNavController(navController)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appConfig)
}
private fun checkExternalStorageManagerPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!Environment.isExternalStorageManager())
startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
}
}
private fun isIntroDone(): Boolean {
return Preferences.getBoolean(this@MainActivity, Preferences.PREFERENCE_INTRO)
}

View File

@@ -26,6 +26,9 @@ import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import coil.load
import coil.transform.RoundedCornersTransformation
import com.aurora.Constants.URL_DISCLAIMER
import com.aurora.Constants.URL_LICENSE
import com.aurora.Constants.URL_TOS
import com.aurora.extensions.browse
import com.aurora.gplayapi.data.models.AuthData
import com.aurora.store.R
@@ -48,11 +51,6 @@ class AccountFragment : Fragment(R.layout.fragment_account) {
private lateinit var authData: AuthData
private lateinit var accountProvider: AccountProvider
private val URL_TOS = "https://play.google.com/about/play-terms/"
private val URL_LICENSE = "https://gitlab.com/AuroraOSS/AuroraStore/blob/master/LICENSE"
private val URL_DISCLAIMER =
"https://gitlab.com/AuroraOSS/AuroraStore/blob/master/DISCLAIMER.md"
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentAccountBinding.bind(view)

View File

@@ -26,6 +26,7 @@ import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.aurora.store.MobileNavigationDirections
import com.aurora.store.R
import com.aurora.store.data.providers.AuthProvider
import com.aurora.store.databinding.FragmentAppsGamesBinding
@@ -48,6 +49,24 @@ class AppsContainerFragment : Fragment(R.layout.fragment_apps_games) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentAppsGamesBinding.bind(view)
// Toolbar
binding.toolbar.apply {
title = getString(R.string.title_apps)
setOnMenuItemClickListener {
when (it.itemId) {
R.id.menu_download_manager -> {
findNavController().navigate(R.id.downloadFragment)
}
R.id.menu_more -> {
findNavController().navigate(
MobileNavigationDirections.actionGlobalMoreDialogFragment()
)
}
}
true
}
}
// ViewPager
val isForYouEnabled = Preferences.getBoolean(
requireContext(),

View File

@@ -0,0 +1,282 @@
package com.aurora.store.view.ui.commons
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import androidx.annotation.DrawableRes
import androidx.annotation.IdRes
import androidx.annotation.StringRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.util.fastForEach
import androidx.core.graphics.ColorUtils
import androidx.fragment.app.DialogFragment
import androidx.navigation.fragment.findNavController
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.aurora.Constants
import com.aurora.Constants.URL_TOS
import com.aurora.extensions.accentColor
import com.aurora.extensions.browse
import com.aurora.store.R
import com.aurora.store.data.providers.AuthProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
class MoreDialogFragment : DialogFragment() {
private data class Option(
@StringRes val title: Int,
@DrawableRes val icon: Int,
@IdRes val destinationID: Int
)
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return MaterialAlertDialogBuilder(requireContext())
.setView(customDialogView(requireContext()))
.create()
}
private fun customDialogView(context: Context): ComposeView {
return ComposeView(context).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
val bColor = ColorUtils.setAlphaComponent(LocalContext.current.accentColor(), 20)
Column(
modifier = Modifier
.fillMaxWidth()
.background(color = Color(bColor))
.verticalScroll(rememberScrollState())
.padding(13.dp),
verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.CenterVertically)
) {
AppBar()
AccountHeader()
Column(
modifier = Modifier
.clip(
RoundedCornerShape(
topStart = 5.dp,
topEnd = 5.dp,
bottomStart = 20.dp,
bottomEnd = 20.dp
)
)
.background(color = Color.White)
) {
getOptions().fastForEach { option -> OptionItem(option = option) }
}
getExtraOptions().fastForEach { option -> OptionItem(option = option) }
Footer()
}
}
}
}
@Composable
fun AppBar() {
Box(contentAlignment = Alignment.CenterStart) {
IconButton(onClick = { findNavController().navigateUp() }) {
Icon(
painter = painterResource(id = R.drawable.ic_cancel),
contentDescription = stringResource(id = R.string.action_cancel),
tint = Color.Black
)
}
Text(
modifier = Modifier.fillMaxWidth(),
text = stringResource(id = R.string.app_name),
style = MaterialTheme.typography.titleMedium,
textAlign = TextAlign.Center
)
}
}
@Composable
fun Footer() {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(5.dp, Alignment.CenterHorizontally)
) {
TextButton(onClick = { requireContext().browse(Constants.URL_POLICY) }) {
Text(
text = stringResource(id = R.string.privacy_policy_title),
color = Color.Black
)
}
Text(text = "")
TextButton(onClick = { requireContext().browse(URL_TOS) }) {
Text(
text = stringResource(id = R.string.menu_terms),
color = Color.Black
)
}
}
}
@Composable
private fun AccountHeader() {
val authData = AuthProvider.with(LocalContext.current).getAuthData()
Column(
modifier = Modifier
.fillMaxWidth()
.clip(
RoundedCornerShape(
topStart = 20.dp,
topEnd = 20.dp,
bottomStart = 5.dp,
bottomEnd = 5.dp
)
)
.background(color = Color.White)
.padding(20.dp),
verticalArrangement = Arrangement.spacedBy(15.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
modifier = Modifier
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(15.dp, Alignment.Start)
) {
SubcomposeAsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(if (authData.isAnonymous) R.mipmap.ic_launcher else authData.userProfile?.artwork?.url)
.placeholder(R.drawable.ic_account)
.crossfade(true)
.build(),
contentDescription = stringResource(id = R.string.title_account_manager),
contentScale = ContentScale.Crop,
modifier = Modifier
.requiredSize(48.dp)
.clip(CircleShape)
)
Column(
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.Start
) {
Text(
text = if (authData.isAnonymous) "anonymous" else authData.userProfile!!.name,
fontWeight = FontWeight.SemiBold,
fontSize = 16.sp
)
Text(
text = if (authData.isAnonymous) "anonymous@gmail.com" else authData.userProfile!!.email,
fontWeight = FontWeight.Normal,
fontSize = 14.sp
)
}
}
OutlinedButton(
onClick = { findNavController().navigate(R.id.accountFragment) },
shape = RoundedCornerShape(12.dp)
) {
Text(
text = stringResource(id = R.string.manage_account),
color = Color.Black
)
}
}
}
@Composable
private fun OptionItem(option: Option) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { findNavController().navigate(option.destinationID) }
.padding(15.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.Start)
) {
Image(
painter = painterResource(id = option.icon),
contentDescription = stringResource(id = option.title),
colorFilter = ColorFilter.tint(color = Color.Black),
modifier = Modifier
.padding(horizontal = 10.dp)
.requiredSize(25.dp)
)
Text(
modifier = Modifier.fillMaxWidth(),
text = stringResource(id = option.title),
color = Color.Black,
fontSize = 16.sp,
)
}
}
private fun getOptions(): List<Option> {
return listOf(
Option(
title = R.string.title_apps_games,
icon = R.drawable.ic_apps,
destinationID = R.id.appsGamesFragment
),
Option(
title = R.string.title_apps_sale,
icon = R.drawable.ic_sale,
destinationID = R.id.appSalesFragment
),
Option(
title = R.string.title_blacklist_manager,
icon = R.drawable.ic_blacklist,
destinationID = R.id.blacklistFragment
),
Option(
title = R.string.title_spoof_manager,
icon = R.drawable.ic_spoof,
destinationID = R.id.spoofFragment
)
)
}
private fun getExtraOptions(): List<Option> {
return listOf(
Option(
title = R.string.title_settings,
icon = R.drawable.ic_menu_settings,
destinationID = R.id.settingsFragment
),
Option(
title = R.string.title_about,
icon = R.drawable.ic_menu_about,
destinationID = R.id.aboutFragment
)
)
}
}

View File

@@ -26,6 +26,7 @@ import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.aurora.store.MobileNavigationDirections
import com.aurora.store.R
import com.aurora.store.data.providers.AuthProvider
import com.aurora.store.databinding.FragmentAppsGamesBinding
@@ -48,6 +49,24 @@ class GamesContainerFragment : Fragment(R.layout.fragment_apps_games) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentAppsGamesBinding.bind(view)
// Toolbar
binding.toolbar.apply {
title = getString(R.string.title_games)
setOnMenuItemClickListener {
when (it.itemId) {
R.id.menu_download_manager -> {
findNavController().navigate(R.id.downloadFragment)
}
R.id.menu_more -> {
findNavController().navigate(
MobileNavigationDirections.actionGlobalMoreDialogFragment()
)
}
}
true
}
}
// ViewPager
val isForYouEnabled = Preferences.getBoolean(
requireContext(),

View File

@@ -36,6 +36,7 @@ import com.aurora.extensions.browse
import com.aurora.extensions.isRAndAbove
import com.aurora.extensions.toast
import com.aurora.gplayapi.data.models.App
import com.aurora.store.MobileNavigationDirections
import com.aurora.store.R
import com.aurora.store.data.event.BusEvent
import com.aurora.store.data.room.download.Download
@@ -87,6 +88,21 @@ class UpdatesFragment : BaseFragment(R.layout.fragment_updates) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentUpdatesBinding.bind(view)
// Toolbar
binding.toolbar.setOnMenuItemClickListener {
when (it.itemId) {
R.id.menu_download_manager -> {
findNavController().navigate(R.id.downloadFragment)
}
R.id.menu_more -> {
findNavController().navigate(
MobileNavigationDirections.actionGlobalMoreDialogFragment()
)
}
}
true
}
viewModel.observe()
viewLifecycleOwner.lifecycleScope.launch {
viewModel.updates.combine(viewModel.downloadsList) { uList, dList ->