diff --git a/changelog/unreleased/4871 b/changelog/unreleased/4871 new file mode 100644 index 00000000000..fea65f1f46d --- /dev/null +++ b/changelog/unreleased/4871 @@ -0,0 +1,6 @@ +Enhancement: Passcode and pattern screens in landscape mode + +Orientation restrictions defined in the manifest have been removed, and support for both +orientations (portrait and landscape) has been added to the passcode and pattern screens. + +https://github.com/owncloud/android/pull/4871 diff --git a/owncloudApp/src/main/AndroidManifest.xml b/owncloudApp/src/main/AndroidManifest.xml index 8576ebf3229..73bf0a56ddf 100644 --- a/owncloudApp/src/main/AndroidManifest.xml +++ b/owncloudApp/src/main/AndroidManifest.xml @@ -187,7 +187,6 @@ diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/security/passcode/PassCodeActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/security/passcode/PassCodeActivity.kt index cf89b1d4223..bcd791fe4f4 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/security/passcode/PassCodeActivity.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/security/passcode/PassCodeActivity.kt @@ -13,7 +13,7 @@ * @author Jorge Aguado Recio * * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2025 ownCloud GmbH. + * Copyright (C) 2026 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -42,7 +42,7 @@ import android.widget.LinearLayout import androidx.appcompat.app.AppCompatActivity import com.owncloud.android.BuildConfig import com.owncloud.android.R -import com.owncloud.android.databinding.PasscodelockBinding +import com.owncloud.android.databinding.PasscodeLockActivityBinding import com.owncloud.android.domain.utils.Event import com.owncloud.android.extensions.showBiometricDialog import com.owncloud.android.extensions.showMessageInSnackbar @@ -66,7 +66,7 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom private val biometricViewModel by viewModel() - private var _binding: PasscodelockBinding? = null + private var _binding: PasscodeLockActivityBinding? = null val binding get() = _binding!! private lateinit var passCodeEditTexts: Array @@ -87,7 +87,7 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom subscribeToViewModel() - _binding = PasscodelockBinding.inflate(layoutInflater) + _binding = PasscodeLockActivityBinding.inflate(layoutInflater) // protection against screen recording if (!BuildConfig.DEBUG) { @@ -106,7 +106,7 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom // Allow or disallow touches with other visible windows binding.passcodeLockLayout.filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(this) - binding.explanation.filterTouchesWhenObscured = + binding.passcodeExplanation.filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(this) inflatePasscodeTxtLine() @@ -120,8 +120,8 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom when (intent.action) { ACTION_CHECK -> { //When you start the app with passcode // this is a pass code request; the user has to input the right value - binding.header.text = getString(R.string.pass_code_enter_pass_code) - binding.explanation.visibility = View.INVISIBLE + binding.passcodeHeader.text = getString(R.string.pass_code_enter_pass_code) + binding.passcodeExplanation.visibility = View.INVISIBLE supportActionBar?.setDisplayHomeAsUpEnabled(false) //Don´t show the back arrow } @@ -131,14 +131,14 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom requestPassCodeConfirmation() } else { if (intent.extras?.getBoolean(EXTRAS_MIGRATION) == true) { - binding.header.text = + binding.passcodeHeader.text = getString(R.string.pass_code_configure_your_pass_code_migration, passCodeViewModel.getNumberOfPassCodeDigits()) } else { // pass code preference has just been activated in Preferences; // will receive and confirm pass code value - binding.header.text = getString(R.string.pass_code_configure_your_pass_code) + binding.passcodeHeader.text = getString(R.string.pass_code_configure_your_pass_code) } - binding.explanation.visibility = View.VISIBLE + binding.passcodeExplanation.visibility = View.VISIBLE when { intent.extras?.getBoolean(EXTRAS_MIGRATION) == true -> { supportActionBar?.setDisplayHomeAsUpEnabled(false) @@ -158,8 +158,8 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom ACTION_REMOVE -> { // Remove password // pass code preference has just been disabled in Preferences; // will confirm user knows pass code, then remove it - binding.header.text = getString(R.string.pass_code_remove_your_pass_code) - binding.explanation.visibility = View.INVISIBLE + binding.passcodeHeader.text = getString(R.string.pass_code_remove_your_pass_code) + binding.passcodeExplanation.visibility = View.INVISIBLE supportActionBar?.setDisplayHomeAsUpEnabled(true) } @@ -180,7 +180,7 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom } private fun inflatePasscodeTxtLine() { - val layoutCode = findViewById(R.id.layout_code) + val layoutCode = findViewById(R.id.passcode_value) val numberOfPasscodeDigits = (passCodeViewModel.getPassCode()?.length ?: passCodeViewModel.getNumberOfPassCodeDigits()) for (i in 0 until numberOfPasscodeDigits) { val txt = layoutInflater.inflate(R.layout.passcode_edit_text, layoutCode, false) as EditText @@ -259,14 +259,14 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom private fun actionCheckOk() { // pass code accepted in request, user is allowed to access the app - binding.error.visibility = View.INVISIBLE + binding.passcodeError.visibility = View.INVISIBLE PassCodeManager.onActivityStopped(this) finish() } private fun actionCheckMigration() { - binding.error.visibility = View.INVISIBLE + binding.passcodeError.visibility = View.INVISIBLE val intent = Intent(baseContext, PassCodeActivity::class.java) intent.apply { @@ -305,7 +305,7 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom } private fun actionCreateNoConfirm() { - binding.error.visibility = View.INVISIBLE + binding.passcodeError.visibility = View.INVISIBLE requestPassCodeConfirmation() } @@ -341,10 +341,10 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom errorMessage: Int, headerMessage: String, explanationVisibility: Int ) { - binding.error.setText(errorMessage) - binding.error.visibility = View.VISIBLE - binding.header.text = headerMessage - binding.explanation.visibility = explanationVisibility + binding.passcodeError.setText(errorMessage) + binding.passcodeError.visibility = View.VISIBLE + binding.passcodeHeader.text = headerMessage + binding.passcodeExplanation.visibility = explanationVisibility clearBoxes() } @@ -354,8 +354,8 @@ class PassCodeActivity : AppCompatActivity(), NumberKeyboardListener, EnableBiom */ private fun requestPassCodeConfirmation() { clearBoxes() - binding.header.setText(R.string.pass_code_reenter_your_pass_code) - binding.explanation.visibility = View.INVISIBLE + binding.passcodeHeader.setText(R.string.pass_code_reenter_your_pass_code) + binding.passcodeExplanation.visibility = View.INVISIBLE confirmingPassCode = true } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/security/pattern/PatternActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/security/pattern/PatternActivity.kt index 4afc2bc51dc..3d3b0d238f7 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/security/pattern/PatternActivity.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/security/pattern/PatternActivity.kt @@ -8,7 +8,7 @@ * @author Juan Carlos Garrote Gascón * @author Jorge Aguado Recio * - * Copyright (C) 2025 ownCloud GmbH. + * Copyright (C) 2026 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -40,7 +40,7 @@ import com.andrognito.patternlockview.utils.PatternLockUtils import com.owncloud.android.BuildConfig import com.owncloud.android.R import com.owncloud.android.data.providers.implementation.OCSharedPreferencesProvider -import com.owncloud.android.databinding.ActivityPatternLockBinding +import com.owncloud.android.databinding.PatternLockActivityBinding import com.owncloud.android.extensions.showBiometricDialog import com.owncloud.android.extensions.showMessageInSnackbar import com.owncloud.android.presentation.documentsprovider.DocumentsProviderUtils.notifyDocumentsProviderRoots @@ -59,7 +59,7 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { private val patternViewModel by viewModel() private val biometricViewModel by viewModel() - private var _binding: ActivityPatternLockBinding? = null + private var _binding: PatternLockActivityBinding? = null val binding get() = _binding!! private var confirmingPattern = false @@ -75,7 +75,7 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) } - _binding = ActivityPatternLockBinding.inflate(layoutInflater) + _binding = PatternLockActivityBinding.inflate(layoutInflater) setContentView(binding.root) @@ -102,8 +102,8 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { * This block is executed when the user opens the app after setting the pattern lock * this block takes the pattern input by the user and checks it with the pattern initially set by the user. */ - binding.headerPattern.text = getString(R.string.pattern_enter_pattern) - binding.explanationPattern.visibility = View.INVISIBLE + binding.patternHeader.text = getString(R.string.pattern_enter_pattern) + binding.patternExplanation.visibility = View.INVISIBLE supportActionBar?.setDisplayHomeAsUpEnabled(false) } ACTION_REQUEST_WITH_RESULT -> { @@ -118,13 +118,13 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { patternExpShouldVisible = savedInstanceState.getBoolean(PATTERN_EXP_VIEW_STATE) } if (confirmingPattern) { - binding.headerPattern.text = headerPatternViewText + binding.patternHeader.text = headerPatternViewText if (!patternExpShouldVisible) { - binding.explanationPattern.visibility = View.INVISIBLE + binding.patternExplanation.visibility = View.INVISIBLE } } else { - binding.headerPattern.text = getString(R.string.pattern_configure_pattern) - binding.explanationPattern.visibility = View.VISIBLE + binding.patternHeader.text = getString(R.string.pattern_configure_pattern) + binding.patternExplanation.visibility = View.VISIBLE if (intent.extras?.getBoolean(EXTRAS_LOCK_ENFORCED) == true) { supportActionBar?.setDisplayHomeAsUpEnabled(false) } else { @@ -136,9 +136,9 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { /** * This block is executed when the user is removing the pattern lock (i.e disabling the pattern lock) */ - binding.headerPattern.text = getString(R.string.pattern_remove_pattern) - binding.explanationPattern.text = getString(R.string.pattern_no_longer_required) - binding.explanationPattern.visibility = View.VISIBLE + binding.patternHeader.text = getString(R.string.pattern_remove_pattern) + binding.patternExplanation.text = getString(R.string.pattern_no_longer_required) + binding.patternExplanation.visibility = View.VISIBLE supportActionBar?.setDisplayHomeAsUpEnabled(true) } else -> { @@ -223,7 +223,7 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { private fun handleActionCheck() { if (patternViewModel.checkPatternIsValid(patternValue)) { - binding.errorPattern.visibility = View.INVISIBLE + binding.patternError.visibility = View.INVISIBLE val preferencesProvider = OCSharedPreferencesProvider(applicationContext) preferencesProvider.putLong(PREFERENCE_LAST_UNLOCK_TIMESTAMP, SystemClock.elapsedRealtime()) PatternManager.onActivityStopped(this) @@ -241,7 +241,7 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { patternViewModel.removePattern() val result = Intent() setResult(RESULT_OK, result) - binding.errorPattern.visibility = View.INVISIBLE + binding.patternError.visibility = View.INVISIBLE notifyDocumentsProviderRoots(applicationContext) finish() } else { @@ -254,7 +254,7 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { private fun handleActionRequestWithResult() { if (!confirmingPattern) { - binding.errorPattern.visibility = View.INVISIBLE + binding.patternError.visibility = View.INVISIBLE requestPatternConfirmation() } else if (confirmPattern()) { savePatternAndExit() @@ -271,10 +271,10 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { explanationVisibility: Int ) { patternValue = null - binding.errorPattern.setText(errorMessage) - binding.errorPattern.visibility = View.VISIBLE - binding.headerPattern.setText(headerMessage) - binding.explanationPattern.visibility = explanationVisibility + binding.patternError.setText(errorMessage) + binding.patternError.visibility = View.VISIBLE + binding.patternHeader.setText(headerMessage) + binding.patternExplanation.visibility = explanationVisibility } /** @@ -282,8 +282,8 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { */ private fun requestPatternConfirmation() { binding.patternLockView.clearPattern() - binding.headerPattern.setText(R.string.pattern_reenter_pattern) - binding.explanationPattern.visibility = View.INVISIBLE + binding.patternHeader.setText(R.string.pattern_reenter_pattern) + binding.patternExplanation.visibility = View.INVISIBLE confirmingPattern = true } @@ -309,8 +309,8 @@ class PatternActivity : AppCompatActivity(), EnableBiometrics { outState.apply { putBoolean(KEY_CONFIRMING_PATTERN, confirmingPattern) putString(KEY_PATTERN_STRING, patternValue) - putString(PATTERN_HEADER_VIEW_TEXT, binding.headerPattern.text.toString()) - putBoolean(PATTERN_EXP_VIEW_STATE, binding.explanationPattern.isVisible) + putString(PATTERN_HEADER_VIEW_TEXT, binding.patternHeader.text.toString()) + putBoolean(PATTERN_EXP_VIEW_STATE, binding.patternExplanation.isVisible) } } diff --git a/owncloudApp/src/main/res/layout-land/passcode_lock_activity.xml b/owncloudApp/src/main/res/layout-land/passcode_lock_activity.xml new file mode 100644 index 00000000000..0a11ace7381 --- /dev/null +++ b/owncloudApp/src/main/res/layout-land/passcode_lock_activity.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/owncloudApp/src/main/res/layout-land/pattern_lock_activity.xml b/owncloudApp/src/main/res/layout-land/pattern_lock_activity.xml new file mode 100644 index 00000000000..8b0e0a4c65a --- /dev/null +++ b/owncloudApp/src/main/res/layout-land/pattern_lock_activity.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/owncloudApp/src/main/res/layout-w600dp/passcodelock.xml b/owncloudApp/src/main/res/layout-sw600dp/passcode_lock_activity.xml similarity index 80% rename from owncloudApp/src/main/res/layout-w600dp/passcodelock.xml rename to owncloudApp/src/main/res/layout-sw600dp/passcode_lock_activity.xml index 24d517ad060..9429c81f805 100644 --- a/owncloudApp/src/main/res/layout-w600dp/passcodelock.xml +++ b/owncloudApp/src/main/res/layout-sw600dp/passcode_lock_activity.xml @@ -2,7 +2,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2020 ownCloud GmbH. + Copyright (C) 2026 ownCloud GmbH. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 2, @@ -18,21 +18,21 @@ --> + app:layout_constraintTop_toBottomOf="@id/passcode_header" /> + app:layout_constraintTop_toBottomOf="@id/passcode_explanation"> - + + app:layout_constraintTop_toBottomOf="@id/passcode_value" /> + app:layout_constraintTop_toBottomOf="@id/passcode_error" /> + + + + + + + + + + + + + + + + + + + + + + + diff --git a/owncloudApp/src/main/res/layout/passcodelock.xml b/owncloudApp/src/main/res/layout/passcode_lock_activity.xml similarity index 82% rename from owncloudApp/src/main/res/layout/passcodelock.xml rename to owncloudApp/src/main/res/layout/passcode_lock_activity.xml index 12f4a28fc65..9a2113774e6 100644 --- a/owncloudApp/src/main/res/layout/passcodelock.xml +++ b/owncloudApp/src/main/res/layout/passcode_lock_activity.xml @@ -2,7 +2,7 @@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski - Copyright (C) 2020 ownCloud GmbH. + Copyright (C) 2026 ownCloud GmbH. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 2, @@ -18,7 +18,7 @@ --> + app:layout_constraintTop_toBottomOf="@id/passcode_header" /> - + + app:layout_constraintTop_toBottomOf="@id/passcode_value" /> + app:layout_constraintTop_toBottomOf="@id/passcode_error" />