#319 show hint when blocked cause of obscured while entering the license
Need to manually handle this in case of dialogs as otherwise the onFilterTouchEventForSecurity method of the ViewGroup isn't called when filterTouchesWhenObscured is set to true in the BaseDialog and in contrast to if set in an Activity
This commit is contained in:
parent
9a65f62ae5
commit
68bb87c04b
@ -6,13 +6,14 @@ import org.cryptomator.domain.usecases.LicenseCheck
|
|||||||
import org.cryptomator.domain.usecases.NoOpResultHandler
|
import org.cryptomator.domain.usecases.NoOpResultHandler
|
||||||
import org.cryptomator.presentation.exception.ExceptionHandlers
|
import org.cryptomator.presentation.exception.ExceptionHandlers
|
||||||
import org.cryptomator.presentation.ui.activity.view.UpdateLicenseView
|
import org.cryptomator.presentation.ui.activity.view.UpdateLicenseView
|
||||||
|
import org.cryptomator.presentation.ui.dialog.AppIsObscuredInfoDialog
|
||||||
import org.cryptomator.util.SharedPreferencesHandler
|
import org.cryptomator.util.SharedPreferencesHandler
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
class LicenseCheckPresenter @Inject internal constructor(
|
class LicenseCheckPresenter @Inject internal constructor(
|
||||||
exceptionHandlers: ExceptionHandlers, //
|
exceptionHandlers: ExceptionHandlers, //
|
||||||
private val doLicenseCheckUsecase: DoLicenseCheckUseCase, //
|
private val doLicenseCheckUseCase: DoLicenseCheckUseCase, //
|
||||||
private val sharedPreferencesHandler: SharedPreferencesHandler
|
private val sharedPreferencesHandler: SharedPreferencesHandler
|
||||||
) : Presenter<UpdateLicenseView>(exceptionHandlers) {
|
) : Presenter<UpdateLicenseView>(exceptionHandlers) {
|
||||||
|
|
||||||
@ -20,18 +21,22 @@ class LicenseCheckPresenter @Inject internal constructor(
|
|||||||
data?.let {
|
data?.let {
|
||||||
val license = it.fragment ?: it.lastPathSegment ?: ""
|
val license = it.fragment ?: it.lastPathSegment ?: ""
|
||||||
view?.showOrUpdateLicenseDialog(license)
|
view?.showOrUpdateLicenseDialog(license)
|
||||||
doLicenseCheckUsecase
|
doLicenseCheckUseCase
|
||||||
.withLicense(license)
|
.withLicense(license)
|
||||||
.run(CheckLicenseStatusSubscriber())
|
.run(CheckLicenseStatusSubscriber())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun validateDialogAware(license: String?) {
|
fun validateDialogAware(license: String?) {
|
||||||
doLicenseCheckUsecase
|
doLicenseCheckUseCase
|
||||||
.withLicense(license)
|
.withLicense(license)
|
||||||
.run(CheckLicenseStatusSubscriber())
|
.run(CheckLicenseStatusSubscriber())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onFilteredTouchEventForSecurity() {
|
||||||
|
view?.showDialog(AppIsObscuredInfoDialog.newInstance())
|
||||||
|
}
|
||||||
|
|
||||||
private inner class CheckLicenseStatusSubscriber : NoOpResultHandler<LicenseCheck>() {
|
private inner class CheckLicenseStatusSubscriber : NoOpResultHandler<LicenseCheck>() {
|
||||||
|
|
||||||
override fun onSuccess(licenseCheck: LicenseCheck) {
|
override fun onSuccess(licenseCheck: LicenseCheck) {
|
||||||
@ -49,6 +54,6 @@ class LicenseCheckPresenter @Inject internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
unsubscribeOnDestroy(doLicenseCheckUsecase)
|
unsubscribeOnDestroy(doLicenseCheckUseCase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,13 @@ import org.cryptomator.presentation.presenter.LicenseCheckPresenter
|
|||||||
import org.cryptomator.presentation.ui.activity.view.UpdateLicenseView
|
import org.cryptomator.presentation.ui.activity.view.UpdateLicenseView
|
||||||
import org.cryptomator.presentation.ui.dialog.LicenseConfirmationDialog
|
import org.cryptomator.presentation.ui.dialog.LicenseConfirmationDialog
|
||||||
import org.cryptomator.presentation.ui.dialog.UpdateLicenseDialog
|
import org.cryptomator.presentation.ui.dialog.UpdateLicenseDialog
|
||||||
|
import org.cryptomator.presentation.ui.layout.ObscuredAwareCoordinatorLayout
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
import kotlinx.android.synthetic.main.activity_layout_obscure_aware.activityRootView
|
||||||
import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
||||||
|
|
||||||
@Activity
|
@Activity(layout = R.layout.activity_layout_obscure_aware)
|
||||||
class LicenseCheckActivity : BaseActivity(), UpdateLicenseDialog.Callback, LicenseConfirmationDialog.Callback, UpdateLicenseView {
|
class LicenseCheckActivity : BaseActivity(), UpdateLicenseDialog.Callback, LicenseConfirmationDialog.Callback, UpdateLicenseView {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@ -23,11 +25,19 @@ class LicenseCheckActivity : BaseActivity(), UpdateLicenseDialog.Callback, Licen
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setupToolbar()
|
activityRootView.setOnFilteredTouchEventForSecurityListener(object : ObscuredAwareCoordinatorLayout.Listener {
|
||||||
|
override fun onFilteredTouchEventForSecurity() {
|
||||||
|
licenseCheckPresenter.onFilteredTouchEventForSecurity()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
validate(intent)
|
validate(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setupView() {
|
||||||
|
setupToolbar()
|
||||||
|
}
|
||||||
|
|
||||||
override fun checkLicenseClicked(license: String?) {
|
override fun checkLicenseClicked(license: String?) {
|
||||||
licenseCheckPresenter.validateDialogAware(license)
|
licenseCheckPresenter.validateDialogAware(license)
|
||||||
}
|
}
|
||||||
@ -51,6 +61,11 @@ class LicenseCheckActivity : BaseActivity(), UpdateLicenseDialog.Callback, Licen
|
|||||||
exitProcess(0)
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun appObscuredClosingEnterLicenseDialog() {
|
||||||
|
closeDialog()
|
||||||
|
licenseCheckPresenter.onFilteredTouchEventForSecurity()
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
toolbar.title = getString(R.string.app_name).uppercase()
|
toolbar.title = getString(R.string.app_name).uppercase()
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
|
@ -82,9 +82,7 @@ abstract class BaseDialog<Callback> : DialogFragment() {
|
|||||||
get() = requireContext().resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
get() = requireContext().resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
|
||||||
fun onErrorResponse(view: View?) {
|
fun onErrorResponse(view: View?) {
|
||||||
if (view != null) {
|
view?.let { it.isFocusableInTouchMode = true }
|
||||||
view.isFocusableInTouchMode = true
|
|
||||||
}
|
|
||||||
allowClosingDialog(true)
|
allowClosingDialog(true)
|
||||||
enableButtons(true)
|
enableButtons(true)
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,10 @@ class LicenseConfirmationDialog : BaseDialog<LicenseConfirmationDialog.Callback>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
return builder //
|
||||||
.setTitle(getString(R.string.dialog_license_confirmation_title)) //
|
.setTitle(getString(R.string.dialog_license_confirmation_title)) //
|
||||||
.setNeutralButton(getText(R.string.dialog_license_confirmation_ok_btn)) { _: DialogInterface, _: Int -> callback?.licenseConfirmationClicked() }
|
.setNeutralButton(getText(R.string.dialog_license_confirmation_ok_btn)) { _: DialogInterface, _: Int -> callback?.licenseConfirmationClicked() } //
|
||||||
return builder.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun setupView() {
|
public override fun setupView() {
|
||||||
|
@ -7,6 +7,9 @@ import android.widget.Button
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import org.cryptomator.generator.Dialog
|
import org.cryptomator.generator.Dialog
|
||||||
import org.cryptomator.presentation.R
|
import org.cryptomator.presentation.R
|
||||||
|
import org.cryptomator.presentation.ui.layout.ObscuredAwareDialogCoordinatorLayout
|
||||||
|
import org.cryptomator.util.SharedPreferencesHandler
|
||||||
|
import kotlinx.android.synthetic.main.dialog_enter_license.dssialogRootView
|
||||||
import kotlinx.android.synthetic.main.dialog_enter_license.et_license
|
import kotlinx.android.synthetic.main.dialog_enter_license.et_license
|
||||||
|
|
||||||
@Dialog(R.layout.dialog_enter_license)
|
@Dialog(R.layout.dialog_enter_license)
|
||||||
@ -19,6 +22,7 @@ class UpdateLicenseDialog : BaseProgressErrorDialog<UpdateLicenseDialog.Callback
|
|||||||
|
|
||||||
fun checkLicenseClicked(license: String?)
|
fun checkLicenseClicked(license: String?)
|
||||||
fun onCheckLicenseCanceled()
|
fun onCheckLicenseCanceled()
|
||||||
|
fun appObscuredClosingEnterLicenseDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
@ -35,6 +39,15 @@ class UpdateLicenseDialog : BaseProgressErrorDialog<UpdateLicenseDialog.Callback
|
|||||||
et_license.nextFocusForwardId = button.id
|
et_license.nextFocusForwardId = button.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* need to manually handle this in case of dialogs as otherwise the onFilterTouchEventForSecurity method of the ViewGroup
|
||||||
|
isn't called when filterTouchesWhenObscured is set to true in the BaseDialog and in contrast to if set in an Activity */
|
||||||
|
dialog?.window?.decorView?.filterTouchesWhenObscured = false
|
||||||
|
dssialogRootView.setOnFilteredTouchEventForSecurityListener(object : ObscuredAwareDialogCoordinatorLayout.Listener {
|
||||||
|
override fun onFilteredTouchEventForSecurity() {
|
||||||
|
callback?.appObscuredClosingEnterLicenseDialog()
|
||||||
|
}
|
||||||
|
}, SharedPreferencesHandler(requireContext()).disableAppWhenObscured())
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
@ -47,9 +60,7 @@ class UpdateLicenseDialog : BaseProgressErrorDialog<UpdateLicenseDialog.Callback
|
|||||||
|
|
||||||
public override fun setupView() {
|
public override fun setupView() {
|
||||||
val license = requireArguments().getSerializable(LICENSE_ARG) as String?
|
val license = requireArguments().getSerializable(LICENSE_ARG) as String?
|
||||||
if (license != null) {
|
license?.let { et_license.setText(it) }
|
||||||
et_license.setText(license)
|
|
||||||
}
|
|
||||||
et_license.requestFocus()
|
et_license.requestFocus()
|
||||||
registerOnEditorDoneActionAndPerformButtonClick(et_license) { checkLicenseButton }
|
registerOnEditorDoneActionAndPerformButtonClick(et_license) { checkLicenseButton }
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package org.cryptomator.presentation.ui.layout
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
|
||||||
|
class ObscuredAwareDialogCoordinatorLayout : CoordinatorLayout {
|
||||||
|
|
||||||
|
private var listener: Listener? = null
|
||||||
|
|
||||||
|
private var active: Boolean = true
|
||||||
|
|
||||||
|
constructor(context: Context) : super(context)
|
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||||
|
|
||||||
|
fun setOnFilteredTouchEventForSecurityListener(listener: Listener, active: Boolean) {
|
||||||
|
this.listener = listener
|
||||||
|
this.active = active
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFilterTouchEventForSecurity(event: MotionEvent): Boolean {
|
||||||
|
return if (active and ((event.flags and MotionEvent.FLAG_WINDOW_IS_OBSCURED) == MotionEvent.FLAG_WINDOW_IS_OBSCURED)) {
|
||||||
|
listener?.onFilteredTouchEventForSecurity()
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Listener {
|
||||||
|
|
||||||
|
fun onFilteredTouchEventForSecurity()
|
||||||
|
}
|
||||||
|
}
|
@ -1,51 +1,57 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<org.cryptomator.presentation.ui.layout.ObscuredAwareDialogCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/dssialogRootView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<RelativeLayout
|
<androidx.core.widget.NestedScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:padding="@dimen/activity_vertical_margin">
|
|
||||||
|
|
||||||
<TextView
|
<RelativeLayout
|
||||||
android:id="@+id/tv_message"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="5dp"
|
android:padding="@dimen/activity_vertical_margin">
|
||||||
android:text="@string/dialog_enter_license_content" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<TextView
|
||||||
android:id="@+id/ll_folder"
|
android:id="@+id/tv_message"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/tv_message"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:src="@drawable/ic_license_key" />
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/et_license"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:imeOptions="actionDone|flagNoPersonalizedLearning"
|
android:layout_marginBottom="5dp"
|
||||||
android:inputType="text" />
|
android:text="@string/dialog_enter_license_content" />
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<include
|
<LinearLayout
|
||||||
layout="@layout/view_dialog_progress"
|
android:id="@+id/ll_license"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/til_password" />
|
android:layout_below="@+id/tv_message"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<include
|
<ImageView
|
||||||
layout="@layout/view_dialog_error"
|
android:layout_width="40dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="40dp"
|
||||||
android:layout_height="wrap_content"
|
android:src="@drawable/ic_license_key" />
|
||||||
android:layout_below="@+id/ll_folder" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
</androidx.core.widget.NestedScrollView>
|
android:id="@+id/et_license"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:imeOptions="actionDone|flagNoPersonalizedLearning"
|
||||||
|
android:inputType="text" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/view_dialog_progress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/til_password" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/view_dialog_error"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/ll_license" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
</org.cryptomator.presentation.ui.layout.ObscuredAwareDialogCoordinatorLayout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user