From 6626d7d0844dc20856f60ca950a77f1acf4614d1 Mon Sep 17 00:00:00 2001 From: iso53 <102249575+ISO53@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:56:08 +0300 Subject: [PATCH 1/2] Add high-precision mode for level meter Introduce a High Precision option to show more granular degree readings in the level meter. Adds UI entry and single-choice dialog in OptionsActivity that stores PreferenceConstants.HIGH_PRECISION in SharedPreferences. --- .../iso53/nothingcompass/OptionsActivity.java | 19 +++++++++++++++ .../fragment/InclinometerFragment.java | 4 ++++ .../preference/PreferenceConstants.java | 1 + .../preference/PreferenceStore.java | 24 +++++++++++++++++++ .../nothingcompass/view/LevelMeterView.java | 23 +++++++++++++++--- app/src/main/res/values/strings.xml | 3 +++ 6 files changed, 71 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/github/iso53/nothingcompass/OptionsActivity.java b/app/src/main/java/io/github/iso53/nothingcompass/OptionsActivity.java index ddd7efa..00d6ee7 100644 --- a/app/src/main/java/io/github/iso53/nothingcompass/OptionsActivity.java +++ b/app/src/main/java/io/github/iso53/nothingcompass/OptionsActivity.java @@ -69,6 +69,8 @@ private void setupRecyclerView() { v -> showThemeSelectionDialog())); items.add(new OptionItem(getString(R.string.item_haptic_feedback), null, R.drawable.ic_vibration, v -> showHapticFeedbackSelectionDialog())); + items.add(new OptionItem(getString(R.string.item_high_precision), null, + R.drawable.ic_settings, v -> showHighPrecisionSelectionDialog())); items.add(new OptionItem(getString(R.string.item_north_reference), null, R.drawable.ic_compass, v -> showNorthReferenceSelectionDialog())); @@ -152,6 +154,23 @@ private void showHapticFeedbackSelectionDialog() { }).show(); } + private void showHighPrecisionSelectionDialog() { + String[] options = {getString(R.string.high_precision_on), + getString(R.string.high_precision_off)}; + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + boolean currentHighPrecision = prefs.getBoolean(PreferenceConstants.HIGH_PRECISION, false); + + int checkedItem = currentHighPrecision ? 0 : 1; + + new MaterialAlertDialogBuilder(this).setTitle(R.string.item_high_precision) + .setSingleChoiceItems(options, checkedItem, (dialog, which) -> { + boolean enabled = (which == 0); + prefs.edit().putBoolean(PreferenceConstants.HIGH_PRECISION, enabled).apply(); + dialog.dismiss(); + }).show(); + } + private void openPlayStore() { String packageName = getPackageName(); try { diff --git a/app/src/main/java/io/github/iso53/nothingcompass/fragment/InclinometerFragment.java b/app/src/main/java/io/github/iso53/nothingcompass/fragment/InclinometerFragment.java index f16337e..9b90457 100644 --- a/app/src/main/java/io/github/iso53/nothingcompass/fragment/InclinometerFragment.java +++ b/app/src/main/java/io/github/iso53/nothingcompass/fragment/InclinometerFragment.java @@ -47,6 +47,10 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa levelMeterView.setHapticFeedbackEnabled(enabled); }); + preferenceStore.getHighPrecision().observe(getViewLifecycleOwner(), enabled -> { + levelMeterView.setHighPrecisionEnabled(enabled); + }); + // Initially show inclinometer, hide level meter inclinometerView.setAlpha(1f); inclinometerView.setIsActive(true); diff --git a/app/src/main/java/io/github/iso53/nothingcompass/preference/PreferenceConstants.java b/app/src/main/java/io/github/iso53/nothingcompass/preference/PreferenceConstants.java index 18c2419..8781755 100644 --- a/app/src/main/java/io/github/iso53/nothingcompass/preference/PreferenceConstants.java +++ b/app/src/main/java/io/github/iso53/nothingcompass/preference/PreferenceConstants.java @@ -9,4 +9,5 @@ private PreferenceConstants() { public static final String APP_LAUNCH_COUNT = "app_launch_count"; public static final String HAS_ASKED_FOR_REVIEW = "has_asked_for_review"; public static final String THEME = "theme"; + public static final String HIGH_PRECISION = "high_precision"; } diff --git a/app/src/main/java/io/github/iso53/nothingcompass/preference/PreferenceStore.java b/app/src/main/java/io/github/iso53/nothingcompass/preference/PreferenceStore.java index 0df843d..25e1a10 100644 --- a/app/src/main/java/io/github/iso53/nothingcompass/preference/PreferenceStore.java +++ b/app/src/main/java/io/github/iso53/nothingcompass/preference/PreferenceStore.java @@ -17,12 +17,14 @@ public class PreferenceStore { private final MutableLiveData trueNorth = new MutableLiveData<>(); private final MutableLiveData hapticFeedback = new MutableLiveData<>(); + private final MutableLiveData highPrecision = new MutableLiveData<>(); private final SharedPreferences sharedPreferences; private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener; private final Observer trueNorthObserver; private final Observer hapticFeedbackObserver; + private final Observer highPrecisionObserver; public PreferenceStore(@NonNull Context context, @NonNull Lifecycle lifecycle) { this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); @@ -37,6 +39,9 @@ public PreferenceStore(@NonNull Context context, @NonNull Lifecycle lifecycle) { case PreferenceConstants.HAPTIC_FEEDBACK: updateHapticFeedback(); break; + case PreferenceConstants.HIGH_PRECISION: + updateHighPrecision(); + break; } }; @@ -50,14 +55,21 @@ public PreferenceStore(@NonNull Context context, @NonNull Lifecycle lifecycle) { Log.d(TAG, "Persisted hapticFeedback: " + value); }; + this.highPrecisionObserver = value -> { + sharedPreferences.edit().putBoolean(PreferenceConstants.HIGH_PRECISION, value).apply(); + Log.d(TAG, "Persisted highPrecision: " + value); + }; + updateTrueNorth(); updateHapticFeedback(); + updateHighPrecision(); lifecycle.addObserver(new DefaultLifecycleObserver() { @Override public void onCreate(@NonNull LifecycleOwner owner) { trueNorth.observeForever(trueNorthObserver); hapticFeedback.observeForever(hapticFeedbackObserver); + highPrecision.observeForever(highPrecisionObserver); sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); } @@ -68,6 +80,7 @@ public void onDestroy(@NonNull LifecycleOwner owner) { trueNorth.removeObserver(trueNorthObserver); hapticFeedback.removeObserver(hapticFeedbackObserver); + highPrecision.removeObserver(highPrecisionObserver); } }); } @@ -80,6 +93,10 @@ public MutableLiveData getHapticFeedback() { return hapticFeedback; } + public MutableLiveData getHighPrecision() { + return highPrecision; + } + private void updateTrueNorth() { boolean storedValue = sharedPreferences.getBoolean(PreferenceConstants.TRUE_NORTH, false); if (!Boolean.valueOf(storedValue).equals(trueNorth.getValue())) { @@ -93,4 +110,11 @@ private void updateHapticFeedback() { hapticFeedback.setValue(storedValue); } } + + private void updateHighPrecision() { + boolean storedValue = sharedPreferences.getBoolean(PreferenceConstants.HIGH_PRECISION, false); + if (!Boolean.valueOf(storedValue).equals(highPrecision.getValue())) { + highPrecision.setValue(storedValue); + } + } } diff --git a/app/src/main/java/io/github/iso53/nothingcompass/view/LevelMeterView.java b/app/src/main/java/io/github/iso53/nothingcompass/view/LevelMeterView.java index 045e6e4..251b9de 100644 --- a/app/src/main/java/io/github/iso53/nothingcompass/view/LevelMeterView.java +++ b/app/src/main/java/io/github/iso53/nothingcompass/view/LevelMeterView.java @@ -49,6 +49,7 @@ public class LevelMeterView extends FrameLayout { private int lastVibrationDegree = 0; private boolean isActive = false; private boolean isHapticFeedbackEnabled = true; + private boolean isHighPrecisionEnabled = false; public LevelMeterView(Context c, AttributeSet a) { super(c, a); @@ -220,6 +221,11 @@ public void setHapticFeedbackEnabled(boolean enabled) { this.isHapticFeedbackEnabled = enabled; } + public void setHighPrecisionEnabled(boolean enabled) { + this.isHighPrecisionEnabled = enabled; + invalidate(); + } + private void performHapticFeedback() { Vibrator vibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); if (vibrator != null && vibrator.hasVibrator()) { @@ -249,13 +255,24 @@ private void updateOrientation() { } private void updateDegreeDisplay() { - int displayDegree = calculateDisplayDegree(); + float degreeValue = calculateDegreeValue(); + String displayDegree; + + if (isHighPrecisionEnabled) { + if (Math.abs(degreeValue) < 0.005f) { + degreeValue = 0f; + } + displayDegree = String.format(java.util.Locale.getDefault(), "%.2f", degreeValue); + } else { + displayDegree = String.valueOf(Math.round(degreeValue)); + } + degreeTextView.setTextColor(getDegreeTextColor()); degreeTextView.setText(" " + displayDegree + "°"); degreeTextView.setRotation(spin - 90f); } - private int calculateDisplayDegree() { + private float calculateDegreeValue() { // Calculate angle relative to nearest 90-degree orientation (0, 90, 180, 270) float normalizedSpin = normalizeAngle(spin, 360f); float angleFromNearest90 = normalizedSpin % 90f; @@ -268,7 +285,7 @@ private int calculateDisplayDegree() { degreeValue = angleFromNearest90 - 90f; // 45 to 90 becomes -45 to 0 } - return Math.round(degreeValue); + return degreeValue; } // Color helper methods diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3c9bfe5..f29b5bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -65,6 +65,9 @@ Haptic feedback On Off + High precision + On + Off Compass Reference True North Magnetic North From f1c23e04c66ce1d24a13de66701f306b6e73d9d8 Mon Sep 17 00:00:00 2001 From: iso53 <102249575+ISO53@users.noreply.github.com> Date: Sat, 14 Mar 2026 16:04:26 +0300 Subject: [PATCH 2/2] Bump app to 1.3.0 and add precision drawable Increment versionCode to 3 and versionName to 1.3.0 for the new release. Add a new vector drawable (precision.xml) and update OptionsActivity to use R.drawable.precision for the High Precision option instead of the generic settings icon. --- app/build.gradle.kts | 4 ++-- .../github/iso53/nothingcompass/OptionsActivity.java | 2 +- app/src/main/res/drawable/precision.xml | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 app/src/main/res/drawable/precision.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bd63fe7..8220fc6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,8 +13,8 @@ android { applicationId = "io.github.iso53.nothingcompass" minSdk = 27 targetSdk = 36 - versionCode = 2 - versionName = "1.2.0" + versionCode = 3 + versionName = "1.3.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/io/github/iso53/nothingcompass/OptionsActivity.java b/app/src/main/java/io/github/iso53/nothingcompass/OptionsActivity.java index 00d6ee7..7e277e5 100644 --- a/app/src/main/java/io/github/iso53/nothingcompass/OptionsActivity.java +++ b/app/src/main/java/io/github/iso53/nothingcompass/OptionsActivity.java @@ -70,7 +70,7 @@ private void setupRecyclerView() { items.add(new OptionItem(getString(R.string.item_haptic_feedback), null, R.drawable.ic_vibration, v -> showHapticFeedbackSelectionDialog())); items.add(new OptionItem(getString(R.string.item_high_precision), null, - R.drawable.ic_settings, v -> showHighPrecisionSelectionDialog())); + R.drawable.precision, v -> showHighPrecisionSelectionDialog())); items.add(new OptionItem(getString(R.string.item_north_reference), null, R.drawable.ic_compass, v -> showNorthReferenceSelectionDialog())); diff --git a/app/src/main/res/drawable/precision.xml b/app/src/main/res/drawable/precision.xml new file mode 100644 index 0000000..9e952c7 --- /dev/null +++ b/app/src/main/res/drawable/precision.xml @@ -0,0 +1,10 @@ + + +