forked from melod1n/fast-messenger
Simple screens and logic with Navigation Component
This commit is contained in:
Binary file not shown.
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "com.meloda.fast",
|
||||
"variantName": "processReleaseResources",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"versionCode": 1,
|
||||
"versionName": "1.0",
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package com.meloda.fast.base
|
||||
|
||||
import android.content.Intent
|
||||
import android.util.SparseArray
|
||||
import androidx.core.util.forEach
|
||||
import androidx.core.util.set
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.meloda.fast.R
|
||||
|
||||
|
||||
/*
|
||||
fun BottomNavigationView.setupWithNavController(
|
||||
navGraphIds: List<Int>,
|
||||
fragmentManager: FragmentManager,
|
||||
dataManager: DataManager,
|
||||
containerId: Int,
|
||||
intent: Intent
|
||||
): LiveData<NavController> {
|
||||
|
||||
// Map of tags
|
||||
val graphIdToTagMap = SparseArray<String>()
|
||||
// Result. Mutable live data with the selected controlled
|
||||
val selectedNavController = MutableLiveData<NavController>()
|
||||
|
||||
var firstFragmentGraphId = 0
|
||||
|
||||
// First create a NavHostFragment for each NavGraph ID
|
||||
navGraphIds.forEachIndexed { index, navGraphId ->
|
||||
val fragmentTag = getFragmentTag(index)
|
||||
|
||||
// Find or create the Navigation host fragment
|
||||
val navHostFragment = obtainNavHostFragment(
|
||||
fragmentManager,
|
||||
fragmentTag,
|
||||
navGraphId,
|
||||
containerId
|
||||
)
|
||||
|
||||
// Obtain its id
|
||||
val graphId = navHostFragment.navController.graph.id
|
||||
|
||||
if (index == 0) {
|
||||
firstFragmentGraphId = graphId
|
||||
}
|
||||
|
||||
// Save to the map
|
||||
graphIdToTagMap[graphId] = fragmentTag
|
||||
|
||||
// Attach or detach nav host fragment depending on whether it's the selected item.
|
||||
if (this.selectedItemId == graphId) {
|
||||
// Update livedata with the selected graph
|
||||
selectedNavController.value = navHostFragment.navController
|
||||
attachNavHostFragment(fragmentManager, navHostFragment, index == 0)
|
||||
} else {
|
||||
detachNavHostFragment(fragmentManager, navHostFragment)
|
||||
}
|
||||
}
|
||||
|
||||
// Now connect selecting an item with swapping Fragments
|
||||
var selectedItemTag = graphIdToTagMap[this.selectedItemId]
|
||||
val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId]
|
||||
var isOnFirstFragment = selectedItemTag == firstFragmentTag
|
||||
|
||||
// When a navigation item is selected
|
||||
setOnNavigationItemSelectedListener { item ->
|
||||
// Don't do anything if the state is state has already been saved.
|
||||
if (fragmentManager.isStateSaved) {
|
||||
false
|
||||
} else {
|
||||
val navController = (fragmentManager.findFragmentByTag(selectedItemTag) as NavHostFragment).navController
|
||||
navController.popBackStack(navController.graph.startDestination, false)
|
||||
if (selectedItemTag != graphIdToTagMap[item.itemId]) {
|
||||
val listCheck = listOf(R.id.contacts, R.id.chats)
|
||||
val newlySelectedItemTag = if (listCheck.contains(item.itemId) && dataManager.token.isBlank()) graphIdToTagMap[R.id.signIn] else graphIdToTagMap[item.itemId]
|
||||
|
||||
// Pop everything above the first fragment (the "fixed start destination")
|
||||
fragmentManager.popBackStack(
|
||||
firstFragmentTag,
|
||||
FragmentManager.POP_BACK_STACK_INCLUSIVE
|
||||
)
|
||||
val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag) as NavHostFragment
|
||||
|
||||
// Exclude the first fragment tag because it's always in the back stack.
|
||||
if (firstFragmentTag != newlySelectedItemTag) {
|
||||
// Commit a transaction that cleans the back stack and adds the first fragment
|
||||
// to it, creating the fixed started destination.
|
||||
fragmentManager.beginTransaction()
|
||||
.setCustomAnimations(
|
||||
R.anim.nav_default_enter_anim,
|
||||
R.anim.nav_default_exit_anim,
|
||||
R.anim.nav_default_pop_enter_anim,
|
||||
R.anim.nav_default_pop_exit_anim
|
||||
)
|
||||
.attach(selectedFragment)
|
||||
.setPrimaryNavigationFragment(selectedFragment)
|
||||
.apply {
|
||||
// Detach all other Fragments
|
||||
graphIdToTagMap.forEach { _, fragmentTagIter ->
|
||||
if (fragmentTagIter != newlySelectedItemTag) {
|
||||
detach(fragmentManager.findFragmentByTag(firstFragmentTag)!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
.addToBackStack(firstFragmentTag)
|
||||
.setReorderingAllowed(true)
|
||||
.commit()
|
||||
}
|
||||
selectedItemTag = newlySelectedItemTag
|
||||
isOnFirstFragment = selectedItemTag == firstFragmentTag
|
||||
selectedNavController.value = selectedFragment.navController
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
setOnNavigationItemReselectedListener { item ->
|
||||
val newlySelectedItemTag = graphIdToTagMap[item.itemId]
|
||||
val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag) as NavHostFragment
|
||||
val navController = selectedFragment.navController
|
||||
// Pop the back stack to the start destination of the current navController graph
|
||||
if (selectedItemTag != graphIdToTagMap[item.itemId] && dataManager.token.isNotBlank()) {
|
||||
fragmentManager.beginTransaction()
|
||||
.setCustomAnimations(
|
||||
R.anim.nav_default_enter_anim,
|
||||
R.anim.nav_default_exit_anim,
|
||||
R.anim.nav_default_pop_enter_anim,
|
||||
R.anim.nav_default_pop_exit_anim
|
||||
)
|
||||
.attach(selectedFragment)
|
||||
.setPrimaryNavigationFragment(selectedFragment)
|
||||
.apply {
|
||||
// Detach all other Fragments
|
||||
graphIdToTagMap.forEach { _, fragmentTagIter ->
|
||||
if (fragmentTagIter != newlySelectedItemTag) {
|
||||
detach(fragmentManager.findFragmentByTag(firstFragmentTag)!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
.addToBackStack(firstFragmentTag)
|
||||
.setReorderingAllowed(true)
|
||||
.commit()
|
||||
selectedItemTag = newlySelectedItemTag
|
||||
isOnFirstFragment = selectedItemTag == firstFragmentTag
|
||||
selectedNavController.value = selectedFragment.navController
|
||||
} else navController.popBackStack(navController.graph.startDestination, false)
|
||||
}
|
||||
// Optional: on item reselected, pop back stack to the destination of the graph
|
||||
setupDeepLinks(navGraphIds, fragmentManager, containerId, intent)
|
||||
|
||||
// Finally, ensure that we update our BottomNavigationView when the back stack changes
|
||||
fragmentManager.addOnBackStackChangedListener {
|
||||
if (!isOnFirstFragment && !fragmentManager.isOnBackStack(firstFragmentTag)) {
|
||||
this.selectedItemId = firstFragmentGraphId
|
||||
}
|
||||
|
||||
// Reset the graph if the currentDestination is not valid (happens when the back
|
||||
// stack is popped after using the back button).
|
||||
selectedNavController.value?.let { controller ->
|
||||
if (controller.currentDestination == null) {
|
||||
controller.navigate(controller.graph.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectedNavController
|
||||
}
|
||||
|
||||
private fun BottomNavigationView.setupDeepLinks(
|
||||
navGraphIds: List<Int>,
|
||||
fragmentManager: FragmentManager,
|
||||
containerId: Int,
|
||||
intent: Intent
|
||||
) {
|
||||
navGraphIds.forEachIndexed { index, navGraphId ->
|
||||
val fragmentTag = getFragmentTag(index)
|
||||
|
||||
// Find or create the Navigation host fragment
|
||||
val navHostFragment = obtainNavHostFragment(
|
||||
fragmentManager,
|
||||
fragmentTag,
|
||||
navGraphId,
|
||||
containerId
|
||||
)
|
||||
// Handle Intent
|
||||
if (navHostFragment.navController.handleDeepLink(intent) &&
|
||||
selectedItemId != navHostFragment.navController.graph.id
|
||||
) {
|
||||
this.selectedItemId = navHostFragment.navController.graph.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun detachNavHostFragment(
|
||||
fragmentManager: FragmentManager,
|
||||
navHostFragment: NavHostFragment
|
||||
) {
|
||||
fragmentManager.beginTransaction()
|
||||
.detach(navHostFragment)
|
||||
.commitNow()
|
||||
}
|
||||
|
||||
private fun attachNavHostFragment(
|
||||
fragmentManager: FragmentManager,
|
||||
navHostFragment: NavHostFragment,
|
||||
isPrimaryNavFragment: Boolean
|
||||
) {
|
||||
fragmentManager.beginTransaction()
|
||||
.attach(navHostFragment)
|
||||
.apply {
|
||||
if (isPrimaryNavFragment) {
|
||||
setPrimaryNavigationFragment(navHostFragment)
|
||||
}
|
||||
}
|
||||
.commitNow()
|
||||
}
|
||||
|
||||
private fun obtainNavHostFragment(
|
||||
fragmentManager: FragmentManager,
|
||||
fragmentTag: String,
|
||||
navGraphId: Int,
|
||||
containerId: Int,
|
||||
): NavHostFragment {
|
||||
// If the Nav Host fragment exists, return it
|
||||
val existingFragment = fragmentManager.findFragmentByTag(fragmentTag) as NavHostFragment?
|
||||
existingFragment?.let { return it }
|
||||
|
||||
// Otherwise, create it and return it.
|
||||
val navHostFragment = NavHostFragment.create(navGraphId)
|
||||
fragmentManager.beginTransaction()
|
||||
.add(containerId, navHostFragment, fragmentTag)
|
||||
.commitNow()
|
||||
return navHostFragment
|
||||
}
|
||||
|
||||
private fun FragmentManager.isOnBackStack(backStackName: String): Boolean {
|
||||
val backStackCount = backStackEntryCount
|
||||
for (index in 0 until backStackCount) {
|
||||
if (getBackStackEntryAt(index).name == backStackName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getFragmentTag(index: Int) = "bottomNavigation#$index"
|
||||
*/
|
||||
@@ -27,4 +27,7 @@ abstract class BaseVM : ViewModel() {
|
||||
)
|
||||
}
|
||||
}.also { it.invokeOnCompletion { viewModelScope.launch { onEnd?.invoke() } } }
|
||||
|
||||
protected suspend fun <T : VKEvent> sendEvent(event: T) = tasksEventChannel.send(event)
|
||||
|
||||
}
|
||||
@@ -6,3 +6,6 @@ data class ShowDialogInfoEvent(
|
||||
val positiveBtn: String? = null,
|
||||
val negativeBtn: String? = null
|
||||
) : VKEvent()
|
||||
|
||||
object StartProgressEvent : VKEvent()
|
||||
object StopProgressEvent : VKEvent()
|
||||
@@ -4,6 +4,7 @@ import android.content.Intent
|
||||
import android.util.SparseArray
|
||||
import androidx.core.util.forEach
|
||||
import androidx.core.util.set
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
@@ -11,6 +12,7 @@ import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.meloda.fast.R
|
||||
import com.meloda.fast.UserConfig
|
||||
|
||||
/**
|
||||
* Manages the various graphs needed for a [BottomNavigationView].
|
||||
@@ -22,7 +24,6 @@ object NavigationExtensions {
|
||||
fun BottomNavigationView.setupWithNavController(
|
||||
navGraphIds: List<Int>,
|
||||
fragmentManager: FragmentManager,
|
||||
// dataManager: DataManager,
|
||||
containerId: Int,
|
||||
intent: Intent
|
||||
): LiveData<NavController> {
|
||||
@@ -71,8 +72,7 @@ object NavigationExtensions {
|
||||
val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId]
|
||||
var isOnFirstFragment = selectedItemTag == firstFragmentTag
|
||||
|
||||
// When a navigation item is selected
|
||||
setOnNavigationItemSelectedListener { item ->
|
||||
setOnItemSelectedListener { item ->
|
||||
// Don't do anything if the state is state has already been saved.
|
||||
if (fragmentManager.isStateSaved) {
|
||||
false
|
||||
@@ -81,12 +81,9 @@ object NavigationExtensions {
|
||||
(fragmentManager.findFragmentByTag(selectedItemTag) as NavHostFragment).navController
|
||||
navController.popBackStack(navController.graph.startDestination, false)
|
||||
if (selectedItemTag != graphIdToTagMap[item.itemId]) {
|
||||
// val listCheck = listOf(R.id.contacts, R.id.chats)
|
||||
val newlySelectedItemTag =
|
||||
//if (listCheck.contains(item.itemId) && dataManager.token.isBlank()) graphIdToTagMap[R.id.signIn] else
|
||||
graphIdToTagMap[item.itemId]
|
||||
val newlySelectedItemTag = //graphIdToTagMap[item.itemId]
|
||||
if (!UserConfig.isLoggedIn()) graphIdToTagMap[R.id.login] else graphIdToTagMap[item.itemId]
|
||||
|
||||
// Pop everything above the first fragment (the "fixed start destination")
|
||||
fragmentManager.popBackStack(
|
||||
firstFragmentTag,
|
||||
FragmentManager.POP_BACK_STACK_INCLUSIVE
|
||||
@@ -128,7 +125,8 @@ object NavigationExtensions {
|
||||
}
|
||||
}
|
||||
}
|
||||
setOnNavigationItemReselectedListener { item ->
|
||||
|
||||
setOnItemReselectedListener { item ->
|
||||
val newlySelectedItemTag = graphIdToTagMap[item.itemId]
|
||||
val selectedFragment =
|
||||
fragmentManager.findFragmentByTag(newlySelectedItemTag) as NavHostFragment
|
||||
@@ -257,5 +255,12 @@ object NavigationExtensions {
|
||||
return false
|
||||
}
|
||||
|
||||
val FragmentManager.visibleFragments
|
||||
get(): List<Fragment> {
|
||||
val visibleFragments = arrayListOf<Fragment>()
|
||||
fragments.forEach { if (it.isVisible) visibleFragments.add(it) }
|
||||
return visibleFragments
|
||||
}
|
||||
|
||||
private fun getFragmentTag(index: Int) = "bottomNavigation#$index"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.meloda.fast.fragment.friends
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.viewbinding.library.fragment.viewBinding
|
||||
import com.meloda.fast.R
|
||||
import com.meloda.fast.base.BaseFragment
|
||||
import com.meloda.fast.databinding.FragmentFriendsBinding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class FriendsFragment : BaseFragment(R.layout.fragment_friends) {
|
||||
|
||||
private val binding: FragmentFriendsBinding by viewBinding()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.meloda.fast.fragment.important
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.viewbinding.library.fragment.viewBinding
|
||||
import com.meloda.fast.R
|
||||
import com.meloda.fast.base.BaseFragment
|
||||
import com.meloda.fast.databinding.FragmentImportantBinding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ImportantFragment : BaseFragment(R.layout.fragment_important) {
|
||||
|
||||
private val binding: FragmentImportantBinding by viewBinding()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.meloda.fast.fragment.login
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.KeyEvent
|
||||
@@ -7,9 +8,11 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.viewbinding.library.fragment.viewBinding
|
||||
import android.webkit.CookieManager
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.fragment.app.setFragmentResultListener
|
||||
import androidx.fragment.app.viewModels
|
||||
@@ -21,11 +24,15 @@ import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.meloda.fast.R
|
||||
import com.meloda.fast.base.BaseVMFragment
|
||||
import com.meloda.fast.base.viewmodel.StartProgressEvent
|
||||
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
||||
import com.meloda.fast.base.viewmodel.VKEvent
|
||||
import com.meloda.fast.databinding.FragmentLoginBinding
|
||||
import com.meloda.fast.fragment.main.MainFragment
|
||||
import com.meloda.fast.util.KeyboardUtils
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import kotlin.concurrent.schedule
|
||||
@@ -45,7 +52,7 @@ class LoginFragment : BaseVMFragment<LoginVM>(R.layout.fragment_login) {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
viewModel.checkUserSession()
|
||||
(parentFragment?.parentFragment as? MainFragment)?.bottomBar?.isVisible = false
|
||||
|
||||
prepareViews()
|
||||
|
||||
@@ -63,16 +70,49 @@ class LoginFragment : BaseVMFragment<LoginVM>(R.layout.fragment_login) {
|
||||
when (event) {
|
||||
is ShowCaptchaDialog -> showCaptchaDialog(event.captchaImage, event.captchaSid)
|
||||
is GoToValidationEvent -> goToValidation(event.redirectUrl)
|
||||
GoToMainEvent -> goToMain()
|
||||
is GoToMainEvent -> goToMain(event.haveAuthorized)
|
||||
StartProgressEvent -> onProgressStarted()
|
||||
StopProgressEvent -> onProgressEnded()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onProgressStarted() {
|
||||
binding.loginContainer.isVisible = false
|
||||
binding.passwordContainer.isVisible = false
|
||||
binding.auth.isVisible = false
|
||||
binding.progress.isVisible = true
|
||||
}
|
||||
|
||||
private fun onProgressEnded() {
|
||||
binding.loginContainer.isVisible = true
|
||||
binding.passwordContainer.isVisible = true
|
||||
binding.auth.isVisible = true
|
||||
binding.progress.isVisible = false
|
||||
}
|
||||
|
||||
private fun prepareViews() {
|
||||
prepareWebView()
|
||||
prepareEmailEditText()
|
||||
preparePasswordEditText()
|
||||
prepareAuthButton()
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
private fun prepareWebView() {
|
||||
with(binding.webView) {
|
||||
settings.javaScriptEnabled = true
|
||||
settings.domStorageEnabled = true
|
||||
settings.loadsImagesAutomatically = false
|
||||
settings.userAgentString = "Chrome/41.0.2228.0 Safari/537.36"
|
||||
clearCache(true)
|
||||
}
|
||||
|
||||
val cookieManager = CookieManager.getInstance()
|
||||
cookieManager.removeAllCookies(null)
|
||||
cookieManager.flush()
|
||||
cookieManager.setAcceptCookie(false)
|
||||
}
|
||||
|
||||
private fun prepareEmailEditText() {
|
||||
binding.loginInput.addTextChangedListener {
|
||||
if (!binding.loginLayout.error.isNullOrBlank()) binding.loginLayout.error = ""
|
||||
@@ -98,21 +138,30 @@ class LoginFragment : BaseVMFragment<LoginVM>(R.layout.fragment_login) {
|
||||
(event.action == KeyEvent.ACTION_DOWN && (event.keyCode == KeyEvent.KEYCODE_ENTER || event.keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER))
|
||||
) {
|
||||
KeyboardUtils.hideKeyboardFrom(binding.passwordInput)
|
||||
binding.authorize.performClick()
|
||||
binding.auth.performClick()
|
||||
true
|
||||
} else false
|
||||
}
|
||||
}
|
||||
|
||||
private fun prepareAuthButton() {
|
||||
binding.authorize.setOnClickListener {
|
||||
binding.auth.setOnClickListener {
|
||||
if (binding.progress.isVisible) return@setOnClickListener
|
||||
|
||||
val loginString = binding.loginInput.text.toString().trim()
|
||||
val passwordString = binding.passwordInput.text.toString().trim()
|
||||
|
||||
if (!validateInputData(loginString, passwordString)) return@setOnClickListener
|
||||
|
||||
viewModel.login(requireContext(), loginString, passwordString)
|
||||
KeyboardUtils.hideKeyboardFrom(it)
|
||||
|
||||
lifecycleScope.launch {
|
||||
viewModel.login(
|
||||
binding.webView,
|
||||
loginString,
|
||||
passwordString
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,17 +242,18 @@ class LoginFragment : BaseVMFragment<LoginVM>(R.layout.fragment_login) {
|
||||
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
val captchaCode = captchaCodeEditText.text.toString().trim()
|
||||
|
||||
viewModel.login(
|
||||
requireContext(),
|
||||
lastEmail,
|
||||
lastPassword,
|
||||
"&captcha_sid=$captchaSid&captcha_key=$captchaCode"
|
||||
)
|
||||
lifecycleScope.launch {
|
||||
viewModel.login(
|
||||
binding.webView,
|
||||
lastEmail,
|
||||
lastPassword,
|
||||
"&captcha_sid=$captchaSid&captcha_key=$captchaCode"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
builder.setTitle(R.string.input_captcha)
|
||||
builder.show()
|
||||
|
||||
}
|
||||
|
||||
private fun goToValidation(redirectUrl: String) {
|
||||
@@ -213,8 +263,12 @@ class LoginFragment : BaseVMFragment<LoginVM>(R.layout.fragment_login) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun goToMain() {
|
||||
findNavController().navigate(R.id.toMain)
|
||||
private fun goToMain(haveAuthorized: Boolean) {
|
||||
lifecycleScope.launch {
|
||||
if (haveAuthorized) delay(500)
|
||||
|
||||
findNavController().navigate(R.id.toMain)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
package com.meloda.fast.fragment.login
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.CookieManager
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
@@ -12,68 +8,53 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.meloda.fast.UserConfig
|
||||
import com.meloda.fast.api.VKAuth
|
||||
import com.meloda.fast.base.viewmodel.BaseVM
|
||||
import com.meloda.fast.base.viewmodel.StartProgressEvent
|
||||
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
||||
import com.meloda.fast.base.viewmodel.VKEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.Jsoup
|
||||
|
||||
class LoginVM : BaseVM() {
|
||||
|
||||
fun login(
|
||||
context: Context,
|
||||
private var isWebViewPrepared = true
|
||||
|
||||
suspend fun login(
|
||||
webView: WebView,
|
||||
email: String,
|
||||
password: String,
|
||||
captcha: String = ""
|
||||
) {
|
||||
sendEvent(StartProgressEvent)
|
||||
|
||||
val urlToGo = VKAuth.getDirectAuthUrl(email, password, captcha)
|
||||
|
||||
// val builder = AlertDialog.Builder(context)
|
||||
if (isWebViewPrepared) {
|
||||
isWebViewPrepared = false
|
||||
|
||||
val webView = createWebView(context)
|
||||
webView.layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
webView.addJavascriptInterface(WebViewHandlerInterface(), "HtmlHandler")
|
||||
|
||||
// builder.setTitle("Auth")
|
||||
// builder.setView(webView)
|
||||
// builder.show()
|
||||
|
||||
webView.addJavascriptInterface(WebViewHandlerInterface(), "HtmlHandler")
|
||||
webView.webViewClient = object : WebViewClient() {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
webView.loadUrl(
|
||||
"javascript:window.HtmlHandler.handleHtml" +
|
||||
"('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');"
|
||||
)
|
||||
webView.webViewClient = object : WebViewClient() {
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
webView.loadUrl(
|
||||
"javascript:window.HtmlHandler.handleHtml" +
|
||||
"('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
webView.loadUrl(urlToGo)
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
private fun createWebView(context: Context): WebView {
|
||||
val loginWebView = WebView(context)
|
||||
|
||||
loginWebView.settings.javaScriptEnabled = true
|
||||
loginWebView.settings.domStorageEnabled = true
|
||||
loginWebView.settings.loadsImagesAutomatically = false
|
||||
loginWebView.settings.userAgentString = "Chrome/41.0.2228.0 Safari/537.36"
|
||||
|
||||
loginWebView.clearCache(true)
|
||||
|
||||
val cookieManager = CookieManager.getInstance()
|
||||
cookieManager.removeAllCookies(null)
|
||||
cookieManager.flush()
|
||||
cookieManager.setAcceptCookie(false)
|
||||
|
||||
return loginWebView
|
||||
}
|
||||
|
||||
@Suppress("MoveVariableDeclarationIntoWhen")
|
||||
private fun checkResponse(response: JSONObject) {
|
||||
viewModelScope.launch {
|
||||
viewModelScope.launch(Dispatchers.Default) {
|
||||
delay(1500)
|
||||
sendEvent(StopProgressEvent)
|
||||
|
||||
if (response.has("error")) {
|
||||
val errorString = response.optString("error")
|
||||
|
||||
@@ -82,33 +63,12 @@ class LoginVM : BaseVM() {
|
||||
val redirectUrl = response.optString("redirect_uri")
|
||||
|
||||
tasksEventChannel.send(GoToValidationEvent(redirectUrl))
|
||||
|
||||
// val bundle = Bundle()
|
||||
// bundle.putString("url", redirectUrl)
|
||||
|
||||
/* fragment.setFragmentResultListener("validation") { _, bundle ->
|
||||
val userId = bundle.getInt("userId")
|
||||
val token = bundle.getString("token") ?: ""
|
||||
saveUserData(userId, token)
|
||||
|
||||
openMainScreen()
|
||||
}
|
||||
|
||||
|
||||
fragment.parentFragmentManager.beginTransaction()
|
||||
.replace(
|
||||
R.id.fragmentContainer,
|
||||
ValidationFragment().apply { arguments = bundle })
|
||||
.addToBackStack("")
|
||||
.commit()*/
|
||||
|
||||
}
|
||||
"need_captcha" -> {
|
||||
val captchaImage = response.optString("captcha_img")
|
||||
val captchaSid = response.optString("captcha_sid")
|
||||
|
||||
tasksEventChannel.send(ShowCaptchaDialog(captchaImage, captchaSid))
|
||||
// showCaptchaDialog(captchaImage, captchaSid)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -118,11 +78,7 @@ class LoginVM : BaseVM() {
|
||||
UserConfig.accessToken = accessToken
|
||||
UserConfig.userId = userId
|
||||
|
||||
tasksEventChannel.send(GoToMainEvent)
|
||||
|
||||
// openMainScreen()
|
||||
|
||||
// onResponseListener?.onResponse(null)
|
||||
tasksEventChannel.send(GoToMainEvent())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,11 +90,7 @@ class LoginVM : BaseVM() {
|
||||
UserConfig.accessToken = accessToken
|
||||
UserConfig.userId = userId
|
||||
|
||||
tasksEventChannel.send(GoToMainEvent)
|
||||
}
|
||||
|
||||
fun checkUserSession() = viewModelScope.launch {
|
||||
if (UserConfig.isLoggedIn()) tasksEventChannel.send(GoToMainEvent)
|
||||
tasksEventChannel.send(GoToMainEvent())
|
||||
}
|
||||
|
||||
inner class WebViewHandlerInterface {
|
||||
@@ -158,4 +110,4 @@ class LoginVM : BaseVM() {
|
||||
|
||||
data class ShowCaptchaDialog(val captchaImage: String, val captchaSid: String) : VKEvent()
|
||||
data class GoToValidationEvent(val redirectUrl: String) : VKEvent()
|
||||
object GoToMainEvent : VKEvent()
|
||||
data class GoToMainEvent(val haveAuthorized: Boolean = true) : VKEvent()
|
||||
@@ -4,7 +4,9 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.viewbinding.library.fragment.viewBinding
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.meloda.fast.R
|
||||
import com.meloda.fast.UserConfig
|
||||
import com.meloda.fast.base.BaseVMFragment
|
||||
import com.meloda.fast.databinding.FragmentMainBinding
|
||||
import com.meloda.fast.extensions.NavigationExtensions.setupWithNavController
|
||||
@@ -21,18 +23,29 @@ class MainFragment : BaseVMFragment<MainVM>(R.layout.fragment_main) {
|
||||
|
||||
if (savedInstanceState == null) setupBottomBar()
|
||||
|
||||
if (!UserConfig.isLoggedIn()) findNavController().navigate(R.id.toLogin)
|
||||
}
|
||||
|
||||
private fun setupBottomBar() {
|
||||
val navGraphIds = listOf(R.id.messages, R.id.friends)
|
||||
|
||||
binding.bottomBar.setupWithNavController(
|
||||
navGraphIds = listOf(),
|
||||
fragmentManager = childFragmentManager,
|
||||
containerId = R.id.fragmentContainer,
|
||||
intent = requireActivity().intent
|
||||
val navGraphIds = listOf(
|
||||
R.navigation.messages,
|
||||
R.navigation.friends,
|
||||
R.navigation.important,
|
||||
R.navigation.login
|
||||
)
|
||||
|
||||
with(binding.bottomBar) {
|
||||
selectedItemId = R.id.messages
|
||||
setupWithNavController(
|
||||
navGraphIds = navGraphIds,
|
||||
fragmentManager = childFragmentManager,
|
||||
containerId = R.id.fragmentContainer,
|
||||
intent = requireActivity().intent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val bottomBar get() = binding.bottomBar
|
||||
|
||||
|
||||
}
|
||||
@@ -1,9 +1,21 @@
|
||||
package com.meloda.fast.fragment.messages
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.viewbinding.library.fragment.viewBinding
|
||||
import com.meloda.fast.R
|
||||
import com.meloda.fast.base.BaseFragment
|
||||
import com.meloda.fast.databinding.FragmentConversationsBinding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ConversationsFragment : BaseFragment(R.layout.fragment_conversations) {
|
||||
|
||||
private val binding: FragmentConversationsBinding by viewBinding()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
|
||||
</vector>
|
||||
@@ -4,6 +4,11 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="conversations" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -5,20 +5,25 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="friends" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/toolbar_background"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/toolbar_background"
|
||||
app:layout_scrollFlags="scroll|enterAlways">
|
||||
|
||||
<include layout="@layout/toolbar" />
|
||||
|
||||
@@ -3,4 +3,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="important" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/loginRoot"
|
||||
@@ -8,6 +9,12 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -16,6 +23,7 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
@@ -37,6 +45,14 @@
|
||||
app:tint="?colorAccent" />
|
||||
</FrameLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="48dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/loginContainer"
|
||||
android:layout_width="match_parent"
|
||||
@@ -110,7 +126,7 @@
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/authorize"
|
||||
android:id="@+id/auth"
|
||||
style="@style/Widget.MaterialButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="60dp"
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/navigationFriends"
|
||||
android:id="@id/friends"
|
||||
android:icon="@drawable/ic_people_outline"
|
||||
android:title="@string/navigation_friends" />
|
||||
|
||||
<item
|
||||
android:id="@+id/navigationConversations"
|
||||
android:id="@id/messages"
|
||||
android:icon="@drawable/ic_message_outline"
|
||||
android:title="@string/navigation_chats" />
|
||||
|
||||
<item
|
||||
android:id="@+id/navigationImportant"
|
||||
android:id="@id/important"
|
||||
android:icon="@drawable/ic_star_border"
|
||||
android:title="@string/navigation_important" />
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/friends">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/friends"
|
||||
app:startDestination="@+id/friendsFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/friendsFragment"
|
||||
android:name="com.meloda.fast.fragment.friends.FriendsFragment"
|
||||
android:label="FriendsFragment"
|
||||
tools:layout="@layout/fragment_friends" />
|
||||
|
||||
</navigation>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation 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/important"
|
||||
app:startDestination="@id/importantFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/importantFragment"
|
||||
android:name="com.meloda.fast.fragment.important.ImportantFragment"
|
||||
android:label="ImportantFragment"
|
||||
tools:layout="@layout/fragment_important" />
|
||||
|
||||
</navigation>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation 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/login"
|
||||
app:startDestination="@id/loginFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/loginFragment"
|
||||
android:name="com.meloda.fast.fragment.login.LoginFragment"
|
||||
android:label="LoginFragment"
|
||||
tools:layout="@layout/fragment_login">
|
||||
|
||||
<action
|
||||
android:id="@+id/toMain"
|
||||
app:destination="@id/mainFragment"
|
||||
app:popUpTo="@id/loginFragment"
|
||||
app:popUpToInclusive="true" />
|
||||
|
||||
<action
|
||||
android:id="@+id/toValidation"
|
||||
app:destination="@id/validationFragment" />
|
||||
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/validationFragment"
|
||||
android:name="com.meloda.fast.fragment.login.ValidationFragment"
|
||||
android:label="ValidationFragment"
|
||||
tools:layout="@layout/fragment_validation">
|
||||
|
||||
<action
|
||||
android:id="@+id/toLogin"
|
||||
app:destination="@id/loginFragment"
|
||||
app:popUpTo="@id/validationFragment"
|
||||
app:popUpToInclusive="true" />
|
||||
|
||||
</fragment>
|
||||
|
||||
|
||||
</navigation>
|
||||
@@ -3,13 +3,19 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
app:startDestination="@id/loginFragment">
|
||||
app:startDestination="@id/mainFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/mainFragment"
|
||||
android:name="com.meloda.fast.fragment.main.MainFragment"
|
||||
android:label="MainFragment"
|
||||
tools:layout="@layout/fragment_main" />
|
||||
tools:layout="@layout/fragment_main">
|
||||
|
||||
<action
|
||||
android:id="@+id/toLogin"
|
||||
app:destination="@id/loginFragment" />
|
||||
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/loginFragment"
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/messages">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/messages"
|
||||
app:startDestination="@+id/conversationsFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/conversationsFragment"
|
||||
android:name="com.meloda.fast.fragment.messages.ConversationsFragment"
|
||||
android:label="ConversationsFragment"
|
||||
tools:layout="@layout/fragment_conversations" />
|
||||
|
||||
</navigation>
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
|
||||
<item name="colorPrimary">@color/dark_primary</item>
|
||||
<item name="colorPrimaryDark">@color/dark_primaryDark</item>
|
||||
<item name="colorAccent">@color/dark_accent</item>
|
||||
|
||||
<item name="toolbarStyle">@style/AppTheme.Toolbar</item>
|
||||
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
|
||||
<item name="dialogCornerRadius">12dp</item>
|
||||
<item name="android:windowBackground">@color/dark_background</item>
|
||||
<item name="itemTitleColor">?colorAccent</item>
|
||||
<item name="dividerHorizontal">@color/dark_divider</item>
|
||||
<item name="textColorSecondary">@color/dark_textSecondary</item>
|
||||
<item name="editTextFilledBackgroundColor">@color/dark_edittext_filled_background</item>
|
||||
|
||||
<item name="messageInTextColor">@color/dark_message_in</item>
|
||||
<item name="messageOutTextColor">@color/dark_message_out</item>
|
||||
|
||||
<item name="android:windowAnimationStyle">@style/AppTheme.ActivityAnimation</item>
|
||||
|
||||
<item name="android:navigationBarColor">@color/dark_navigationBar</item>
|
||||
<item name="android:navigationBarDividerColor" tools:targetApi="o_mr1">
|
||||
@android:color/transparent
|
||||
</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Toolbar" parent="Widget.MaterialComponents.Toolbar.PrimarySurface">
|
||||
<item name="titleTextAppearance">@style/Toolbar.Title</item>
|
||||
<item name="android:textSize">24sp</item>
|
||||
<item name="android:elevation">3dp</item>
|
||||
<item name="titleTextColor">@color/dark_accent</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Login.EditText" parent="">
|
||||
<item name="android:layout_height">52dp</item>
|
||||
<item name="android:background">@drawable/edittext_filled_background</item>
|
||||
<item name="android:paddingStart">16dp</item>
|
||||
<item name="android:paddingEnd">16dp</item>
|
||||
<item name="android:layout_marginEnd">16dp</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
<item name="android:textColorHint">?textColorSecondary</item>
|
||||
<item name="fontFamily">@font/google_sans_regular</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:maxLines">1</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.FullScreenDialog" parent="Theme.MaterialComponents.DayNight.Dialog.Bridge">
|
||||
<item name="colorPrimary">@color/dark_primary</item>
|
||||
<item name="colorPrimaryDark">@color/dark_primaryDark</item>
|
||||
<item name="colorAccent">@color/dark_accent</item>
|
||||
<item name="android:windowIsFloating">false</item>
|
||||
<item name="android:windowBackground">@color/dark_background</item>
|
||||
<item name="actionMenuTextColor">?colorAccent</item>
|
||||
|
||||
<item name="android:navigationBarColor" tools:targetApi="o_mr1">@color/dark_navigationBar</item>
|
||||
<item name="android:navigationBarDividerColor" tools:targetApi="o_mr1">
|
||||
@android:color/transparent
|
||||
</item>
|
||||
|
||||
<item name="colorControlNormal">?colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.ProfileDialog" parent="Theme.MaterialComponents.DayNight.BottomSheetDialog">
|
||||
<item name="colorAccent">@color/dark_accent</item>
|
||||
<item name="colorPrimary">@color/dark_primary</item>
|
||||
<item name="colorPrimaryDark">@color/dark_primaryDark</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
|
||||
<item name="colorPrimary">@color/primary</item>
|
||||
<item name="colorPrimaryDark">@color/primaryDark</item>
|
||||
<item name="colorAccent">@color/accent</item>
|
||||
@@ -27,8 +27,6 @@
|
||||
<item name="android:navigationBarDividerColor" tools:targetApi="o_mr1">
|
||||
@android:color/transparent
|
||||
</item>
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Toolbar" parent="Widget.MaterialComponents.Toolbar.PrimarySurface">
|
||||
@@ -59,15 +57,16 @@
|
||||
<item name="android:maxLines">1</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.FullScreenDialog" parent="Theme.MaterialComponents.Light.Dialog.Bridge">
|
||||
<style name="AppTheme.FullScreenDialog" parent="Theme.MaterialComponents.DayNight.Dialog.Bridge">
|
||||
<item name="colorPrimary">@color/primary</item>
|
||||
<item name="colorPrimaryDark">@color/primaryDark</item>
|
||||
<item name="colorAccent">@color/accent</item>
|
||||
<item name="android:windowIsFloating">false</item>
|
||||
<item name="android:windowBackground">@color/background</item>
|
||||
<item name="actionMenuTextColor">?colorAccent</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
|
||||
<item name="android:navigationBarColor" tools:targetApi="o_mr1">?colorPrimaryDark</item>
|
||||
<item name="android:navigationBarColor" tools:targetApi="o_mr1">@color/navigationBar</item>
|
||||
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">true</item>
|
||||
<item name="android:navigationBarDividerColor" tools:targetApi="o_mr1">
|
||||
@android:color/transparent
|
||||
@@ -82,10 +81,11 @@
|
||||
<item name="android:layout_marginEnd">12dp</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.ProfileDialog" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
|
||||
<style name="AppTheme.ProfileDialog" parent="Theme.MaterialComponents.DayNight.BottomSheetDialog">
|
||||
<item name="colorAccent">@color/accent</item>
|
||||
<item name="colorPrimary">@color/primary</item>
|
||||
<item name="colorPrimaryDark">@color/primaryDark</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.TextInputLayout" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
|
||||
|
||||
Reference in New Issue
Block a user