From 6fc9b5baf2b9f52fa70faf022a261ac60cc4af2d Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 09:55:11 +0200 Subject: [PATCH] simplify passcode delay translation Signed-off-by: alperozturk96 --- .../android/ui/activity/PassCodeActivity.kt | 46 +-------- .../ui/activity/PassCodeDelayFormatter.kt | 43 ++++++++ app/src/main/res/values/strings.xml | 25 ++--- .../ui/activity/PassCodeDelayFormatterTest.kt | 97 +++++++++++++++++++ 4 files changed, 154 insertions(+), 57 deletions(-) create mode 100644 app/src/main/java/com/owncloud/android/ui/activity/PassCodeDelayFormatter.kt create mode 100644 app/src/test/java/com/owncloud/android/ui/activity/PassCodeDelayFormatterTest.kt diff --git a/app/src/main/java/com/owncloud/android/ui/activity/PassCodeActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/PassCodeActivity.kt index e89b05ea0e6f..2618b3d63dda 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/PassCodeActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/PassCodeActivity.kt @@ -46,6 +46,7 @@ class PassCodeActivity : companion object { private val TAG = PassCodeActivity::class.java.simpleName + private const val ONE_SECOND_MS = 1000L private const val KEY_PASSCODE_DIGITS = "PASSCODE_DIGITS" private const val KEY_CONFIRMING_PASSCODE = "CONFIRMING_PASSCODE" const val ACTION_REQUEST_WITH_RESULT = "ACTION_REQUEST_WITH_RESULT" @@ -79,6 +80,8 @@ class PassCodeActivity : private var changed = true // to control that only one blocks jump private var delayInSeconds = 0 + private val delayFormatter by lazy { PassCodeDelayFormatter(resources) } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) delayInSeconds = preferences.passCodeDelay @@ -369,45 +372,6 @@ class PassCodeActivity : } } - @Suppress("MagicNumber") - private fun getExplanationText(timeInSecond: Int): String = when { - timeInSecond < 60 -> resources.getQuantityString( - R.plurals.delay_message, - timeInSecond, - timeInSecond - ) - - else -> { - val minutes = timeInSecond / 60 - val remainingSeconds = timeInSecond % 60 - - when { - remainingSeconds == 0 -> resources.getQuantityString( - R.plurals.delay_message_minutes, - minutes, - minutes - ) - - else -> { - val minuteText = resources.getQuantityString( - R.plurals.delay_message_minutes_part, - minutes, - minutes - ) - val secondText = resources.getQuantityString( - R.plurals.delay_message_seconds_part, - remainingSeconds, - remainingSeconds - ) - - val prefixText = "$minuteText $secondText" - getString(R.string.due_to_too_many_wrong_attempts, prefixText) - } - } - } - } - - @Suppress("MagicNumber") private fun showDelay() { val pinBruteForceCount = preferences.pinBruteForceDelay() if (pinBruteForceCount <= 0) { @@ -419,8 +383,8 @@ class PassCodeActivity : var counter = delayInSeconds lifecycleScope.launch(Dispatchers.Main) { while (counter != 0) { - binding.explanation.text = getExplanationText(counter) - delay(1000) + binding.explanation.text = delayFormatter.getExplanationText(counter) + delay(ONE_SECOND_MS) counter -= 1 } diff --git a/app/src/main/java/com/owncloud/android/ui/activity/PassCodeDelayFormatter.kt b/app/src/main/java/com/owncloud/android/ui/activity/PassCodeDelayFormatter.kt new file mode 100644 index 000000000000..6e65e7e97cd7 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/ui/activity/PassCodeDelayFormatter.kt @@ -0,0 +1,43 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +package com.owncloud.android.ui.activity + +import android.content.res.Resources +import com.owncloud.android.R + +class PassCodeDelayFormatter(private val resources: Resources) { + + fun getExplanationText(timeInSeconds: Int): String { + val minutes = timeInSeconds / SECONDS_PER_MINUTE + val remainingSeconds = timeInSeconds % SECONDS_PER_MINUTE + + return when { + timeInSeconds < SECONDS_PER_MINUTE -> resources.getQuantityString( + R.plurals.passcode_delay_seconds, + timeInSeconds, + timeInSeconds + ) + + remainingSeconds == 0 -> resources.getQuantityString( + R.plurals.passcode_delay_minutes, + minutes, + minutes + ) + + else -> resources.getQuantityString( + R.plurals.passcode_delay_minutes_seconds, + minutes, + minutes, + remainingSeconds + ) + } + } + + companion object { + const val SECONDS_PER_MINUTE = 60 + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 55a477218158..00afae5f6647 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1276,28 +1276,21 @@ The link to your %1$s web interface when you open it in the browser. - - Delayed %d second due to too many wrong attempts - Delayed %d seconds due to too many wrong attempts + + Try again in %d second due to too many wrong attempts + Try again in %d seconds due to too many wrong attempts - - Delayed %d minute due to too many wrong attempts - Delayed %d minutes due to too many wrong attempts + + Try again in %d minute due to too many wrong attempts + Try again in %d minutes due to too many wrong attempts - - Delayed %d minute - Delayed %d minutes + + Try again in %1$d minute and %2$d seconds due to too many wrong attempts + Try again in %1$d minutes and %2$d seconds due to too many wrong attempts - - %d second - %d seconds - - - %s due to too many wrong attempts - Create Please select one template diff --git a/app/src/test/java/com/owncloud/android/ui/activity/PassCodeDelayFormatterTest.kt b/app/src/test/java/com/owncloud/android/ui/activity/PassCodeDelayFormatterTest.kt new file mode 100644 index 000000000000..c2bc583aeeeb --- /dev/null +++ b/app/src/test/java/com/owncloud/android/ui/activity/PassCodeDelayFormatterTest.kt @@ -0,0 +1,97 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +package com.owncloud.android.ui.activity + +import android.content.res.Resources +import com.owncloud.android.R +import io.mockk.every +import io.mockk.mockk +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test + +class PassCodeDelayFormatterTest { + + private lateinit var resources: Resources + private lateinit var sut: PassCodeDelayFormatter + + @Before + fun setUp() { + resources = mockk() + sut = PassCodeDelayFormatter(resources) + } + + @Test + fun testGetExplanationTextWhenGivenOneSecondShouldReturnSingularSecondsString() { + val expected = "Try again in 1 second due to too many wrong attempts" + every { resources.getQuantityString(R.plurals.passcode_delay_seconds, 1, 1) } returns expected + + val result = sut.getExplanationText(1) + + assertEquals(expected, result) + } + + @Test + fun testGetExplanationTextWhenGivenFiftyNineSecondsShouldReturnPluralSecondsString() { + val expected = "Try again in 59 seconds due to too many wrong attempts" + every { resources.getQuantityString(R.plurals.passcode_delay_seconds, 59, 59) } returns expected + + val result = sut.getExplanationText(59) + + assertEquals(expected, result) + } + + @Test + fun testGetExplanationTextWhenGivenSixtySecondsShouldReturnSingularMinutesString() { + val expected = "Try again in 1 minute due to too many wrong attempts" + every { resources.getQuantityString(R.plurals.passcode_delay_minutes, 1, 1) } returns expected + + val result = sut.getExplanationText(60) + + assertEquals(expected, result) + } + + @Test + fun testGetExplanationTextWhenGivenOneHundredTwentySecondsShouldReturnPluralMinutesString() { + val expected = "Try again in 2 minutes due to too many wrong attempts" + every { resources.getQuantityString(R.plurals.passcode_delay_minutes, 2, 2) } returns expected + + val result = sut.getExplanationText(120) + + assertEquals(expected, result) + } + + @Test + fun testGetExplanationTextWhenGivenNinetySecondsShouldReturnMinutesAndSecondsString() { + val expected = "Try again in 1 minute and 30 seconds due to too many wrong attempts" + every { resources.getQuantityString(R.plurals.passcode_delay_minutes_seconds, 1, 1, 30) } returns expected + + val result = sut.getExplanationText(90) + + assertEquals(expected, result) + } + + @Test + fun testGetExplanationTextWhenGivenOneHundredFortyFiveSecondsShouldReturnMinutesAndSecondsString() { + val expected = "Try again in 2 minutes and 25 seconds due to too many wrong attempts" + every { resources.getQuantityString(R.plurals.passcode_delay_minutes_seconds, 2, 2, 25) } returns expected + + val result = sut.getExplanationText(145) + + assertEquals(expected, result) + } + + @Test + fun testGetExplanationTextWhenGivenThreeHundredSecondsShouldReturnFiveMinutesString() { + val expected = "Try again in 5 minutes due to too many wrong attempts" + every { resources.getQuantityString(R.plurals.passcode_delay_minutes, 5, 5) } returns expected + + val result = sut.getExplanationText(300) + + assertEquals(expected, result) + } +}