From ae80344da163aed24743e720c8a38af4b304e0b6 Mon Sep 17 00:00:00 2001 From: Vibhor Goel Date: Fri, 26 Jun 2026 15:51:01 +0530 Subject: [PATCH 1/6] Fix right-edge drag bounds gap on first scenario launch The first ever scenario created or opened had a small margin of unboundable area specifically on the right edge. After closing the scenario overlay and reopening it, or during subsequent runs, the dead area disappeared. This first-run bug has been present since 1.5.0 but was never caught. --- .../common/OverlayMenuResizeController.kt | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/core/common/overlays/src/main/java/com/buzbuz/smartautoclicker/core/common/overlays/menu/implementation/common/OverlayMenuResizeController.kt b/core/common/overlays/src/main/java/com/buzbuz/smartautoclicker/core/common/overlays/menu/implementation/common/OverlayMenuResizeController.kt index 7c6972eaa..f7789e956 100644 --- a/core/common/overlays/src/main/java/com/buzbuz/smartautoclicker/core/common/overlays/menu/implementation/common/OverlayMenuResizeController.kt +++ b/core/common/overlays/src/main/java/com/buzbuz/smartautoclicker/core/common/overlays/menu/implementation/common/OverlayMenuResizeController.kt @@ -136,21 +136,30 @@ internal class OverlayMenuResizeController( val width = if (firstChild == null || firstChild.id == resizedContainer.id) { resizedContainer.width } else { - firstChild.children.fold(0) { acc, child -> - acc + ( - if (child.isGone) 0 - else child.width + child.marginStart + child.marginEnd - ) - } + firstChild.visibleHorizontalContentSpan() } return Size(width, height) } } +private fun ViewGroup.visibleHorizontalContentSpan(): Int { + var leftBound = Int.MAX_VALUE + var rightBound = Int.MIN_VALUE + + children + .filterNot { it.isGone } + .forEach { child -> + leftBound = minOf(leftBound, child.left - child.marginStart) + rightBound = maxOf(rightBound, child.right + child.marginEnd) + } + + return if (leftBound == Int.MAX_VALUE) 0 else rightBound - leftBound +} + private data class OverlayTransition( val viewId: Int, val transitionType: Int, ) -private const val TAG = "OverlayMenuResizeController" \ No newline at end of file +private const val TAG = "OverlayMenuResizeController" From e53799acb8831965dc9bef061ab01ca1fabba151 Mon Sep 17 00:00:00 2001 From: Vibhor Goel Date: Sat, 27 Jun 2026 09:53:31 +0530 Subject: [PATCH 2/6] [#926] Display decimal values without redundant trailing zeros --- .../bindings/ItemScreenConditionBindingExt.kt | 3 +- .../IncludeCounterSelectionBindingExt.kt | 5 +- ...cludeStaticOrCounterSelectionBindingExt.kt | 5 +- .../ui/common/formatters/NumberFormatter.kt | 38 ++++++++++ .../common/formatters/OperationsFormatter.kt | 4 +- .../ui/common/model/action/UiChangeCounter.kt | 5 +- .../model/condition/UiTriggerCondition.kt | 5 +- .../counter/UiStaticOrCounterSelection.kt | 3 +- .../brief/ScreenConditionsBriefViewModel.kt | 6 +- .../counter/config/CountersConfigAdapter.kt | 4 +- .../counter/config/CountersConfigViewModel.kt | 9 ++- .../counter/creation/CounterCreationDialog.kt | 4 +- .../selection/CounterSelectionViewModel.kt | 3 +- .../scenario/config/ScenarioConfigContent.kt | 5 +- .../src/main/res/values-ar/strings.xml | 6 +- .../src/main/res/values-es/strings.xml | 6 +- .../src/main/res/values-fr/strings.xml | 6 +- .../src/main/res/values-it/strings.xml | 6 +- .../src/main/res/values-ja/strings.xml | 6 +- .../src/main/res/values-pt-rBR/strings.xml | 6 +- .../src/main/res/values-ru/strings.xml | 6 +- .../src/main/res/values-uk/strings.xml | 6 +- .../src/main/res/values-zh-rCN/strings.xml | 6 +- .../src/main/res/values-zh-rTW/strings.xml | 6 +- .../src/main/res/values/strings.xml | 6 +- .../common/formatters/NumberFormatterTests.kt | 72 +++++++++++++++++++ .../DebugConditionContentViewModel.kt | 15 +++- .../counter/adapter/CounterStateViewHolder.kt | 14 ++-- .../src/main/res/values/strings.xml | 4 +- .../list/adapter/ScenarioEventsAdapter.kt | 5 +- 30 files changed, 210 insertions(+), 65 deletions(-) create mode 100644 feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/NumberFormatter.kt create mode 100644 feature/smart-config/src/test/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/NumberFormatterTests.kt diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/ItemScreenConditionBindingExt.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/ItemScreenConditionBindingExt.kt index bd8caceec..8b81a4795 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/ItemScreenConditionBindingExt.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/ItemScreenConditionBindingExt.kt @@ -28,6 +28,7 @@ import com.buzbuz.smartautoclicker.feature.smart.config.databinding.IncludeScree import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.model.condition.UiScreenCondition import com.buzbuz.smartautoclicker.core.ui.utils.setColorIndicatorDrawable import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toEffectDescription +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString import kotlinx.coroutines.Job @@ -79,7 +80,7 @@ fun IncludeScreenConditionCardBinding.bind( conditionText.visibility = View.VISIBLE conditionText.text = condition.comparisonOperation - .toEffectDescription(root.context, operand = condition.counterValue.value.toString()) + .toEffectDescription(root.context, operand = condition.counterValue.toNaturalDisplayString()) null } diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/counter/IncludeCounterSelectionBindingExt.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/counter/IncludeCounterSelectionBindingExt.kt index 0b46a90f1..f21beae19 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/counter/IncludeCounterSelectionBindingExt.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/counter/IncludeCounterSelectionBindingExt.kt @@ -19,6 +19,7 @@ package com.buzbuz.smartautoclicker.feature.smart.config.ui.common.bindings.coun import com.buzbuz.smartautoclicker.core.base.extensions.setLeftCompoundDrawable import com.buzbuz.smartautoclicker.feature.smart.config.R import com.buzbuz.smartautoclicker.feature.smart.config.databinding.IncludeCounterSelectionBinding +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.model.counter.UiStaticOrCounterSelection import androidx.appcompat.R as AppCompatR @@ -40,8 +41,8 @@ fun IncludeCounterSelectionBinding.setCounter(uiState: UiStaticOrCounterSelectio title.setLeftCompoundDrawable(null) description.text = root.context.getString( R.string.field_counter_selection_desc, - uiState.counter.defaultValue, + uiState.counter.defaultValue.toNaturalDisplayString(maxFractionDigits = 2), ) description.setTextColor(MaterialColors.getColor(root, MaterialR.attr.colorOnSurfaceVariant)) } -} \ No newline at end of file +} diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/counter/IncludeStaticOrCounterSelectionBindingExt.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/counter/IncludeStaticOrCounterSelectionBindingExt.kt index ca9fe4be6..5e07b577d 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/counter/IncludeStaticOrCounterSelectionBindingExt.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/bindings/counter/IncludeStaticOrCounterSelectionBindingExt.kt @@ -30,6 +30,7 @@ import com.buzbuz.smartautoclicker.core.ui.bindings.fields.setText import com.buzbuz.smartautoclicker.core.ui.utils.NumberInputFilter import com.buzbuz.smartautoclicker.feature.smart.config.R import com.buzbuz.smartautoclicker.feature.smart.config.databinding.IncludeStaticOrCounterSelectionBinding +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.model.counter.UiOperandType import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.model.counter.UiCounterOperatorDropdownItem import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.model.counter.UiStaticOrCounterSelection @@ -104,9 +105,9 @@ fun IncludeStaticOrCounterSelectionBinding.setValueInfo(uiState: UiStaticOrCount counterValueLayout.root.visibility = View.GONE staticValueLayout.setText( - uiState.value.toString(), + uiState.value.toNaturalDisplayString(), InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL, ) } } -} \ No newline at end of file +} diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/NumberFormatter.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/NumberFormatter.kt new file mode 100644 index 000000000..d5fb47f8a --- /dev/null +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/NumberFormatter.kt @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2026 Kevin Buzeau + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters + +import com.buzbuz.smartautoclicker.core.domain.model.counter.CounterOperationValue + +import java.math.BigDecimal +import java.math.RoundingMode + +fun Double.toNaturalDisplayString(maxFractionDigits: Int? = null): String { + if (!isFinite()) return toString() + + val value = maxFractionDigits + ?.let { BigDecimal.valueOf(this).setScale(it, RoundingMode.HALF_UP) } + ?: BigDecimal.valueOf(this) + + return value.stripTrailingZeros().toPlainString() +} + +fun CounterOperationValue.toNaturalDisplayString(): String = + when (this) { + is CounterOperationValue.Counter -> value + is CounterOperationValue.Number -> value.toNaturalDisplayString() + } diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/OperationsFormatter.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/OperationsFormatter.kt index 78f2701e5..d1b1c3e87 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/OperationsFormatter.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/OperationsFormatter.kt @@ -90,6 +90,6 @@ internal fun CounterOperationValue.toEffectDescription(context: Context, operati is CounterOperationValue.Number -> context.getString( R.string.message_number_condition_static_value_desc, context.getString(operation.toFullNameRes()), - value.toString(), + value.toNaturalDisplayString(), ) - } \ No newline at end of file + } diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/action/UiChangeCounter.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/action/UiChangeCounter.kt index e93a0b93b..4490e5f0b 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/action/UiChangeCounter.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/action/UiChangeCounter.kt @@ -20,6 +20,7 @@ import android.content.Context import androidx.annotation.DrawableRes import com.buzbuz.smartautoclicker.core.domain.model.action.ChangeCounter import com.buzbuz.smartautoclicker.feature.smart.config.R +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString @DrawableRes @@ -36,5 +37,5 @@ internal fun ChangeCounter.getDescription(context: Context, inError: Boolean): S ChangeCounter.OperationType.MINUS -> "-" ChangeCounter.OperationType.SET -> "=" }, - operationValue.value.toString(), - ) \ No newline at end of file + operationValue.toNaturalDisplayString(), + ) diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/condition/UiTriggerCondition.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/condition/UiTriggerCondition.kt index 70bd9410d..7cfba9781 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/condition/UiTriggerCondition.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/condition/UiTriggerCondition.kt @@ -23,6 +23,7 @@ import com.buzbuz.smartautoclicker.core.domain.model.condition.TriggerCondition import com.buzbuz.smartautoclicker.core.domain.model.counter.ComparisonOperation.* import com.buzbuz.smartautoclicker.core.ui.utils.formatDuration import com.buzbuz.smartautoclicker.feature.smart.config.R +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString data class UiTriggerCondition( @@ -52,7 +53,7 @@ private fun TriggerCondition.getTriggerConditionDescription(context: Context): S R.string.item_counter_reached_details, counterName, getComparisonOperationDisplayName(context), - counterValue.value.toString(), + counterValue.toNaturalDisplayString(), ) is TriggerCondition.OnTimerReached -> context.getString( @@ -76,4 +77,4 @@ private fun TriggerCondition.OnBroadcastReceived.toBroadcastActionDisplayName(): return if (lastDotIndex != -1 && lastDotIndex != intentAction.lastIndex) intentAction.substring(lastDotIndex + 1) else intentAction -} \ No newline at end of file +} diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/counter/UiStaticOrCounterSelection.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/counter/UiStaticOrCounterSelection.kt index 9c4f6552b..908b6eba2 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/counter/UiStaticOrCounterSelection.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/model/counter/UiStaticOrCounterSelection.kt @@ -17,6 +17,7 @@ package com.buzbuz.smartautoclicker.feature.smart.config.ui.common.model.counter import com.buzbuz.smartautoclicker.core.domain.model.counter.Counter +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString sealed class UiStaticOrCounterSelection { data class StaticValue(val value: Double): UiStaticOrCounterSelection() @@ -31,6 +32,6 @@ enum class UiOperandType { fun UiStaticOrCounterSelection.toDisplayValue(): String = when (this) { is UiStaticOrCounterSelection.CounterValue -> counter?.counterName ?: "?" - is UiStaticOrCounterSelection.StaticValue -> value.toString() + is UiStaticOrCounterSelection.StaticValue -> value.toNaturalDisplayString() } diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/condition/screen/brief/ScreenConditionsBriefViewModel.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/condition/screen/brief/ScreenConditionsBriefViewModel.kt index 1d0d45354..ca4e72828 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/condition/screen/brief/ScreenConditionsBriefViewModel.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/condition/screen/brief/ScreenConditionsBriefViewModel.kt @@ -50,6 +50,7 @@ import com.buzbuz.smartautoclicker.core.ui.views.itembrief.renderers.TextConditi import com.buzbuz.smartautoclicker.feature.smart.config.domain.EditionRepository import com.buzbuz.smartautoclicker.feature.smart.config.domain.model.EditedListState import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toEffectDescription +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.model.condition.toUiScreenCondition import dagger.hilt.android.qualifiers.ApplicationContext @@ -263,6 +264,9 @@ private fun ScreenCondition.Text.toTextItemDescription(): TextConditionDescripti private fun ScreenCondition.Number.toTextItemDescription(context: Context): TextConditionDescription = TextConditionDescription( - conditionText = comparisonOperation.toEffectDescription(context, operand = counterValue.value.toString()), + conditionText = comparisonOperation.toEffectDescription( + context = context, + operand = counterValue.toNaturalDisplayString(), + ), conditionDetectionArea = detectionArea, ) diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/config/CountersConfigAdapter.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/config/CountersConfigAdapter.kt index 722f3c117..718e66384 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/config/CountersConfigAdapter.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/config/CountersConfigAdapter.kt @@ -28,9 +28,9 @@ import com.buzbuz.smartautoclicker.core.ui.bindings.fields.setOnTextChangedListe import com.buzbuz.smartautoclicker.core.ui.bindings.fields.setText import com.buzbuz.smartautoclicker.feature.smart.config.R import com.buzbuz.smartautoclicker.feature.smart.config.databinding.ItemCounterConfigBinding +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString import com.google.android.material.textfield.TextInputLayout -import java.util.Locale /** * Adapter for the list of counters in the configuration. @@ -132,7 +132,7 @@ class CountersConfigViewHolder( readByButton.visibility = View.VISIBLE deleteButton.visibility = View.VISIBLE - val startingValueText = String.format(Locale.getDefault(), "%s", newItem.startingValue) + val startingValueText = newItem.startingValue.toNaturalDisplayString() layoutStartingValue.setText(startingValueText, InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL) } else { buttonExpandCollapse.setIconResource(R.drawable.ic_chevron_down) diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/config/CountersConfigViewModel.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/config/CountersConfigViewModel.kt index 062ee1218..e9f87f769 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/config/CountersConfigViewModel.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/config/CountersConfigViewModel.kt @@ -28,6 +28,7 @@ import com.buzbuz.smartautoclicker.feature.smart.config.domain.usecase.counter.G import com.buzbuz.smartautoclicker.feature.smart.config.domain.usecase.counter.model.CounterReference import com.buzbuz.smartautoclicker.feature.smart.config.domain.usecase.counter.GetCounterWriteReferencesUseCase import com.buzbuz.smartautoclicker.feature.smart.config.domain.usecase.counter.ReplaceCounterUseCase +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString import dagger.hilt.android.qualifiers.ApplicationContext @@ -171,8 +172,10 @@ private fun Context.getDescription(referencesCount: Int, isExpanded: Boolean, st if (referencesCount == 0) getString(R.string.item_counter_desc_expanded_no_reference) else getString(R.string.item_counter_desc_expanded_referenced, referencesCount) } else { - if (referencesCount == 0) getString(R.string.item_counter_desc_collapsed_no_reference, startingValue) - else getString(R.string.item_counter_desc_collapsed_referenced, referencesCount, startingValue) + val startingValueText = startingValue.toNaturalDisplayString(maxFractionDigits = 2) + + if (referencesCount == 0) getString(R.string.item_counter_desc_collapsed_no_reference, startingValueText) + else getString(R.string.item_counter_desc_collapsed_referenced, referencesCount, startingValueText) } private fun Context.getSetByButtonText(actionsCount: Int): String = @@ -185,4 +188,4 @@ private fun Context.getReadByButtonText(conditionsCount: Int): String = private fun Context.getDeleteButtonText(referencesCount: Int): String = if (referencesCount == 0) getString(R.string.button_text_counter_delete) - else getString(R.string.button_text_counter_delete_and_replace) \ No newline at end of file + else getString(R.string.button_text_counter_delete_and_replace) diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/creation/CounterCreationDialog.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/creation/CounterCreationDialog.kt index d2ae4d2c1..2fde14eb6 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/creation/CounterCreationDialog.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/creation/CounterCreationDialog.kt @@ -69,7 +69,7 @@ class CounterCreationDialog : OverlayDialog(R.style.ScenarioConfigTheme) { fieldStartingValue.root.hint = context.getString(R.string.field_new_counter_starting_value) fieldStartingValue.textField.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL - fieldStartingValue.textField.setText("0.0") + fieldStartingValue.textField.setText("0") fieldStartingValue.textField.doAfterTextChanged { viewModel.setStartingValue(it.toString().toDoubleOrNull() ?: 0.0) } @@ -97,4 +97,4 @@ class CounterCreationDialog : OverlayDialog(R.style.ScenarioConfigTheme) { ) } } -} \ No newline at end of file +} diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/selection/CounterSelectionViewModel.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/selection/CounterSelectionViewModel.kt index a21f853ee..d573b12a4 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/selection/CounterSelectionViewModel.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/counter/selection/CounterSelectionViewModel.kt @@ -21,6 +21,7 @@ import androidx.lifecycle.ViewModel import com.buzbuz.smartautoclicker.feature.smart.config.R import com.buzbuz.smartautoclicker.feature.smart.config.domain.EditionRepository +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.Flow @@ -39,7 +40,7 @@ class CounterSelectionViewModel @Inject constructor( counterName = counter.counterName, counterStartingValueDesc = context.getString( R.string.field_counter_selection_desc, - counter.defaultValue, + counter.defaultValue.toNaturalDisplayString(maxFractionDigits = 2), ) ) }.sortedBy { counter -> counter.counterName } diff --git a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/scenario/config/ScenarioConfigContent.kt b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/scenario/config/ScenarioConfigContent.kt index 3dfa07cb1..94d052073 100644 --- a/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/scenario/config/ScenarioConfigContent.kt +++ b/feature/smart-config/src/main/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/scenario/config/ScenarioConfigContent.kt @@ -43,6 +43,7 @@ import com.buzbuz.smartautoclicker.core.ui.utils.MinMaxDoubleInputFilter import com.buzbuz.smartautoclicker.feature.smart.config.R import com.buzbuz.smartautoclicker.feature.smart.config.databinding.ContentScenarioConfigBinding import com.buzbuz.smartautoclicker.feature.smart.config.di.ScenarioConfigViewModelsEntryPoint +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString import com.google.android.material.textfield.TextInputLayout import kotlinx.coroutines.launch @@ -157,7 +158,7 @@ class ScenarioConfigContent(appContext: Context) : NavBarDialogContent(appContex editFpsLimit.textLayout.isEnabled = state.isEnabled if (state.isEnabled) { editFpsLimit.textField.filters = arrayOf(MinMaxDoubleInputFilter(min = 0.0, max = state.maxValue)) - editFpsLimit.setText(state.value.toString(), InputType.TYPE_NUMBER_FLAG_DECIMAL) + editFpsLimit.setText(state.value.toNaturalDisplayString(), InputType.TYPE_NUMBER_FLAG_DECIMAL) } else { editFpsLimit.textField.filters = emptyArray() editFpsLimit.setText(context.getString(R.string.field_scenario_fps_limit_disable_rate)) @@ -181,4 +182,4 @@ class ScenarioConfigContent(appContext: Context) : NavBarDialogContent(appContex } } } -} \ No newline at end of file +} diff --git a/feature/smart-config/src/main/res/values-ar/strings.xml b/feature/smart-config/src/main/res/values-ar/strings.xml index 6d20e6e40..e101ecd0c 100644 --- a/feature/smart-config/src/main/res/values-ar/strings.xml +++ b/feature/smart-config/src/main/res/values-ar/strings.xml @@ -454,8 +454,8 @@ العدادات لا يوجد عداد محدد خزن العداد قيمة رقمية يمكن تغييرها أو التحقق منها أو استخدامها في الإجراءات أو الشروط الخاصة بك - هذا العداد غير مستخدم. (%1$.2f) - يُشار إلى هذا العداد %1$d مرة. (%2$.2f) + هذا العداد غير مستخدم. (%1$s) + يُشار إلى هذا العداد %1$d مرة. (%2$s) هذا العداد غير مستخدم. يُشار إلى هذا العداد %1$d مرة. القيمة الابتدائية @@ -470,7 +470,7 @@ القيمة الابتدائية اسم العداد هذا موجود بالفعل لم يتم اختيار عداد - القيمة الابتدائية: %1$.2f + القيمة الابتدائية: %1$s انقر هنا لاختيار عداد حل المشكلات diff --git a/feature/smart-config/src/main/res/values-es/strings.xml b/feature/smart-config/src/main/res/values-es/strings.xml index 8db508884..549d5d70f 100644 --- a/feature/smart-config/src/main/res/values-es/strings.xml +++ b/feature/smart-config/src/main/res/values-es/strings.xml @@ -454,8 +454,8 @@ Contadores No hay contadores definidos Un contador almacena un valor numérico que se puede modificar, verificar o utilizar en tus acciones o condiciones - Este contador no se usa. (%1$.2f) - Este contador se referencia %1$d veces. (%2$.2f) + Este contador no se usa. (%1$s) + Este contador se referencia %1$d veces. (%2$s) Este contador no se usa. Este contador se referencia %1$d veces. Valor inicial @@ -470,7 +470,7 @@ Valor inicial Este nombre de contador ya existe Ningún contador seleccionado - Valor inicial: %1$.2f + Valor inicial: %1$s Toca aquí para seleccionar un contador Resolver problemas diff --git a/feature/smart-config/src/main/res/values-fr/strings.xml b/feature/smart-config/src/main/res/values-fr/strings.xml index dc529c0a8..4db1fc114 100644 --- a/feature/smart-config/src/main/res/values-fr/strings.xml +++ b/feature/smart-config/src/main/res/values-fr/strings.xml @@ -432,8 +432,8 @@ Compteurs Aucun compteur défini Un compteur stocke une valeur numérique qui peut être modifiée, vérifiée ou utilisée dans vos actions ou conditions - Ce compteur n\'est pas utilisé. (%1$.2f) - Ce compteur est référencé %1$d fois. (%2$.2f) + Ce compteur n\'est pas utilisé. (%1$s) + Ce compteur est référencé %1$d fois. (%2$s) Ce compteur n\'est pas utilisé. Ce compteur est référencé %1$d fois. Valeur initiale @@ -448,7 +448,7 @@ Valeur initiale Ce nom de compteur existe déjà Aucun compteur sélectionné - Valeur initiale : %1$.2f + Valeur initiale : %1$s Cliquez ici pour sélectionner un compteur Résoudre les problèmes diff --git a/feature/smart-config/src/main/res/values-it/strings.xml b/feature/smart-config/src/main/res/values-it/strings.xml index 717ab83d7..9151832c4 100644 --- a/feature/smart-config/src/main/res/values-it/strings.xml +++ b/feature/smart-config/src/main/res/values-it/strings.xml @@ -432,8 +432,8 @@ %1$s = %1$s %2$s %3$s Contatori - Questo contatore non è utilizzato. (%1$.2f) - Questo contatore è referenziato %1$d volte. (%2$.2f) + Questo contatore non è utilizzato. (%1$s) + Questo contatore è referenziato %1$d volte. (%2$s) Questo contatore non è utilizzato. Questo contatore è referenziato %1$d volte. Valore iniziale @@ -448,7 +448,7 @@ Valore iniziale Questo nome di contatore esiste già Nessun contatore selezionato - Valore iniziale: %1$.2f + Valore iniziale: %1$s Clicca qui per selezionare un contatore Risolvi i problemi diff --git a/feature/smart-config/src/main/res/values-ja/strings.xml b/feature/smart-config/src/main/res/values-ja/strings.xml index 5825d8b35..a1eeb8fb0 100644 --- a/feature/smart-config/src/main/res/values-ja/strings.xml +++ b/feature/smart-config/src/main/res/values-ja/strings.xml @@ -293,8 +293,8 @@ カウンター カウンターが未定義です カウンターには数値が格納され、アクションや条件式内でその値を変更、検証、または使用することができます - このカウンターは未使用です。(%1$.2f) - このカウンターは %1$d 回参照されています。(%2$.2f) + このカウンターは未使用です。(%1$s) + このカウンターは %1$d 回参照されています。(%2$s) このカウンターは未使用です。 このカウンターは %1$d 回参照されています。 初期値 @@ -309,7 +309,7 @@ 初期値 このカウンター名はすでに存在します カウンターが選択されていません - 初期値: %1$.2f + 初期値: %1$s ここをクリックしてカウンターを選択 問題を解決 diff --git a/feature/smart-config/src/main/res/values-pt-rBR/strings.xml b/feature/smart-config/src/main/res/values-pt-rBR/strings.xml index e7f5343ec..44c5ffd36 100644 --- a/feature/smart-config/src/main/res/values-pt-rBR/strings.xml +++ b/feature/smart-config/src/main/res/values-pt-rBR/strings.xml @@ -450,8 +450,8 @@ Contadores Nenhum contador definido Um contador armazena um valor numérico que pode ser alterado, verificado ou utilizado nas suas ações ou condições - Este contador não está sendo usado. (%1$.2f) - Este contador é referenciado %1$d vezes. (%2$.2f) + Este contador não está sendo usado. (%1$s) + Este contador é referenciado %1$d vezes. (%2$s) Este contador não está sendo usado. Este contador é referenciado %1$d vezes. Valor inicial @@ -466,7 +466,7 @@ Valor inicial Este nome de contador já existe Nenhum contador selecionado - Valor inicial: %1$.2f + Valor inicial: %1$s Toque aqui para selecionar um contador Resolver problemas diff --git a/feature/smart-config/src/main/res/values-ru/strings.xml b/feature/smart-config/src/main/res/values-ru/strings.xml index 499b3cf45..c9e9997df 100644 --- a/feature/smart-config/src/main/res/values-ru/strings.xml +++ b/feature/smart-config/src/main/res/values-ru/strings.xml @@ -454,8 +454,8 @@ Счётчики Счётчики не определены Счетчик хранит числовое значение, которое можно изменять, проверять или использовать в действиях или условиях - Этот счётчик не используется. (%1$.2f) - На этот счётчик ссылаются %1$d раз. (%2$.2f) + Этот счётчик не используется. (%1$s) + На этот счётчик ссылаются %1$d раз. (%2$s) Этот счётчик не используется. На этот счётчик ссылаются %1$d раз. Начальное значение @@ -470,7 +470,7 @@ Начальное значение Этот счётчик уже существует Счётчик не выбран - Начальное значение: %1$.2f + Начальное значение: %1$s Нажмите здесь, чтобы выбрать счётчик Устранить проблемы diff --git a/feature/smart-config/src/main/res/values-uk/strings.xml b/feature/smart-config/src/main/res/values-uk/strings.xml index 323ead499..ebefa65d2 100644 --- a/feature/smart-config/src/main/res/values-uk/strings.xml +++ b/feature/smart-config/src/main/res/values-uk/strings.xml @@ -457,8 +457,8 @@ Лічильники Лічильники не визначені Лічильник зберігає числове значення, яке можна змінювати, перевіряти або використовувати у ваших діях чи умовах - Цей лічильник не використовується. (%1$.2f) - На цей лічильник посилаються %1$d разів. (%2$.2f) + Цей лічильник не використовується. (%1$s) + На цей лічильник посилаються %1$d разів. (%2$s) Цей лічильник не використовується. На цей лічильник посилаються %1$d разів. Початкове значення @@ -473,7 +473,7 @@ Початкове значення Цей лічильник вже існує Лічильник не вибраний - Початкове значення: %1$.2f + Початкове значення: %1$s Натисніть тут, щоб вибрати лічильник Вирішити проблеми diff --git a/feature/smart-config/src/main/res/values-zh-rCN/strings.xml b/feature/smart-config/src/main/res/values-zh-rCN/strings.xml index d74f22a58..3b64bfa37 100644 --- a/feature/smart-config/src/main/res/values-zh-rCN/strings.xml +++ b/feature/smart-config/src/main/res/values-zh-rCN/strings.xml @@ -429,8 +429,8 @@ 计数器 未定义计数器 计数器用于存储一个数值,该数值可在您的操作或条件中进行修改、验证或使用 - 此计数器未被使用。(%1$.2f) - 此计数器被引用了 %1$d 次。(%2$.2f) + 此计数器未被使用。(%1$s) + 此计数器被引用了 %1$d 次。(%2$s) 此计数器未被使用。 此计数器被引用了 %1$d 次。 初始值 @@ -445,7 +445,7 @@ 初始值 此计数器名称已存在 未选择计数器 - 初始值:%1$.2f + 初始值:%1$s 点击此处选择计数器 解决问题 diff --git a/feature/smart-config/src/main/res/values-zh-rTW/strings.xml b/feature/smart-config/src/main/res/values-zh-rTW/strings.xml index 82990e85c..3da03f85d 100644 --- a/feature/smart-config/src/main/res/values-zh-rTW/strings.xml +++ b/feature/smart-config/src/main/res/values-zh-rTW/strings.xml @@ -429,8 +429,8 @@ 計數器 未定義計數器 計數器用於儲存數值,該數值可在您的動作或條件中進行變更、驗證或使用 - 此計數器未被使用。(%1$.2f) - 此計數器被引用了 %1$d 次。(%2$.2f) + 此計數器未被使用。(%1$s) + 此計數器被引用了 %1$d 次。(%2$s) 此計數器未被使用。 此計數器被引用了 %1$d 次。 初始值 @@ -445,7 +445,7 @@ 初始值 此計數器名稱已存在 未選擇計數器 - 初始值:%1$.2f + 初始值:%1$s 點擊此處選擇計數器 解決問題 diff --git a/feature/smart-config/src/main/res/values/strings.xml b/feature/smart-config/src/main/res/values/strings.xml index 7b4eeb71a..82796c86b 100644 --- a/feature/smart-config/src/main/res/values/strings.xml +++ b/feature/smart-config/src/main/res/values/strings.xml @@ -500,8 +500,8 @@ No counter defined A Counter stores a numeric value that can be changed, verified or used in your Actions or Conditions - This counter is unused. (%1$.2f) - This counter is referenced %1$d times. (%2$.2f) + This counter is unused. (%1$s) + This counter is referenced %1$d times. (%2$s) This counter is unused. This counter is referenced %1$d times. @@ -521,7 +521,7 @@ This counter name already exists No counter selected - Starting value: %1$.2f + Starting value: %1$s Click here to select a counter diff --git a/feature/smart-config/src/test/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/NumberFormatterTests.kt b/feature/smart-config/src/test/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/NumberFormatterTests.kt new file mode 100644 index 000000000..8967b81ec --- /dev/null +++ b/feature/smart-config/src/test/java/com/buzbuz/smartautoclicker/feature/smart/config/ui/common/formatters/NumberFormatterTests.kt @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2026 Kevin Buzeau + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters + +import com.buzbuz.smartautoclicker.core.domain.model.counter.CounterOperationValue + +import org.junit.Assert.assertEquals +import org.junit.Test + +class NumberFormatterTests { + + @Test + fun wholeNumber_removesUselessDecimal() { + assertEquals("1", 1.0.toNaturalDisplayString()) + } + + @Test + fun zero_removesUselessDecimal() { + assertEquals("0", 0.0.toNaturalDisplayString()) + } + + @Test + fun negativeWholeNumber_removesUselessDecimal() { + assertEquals("-5", (-5.0).toNaturalDisplayString()) + } + + @Test + fun decimalValue_keepsMeaningfulDecimal() { + assertEquals("1.25", 1.25.toNaturalDisplayString()) + } + + @Test + fun trailingZeroDecimal_removesOnlyUselessZero() { + assertEquals("1.5", 1.50.toNaturalDisplayString()) + } + + @Test + fun longDecimal_keepsMeaningfulDecimals() { + assertEquals("1.234567", 1.234567.toNaturalDisplayString()) + } + + @Test + fun maxFractionDigits_keepsNaturalDisplayAfterRounding() { + assertEquals("1.23", 1.234.toNaturalDisplayString(maxFractionDigits = 2)) + assertEquals("1.2", 1.20.toNaturalDisplayString(maxFractionDigits = 2)) + assertEquals("1", 1.0.toNaturalDisplayString(maxFractionDigits = 2)) + } + + @Test + fun counterOperationNumber_formatsWrappedNumber() { + assertEquals("1.5", CounterOperationValue.Number(1.50).toNaturalDisplayString()) + } + + @Test + fun counterOperationCounter_keepsCounterName() { + assertEquals("Counter A", CounterOperationValue.Counter("Counter A").toNaturalDisplayString()) + } +} diff --git a/feature/smart-debugging/src/main/java/com/buzbuz/smartautoclicker/feature/smart/debugging/ui/dialog/report/details/condition/DebugConditionContentViewModel.kt b/feature/smart-debugging/src/main/java/com/buzbuz/smartautoclicker/feature/smart/debugging/ui/dialog/report/details/condition/DebugConditionContentViewModel.kt index acc594ec7..6d480817d 100644 --- a/feature/smart-debugging/src/main/java/com/buzbuz/smartautoclicker/feature/smart/debugging/ui/dialog/report/details/condition/DebugConditionContentViewModel.kt +++ b/feature/smart-debugging/src/main/java/com/buzbuz/smartautoclicker/feature/smart/debugging/ui/dialog/report/details/condition/DebugConditionContentViewModel.kt @@ -38,6 +38,7 @@ import com.buzbuz.smartautoclicker.core.domain.model.counter.ComparisonOperation import com.buzbuz.smartautoclicker.core.domain.model.counter.ComparisonOperation.GREATER_OR_EQUALS import com.buzbuz.smartautoclicker.core.domain.model.counter.ComparisonOperation.LOWER import com.buzbuz.smartautoclicker.core.domain.model.counter.ComparisonOperation.LOWER_OR_EQUALS +import com.buzbuz.smartautoclicker.core.domain.model.counter.CounterOperationValue import com.buzbuz.smartautoclicker.core.domain.model.event.Event import com.buzbuz.smartautoclicker.core.domain.model.event.ScreenEvent import com.buzbuz.smartautoclicker.core.domain.model.event.TriggerEvent @@ -60,6 +61,7 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import java.math.BigDecimal import javax.inject.Inject import kotlin.coroutines.cancellation.CancellationException @@ -187,7 +189,7 @@ class DebugConditionContentViewModel @Inject constructor( R.string.item_event_occurrence_details_trigger_desc_counter, counterName, comparisonOperation.getComparisonOperationDisplayName(context), - counterValue.value.toString(), + counterValue.toNaturalDisplayString(), ) is TriggerCondition.OnTimerReached -> context.getString( R.string.item_event_occurrence_details_trigger_desc_timer, @@ -231,4 +233,15 @@ class DebugConditionContentViewModel @Inject constructor( private fun Int.toMinimumConfidence(): Double = 100.00 - this + + private fun Double.toNaturalDisplayString(): String { + if (!isFinite()) return toString() + return BigDecimal.valueOf(this).stripTrailingZeros().toPlainString() + } + + private fun CounterOperationValue.toNaturalDisplayString(): String = + when (this) { + is CounterOperationValue.Counter -> value + is CounterOperationValue.Number -> value.toNaturalDisplayString() + } } diff --git a/feature/smart-debugging/src/main/java/com/buzbuz/smartautoclicker/feature/smart/debugging/ui/dialog/report/details/counter/adapter/CounterStateViewHolder.kt b/feature/smart-debugging/src/main/java/com/buzbuz/smartautoclicker/feature/smart/debugging/ui/dialog/report/details/counter/adapter/CounterStateViewHolder.kt index 803a8952c..4dbc6c38b 100644 --- a/feature/smart-debugging/src/main/java/com/buzbuz/smartautoclicker/feature/smart/debugging/ui/dialog/report/details/counter/adapter/CounterStateViewHolder.kt +++ b/feature/smart-debugging/src/main/java/com/buzbuz/smartautoclicker/feature/smart/debugging/ui/dialog/report/details/counter/adapter/CounterStateViewHolder.kt @@ -23,6 +23,7 @@ import androidx.recyclerview.widget.RecyclerView import com.buzbuz.smartautoclicker.feature.smart.debugging.R import com.buzbuz.smartautoclicker.feature.smart.debugging.databinding.ItemCounterStateBinding import com.buzbuz.smartautoclicker.feature.smart.debugging.ui.dialog.report.details.counter.CounterStateItem +import java.math.BigDecimal class CounterStateViewHolder private constructor( private val viewBinding: ItemCounterStateBinding, @@ -46,14 +47,19 @@ class CounterStateViewHolder private constructor( return if (oldValue == null) { context.getString( R.string.item_counter_state_value_same, - currentCounterValue, + currentCounterValue.toNaturalDisplayString(), ) } else { context.getString( R.string.item_counter_state_value_changed, - oldValue, - currentCounterValue, + oldValue.toNaturalDisplayString(), + currentCounterValue.toNaturalDisplayString(), ) } } -} \ No newline at end of file + + private fun Double.toNaturalDisplayString(): String { + if (!isFinite()) return toString() + return BigDecimal.valueOf(this).stripTrailingZeros().toPlainString() + } +} diff --git a/feature/smart-debugging/src/main/res/values/strings.xml b/feature/smart-debugging/src/main/res/values/strings.xml index 45e439cc2..c63a42c85 100644 --- a/feature/smart-debugging/src/main/res/values/strings.xml +++ b/feature/smart-debugging/src/main/res/values/strings.xml @@ -90,8 +90,8 @@ - DO NOT TRANSLATE. --> " » " - %1$f - %1$.2f » %2$.2f + %1$s + %1$s » %2$s \ No newline at end of file diff --git a/smartautoclicker/src/main/java/com/buzbuz/smartautoclicker/scenarios/list/adapter/ScenarioEventsAdapter.kt b/smartautoclicker/src/main/java/com/buzbuz/smartautoclicker/scenarios/list/adapter/ScenarioEventsAdapter.kt index d1c051753..62bb3ed3b 100644 --- a/smartautoclicker/src/main/java/com/buzbuz/smartautoclicker/scenarios/list/adapter/ScenarioEventsAdapter.kt +++ b/smartautoclicker/src/main/java/com/buzbuz/smartautoclicker/scenarios/list/adapter/ScenarioEventsAdapter.kt @@ -32,6 +32,7 @@ import com.buzbuz.smartautoclicker.core.domain.model.condition.ScreenCondition import com.buzbuz.smartautoclicker.core.ui.utils.setColorIndicatorDrawable import com.buzbuz.smartautoclicker.databinding.ItemEventCardBinding import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toEffectDescription +import com.buzbuz.smartautoclicker.feature.smart.config.ui.common.formatters.toNaturalDisplayString import com.buzbuz.smartautoclicker.scenarios.list.model.ScenarioListUiState.Item.ScenarioItem.Valid.Smart.EventItem import kotlinx.coroutines.Job @@ -109,7 +110,7 @@ class EventCardViewHolder( conditionText.visibility = View.VISIBLE conditionText.text = condition.comparisonOperation - .toEffectDescription(root.context, operand = condition.counterValue.value.toString()) + .toEffectDescription(root.context, operand = condition.counterValue.toNaturalDisplayString()) } is ScreenCondition.Text -> { @@ -134,4 +135,4 @@ class EventCardViewHolder( } ) } -} \ No newline at end of file +} From f6bd0421a43033e8e4efebf45407dd27802b10b8 Mon Sep 17 00:00:00 2001 From: Vibhor Goel Date: Tue, 30 Jun 2026 10:56:52 +0530 Subject: [PATCH 3/6] Ignore screen orientation when checking backup compatibility --- .../data/smart/SmartBackupDataSource.kt | 21 +++++++++- .../data/smart/SmartBackupDataSourceTests.kt | 39 +++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 feature/backup/src/test/java/com/buzbuz/smartautoclicker/feature/backup/data/smart/SmartBackupDataSourceTests.kt diff --git a/feature/backup/src/main/java/com/buzbuz/smartautoclicker/feature/backup/data/smart/SmartBackupDataSource.kt b/feature/backup/src/main/java/com/buzbuz/smartautoclicker/feature/backup/data/smart/SmartBackupDataSource.kt index 1131d2cea..d41ae4743 100644 --- a/feature/backup/src/main/java/com/buzbuz/smartautoclicker/feature/backup/data/smart/SmartBackupDataSource.kt +++ b/feature/backup/src/main/java/com/buzbuz/smartautoclicker/feature/backup/data/smart/SmartBackupDataSource.kt @@ -119,7 +119,12 @@ internal class SmartBackupDataSource( } if (!screenCompatWarning) { - screenCompatWarning = screenSize != Point(backup.screenWidth, backup.screenHeight) + screenCompatWarning = hasDifferentScreenSize( + currentWidth = screenSize.x, + currentHeight = screenSize.y, + backupWidth = backup.screenWidth, + backupHeight = backup.screenHeight, + ) } Log.i(TAG, "Smart scenario is valid, has warnings: $screenCompatWarning") @@ -157,4 +162,16 @@ internal class SmartBackupDataSource( } /** Tag for logs. */ -private const val TAG = "SmartBackupEngine" \ No newline at end of file +private const val TAG = "SmartBackupEngine" + +internal fun hasDifferentScreenSize( + currentWidth: Int, + currentHeight: Int, + backupWidth: Int, + backupHeight: Int, +): Boolean { + val sameOrientation = currentWidth == backupWidth && currentHeight == backupHeight + val rotatedOrientation = currentWidth == backupHeight && currentHeight == backupWidth + + return !sameOrientation && !rotatedOrientation +} diff --git a/feature/backup/src/test/java/com/buzbuz/smartautoclicker/feature/backup/data/smart/SmartBackupDataSourceTests.kt b/feature/backup/src/test/java/com/buzbuz/smartautoclicker/feature/backup/data/smart/SmartBackupDataSourceTests.kt new file mode 100644 index 000000000..08f958d0c --- /dev/null +++ b/feature/backup/src/test/java/com/buzbuz/smartautoclicker/feature/backup/data/smart/SmartBackupDataSourceTests.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2026 Kevin Buzeau + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.buzbuz.smartautoclicker.feature.backup.data.smart + +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test + +class SmartBackupDataSourceTests { + + @Test + fun sameScreenSize_sameOrientation_noWarning() { + assertFalse(hasDifferentScreenSize(1080, 2400, 1080, 2400)) + } + + @Test + fun sameScreenSize_differentOrientation_noWarning() { + assertFalse(hasDifferentScreenSize(1080, 2400, 2400, 1080)) + } + + @Test + fun differentScreenSize_warning() { + assertTrue(hasDifferentScreenSize(1080, 2400, 1440, 3200)) + } +} From 071eac9c7a4f6e1266ec05ce578373ceca5c5eec Mon Sep 17 00:00:00 2001 From: Vibhor Goel Date: Wed, 1 Jul 2026 13:16:24 +0530 Subject: [PATCH 4/6] Fix scenario stats database queries to use the correct foreign key columns --- .../smartautoclicker/core/dumb/data/database/DumbScenarioDao.kt | 2 +- .../buzbuz/smartautoclicker/core/database/dao/ScenarioDao.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/dumb/src/main/java/com/buzbuz/smartautoclicker/core/dumb/data/database/DumbScenarioDao.kt b/core/dumb/src/main/java/com/buzbuz/smartautoclicker/core/dumb/data/database/DumbScenarioDao.kt index ea04b2fd1..5faabb3e4 100644 --- a/core/dumb/src/main/java/com/buzbuz/smartautoclicker/core/dumb/data/database/DumbScenarioDao.kt +++ b/core/dumb/src/main/java/com/buzbuz/smartautoclicker/core/dumb/data/database/DumbScenarioDao.kt @@ -118,7 +118,7 @@ interface DumbScenarioDao { * * @return the scenario stats. */ - @Query("SELECT * FROM dumb_scenario_stats_table WHERE id=:scenarioId") + @Query("SELECT * FROM dumb_scenario_stats_table WHERE dumb_scenario_id=:scenarioId") suspend fun getScenarioStats(scenarioId: Long): DumbScenarioStatsEntity? /** diff --git a/core/smart/database/src/main/java/com/buzbuz/smartautoclicker/core/database/dao/ScenarioDao.kt b/core/smart/database/src/main/java/com/buzbuz/smartautoclicker/core/database/dao/ScenarioDao.kt index d806e7a7a..5d7af591c 100644 --- a/core/smart/database/src/main/java/com/buzbuz/smartautoclicker/core/database/dao/ScenarioDao.kt +++ b/core/smart/database/src/main/java/com/buzbuz/smartautoclicker/core/database/dao/ScenarioDao.kt @@ -103,7 +103,7 @@ interface ScenarioDao { * * @return the scenario stats. */ - @Query("SELECT * FROM $SCENARIO_USAGE_TABLE WHERE id=:scenarioId") + @Query("SELECT * FROM $SCENARIO_USAGE_TABLE WHERE scenario_id=:scenarioId") suspend fun getScenarioStats(scenarioId: Long): ScenarioStatsEntity? /** From 5479efeae8e5301b36e8625c0bf01be38fb91b8e Mon Sep 17 00:00:00 2001 From: Vibhor Goel Date: Fri, 3 Jul 2026 19:54:44 +0530 Subject: [PATCH 5/6] [#932] Use branded DontKillMyApp link for Klick'r --- .../common/quality/ui/AccessibilityTroubleshootingDialog.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/common/quality/src/main/java/com/buzbuz/smartautoclicker/core/common/quality/ui/AccessibilityTroubleshootingDialog.kt b/core/common/quality/src/main/java/com/buzbuz/smartautoclicker/core/common/quality/ui/AccessibilityTroubleshootingDialog.kt index 4b1c78638..110e496d7 100644 --- a/core/common/quality/src/main/java/com/buzbuz/smartautoclicker/core/common/quality/ui/AccessibilityTroubleshootingDialog.kt +++ b/core/common/quality/src/main/java/com/buzbuz/smartautoclicker/core/common/quality/ui/AccessibilityTroubleshootingDialog.kt @@ -58,6 +58,6 @@ class AccessibilityTroubleshootingDialog : DialogFragment() { } private fun showDontKillMyApp() { - context?.safeStartWebBrowserActivity("https://dontkillmyapp.com") + context?.safeStartWebBrowserActivity("https://dontkillmyapp.com?app=Klick%27r") } } \ No newline at end of file From 60295755294345a87975bba8e498756d293cda4f Mon Sep 17 00:00:00 2001 From: Vibhor Goel Date: Sat, 4 Jul 2026 12:10:05 +0530 Subject: [PATCH 6/6] Fix ZIP backup corruption on overwrite by forcing write truncation --- .../smartautoclicker/feature/backup/data/BackupEngine.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/feature/backup/src/main/java/com/buzbuz/smartautoclicker/feature/backup/data/BackupEngine.kt b/feature/backup/src/main/java/com/buzbuz/smartautoclicker/feature/backup/data/BackupEngine.kt index fd18a55e6..70b67c6ce 100644 --- a/feature/backup/src/main/java/com/buzbuz/smartautoclicker/feature/backup/data/BackupEngine.kt +++ b/feature/backup/src/main/java/com/buzbuz/smartautoclicker/feature/backup/data/BackupEngine.kt @@ -65,7 +65,7 @@ internal class BackupEngine(appDataDir: File, private val contentResolver: Conte // Create the zip file containing the scenarios and their events conditions. withContext(Dispatchers.IO) { try { - ZipOutputStream(contentResolver.openOutputStream(zipFileUri)).use { zipStream -> + ZipOutputStream(contentResolver.openOutputStream(zipFileUri, "wt")).use { zipStream -> dumbScenarios.forEach { dumbScenario -> Log.d(TAG, "Backup dumb scenario ${dumbScenario.scenario.id}") @@ -83,9 +83,9 @@ internal class BackupEngine(appDataDir: File, private val contentResolver: Conte currentProgress++ progress.onProgressChanged(currentProgress, smartScenarios.size) } - - progress.onCompleted(dumbScenarios, smartScenarios, 0, false) } + + progress.onCompleted(dumbScenarios, smartScenarios, 0, false) } catch (ioEx: IOException) { Log.e(TAG, "Error while creating backup archive.") progress.onError()