Privacy-preserving location sharing with end-to-end encryption coord.is
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Android UX improvements: back button handling and debug branding

- Add BackHandler to AddFriendScreen (step navigation + dismiss)
- Add BackHandler to LocationSettingsScreen (dismiss to map)
- Add BackHandler to OnboardingScreen (page navigation)
- Add BackHandler to ShareBackScreen (dismiss to map)
- Add BackHandler to MapScreen edit mode (exit edit on back)
- Add debug build branding: "Coords Dev" name + red icon
- Add Android Studio to dev shell for interactive development
- Add proguard rule for errorprone annotations

+40 -1
+1 -1
.gitignore
··· 4 4 5 5 # Android 6 6 android/.idea/ 7 - android/.kotlin/errors 7 + android/.kotlin 8 8 android/app/src/main/jniLibs/arm64-v8a/libtransponder_core.so 9 9 10 10 # Apple build artifacts (regenerate with apple/build-xcframework.sh)
+2
android/app/build.gradle.kts
··· 44 44 buildTypes { 45 45 debug { 46 46 applicationIdSuffix = ".dev" 47 + resValue("string", "app_name", "Coords Dev") 47 48 buildConfigField("Boolean", "USE_MOCK_FRIENDS", "true") 48 49 // Temporarily test minification 49 50 isMinifyEnabled = true ··· 54 55 ) 55 56 } 56 57 release { 58 + resValue("string", "app_name", "Coords") 57 59 isMinifyEnabled = true 58 60 isShrinkResources = true 59 61 proguardFiles(
+3
android/app/proguard-rules.pro
··· 5 5 # For more details, see 6 6 # http://developer.android.com/guide/developing/tools/proguard.html 7 7 8 + # AndroidX test references error-prone annotations not included at runtime 9 + -dontwarn com.google.errorprone.annotations.** 10 + 8 11 # JNA - required for UniFFI native bindings 9 12 # JNA uses reflection to find native methods 10 13 -dontwarn java.awt.*
+4
android/app/src/debug/res/drawable/ic_launcher_background.xml
··· 1 + <?xml version="1.0" encoding="utf-8"?> 2 + <shape xmlns:android="http://schemas.android.com/apk/res/android"> 3 + <solid android:color="#FF3B30"/> 4 + </shape>
+12
android/app/src/main/java/sh/bentley/transponder/AddFriendScreen.kt
··· 5 5 import android.graphics.Bitmap 6 6 import android.graphics.ImageFormat 7 7 import android.util.Size 8 + import androidx.activity.compose.BackHandler 8 9 import androidx.activity.compose.rememberLauncherForActivityResult 9 10 import androidx.activity.result.contract.ActivityResultContracts 10 11 import androidx.camera.core.CameraSelector ··· 59 60 var role by remember { mutableStateOf(ExchangeRole.SCAN_FIRST) } 60 61 var currentStep by remember { mutableIntStateOf(0) } 61 62 var addedFriendName by remember { mutableStateOf<String?>(null) } 63 + 64 + BackHandler { 65 + if (currentStep > 0) { 66 + currentStep = 0 67 + addedFriendName = null 68 + } else { 69 + onDismiss() 70 + } 71 + } 62 72 63 73 Scaffold( 64 74 topBar = { ··· 569 579 friendName: String, 570 580 onDismiss: () -> Unit 571 581 ) { 582 + BackHandler { onDismiss() } 583 + 572 584 val qrBitmap = remember(identityStore) { 573 585 val identity = identityStore.getIdentity() ?: return@remember null 574 586 val serverUrl = identityStore.serverUrl ?: return@remember null
+3
android/app/src/main/java/sh/bentley/transponder/LocationSettingsScreen.kt
··· 1 1 package sh.bentley.transponder 2 2 3 + import androidx.activity.compose.BackHandler 3 4 import androidx.compose.foundation.layout.* 4 5 import androidx.compose.material.icons.Icons 5 6 import androidx.compose.material.icons.filled.Close ··· 18 19 ) { 19 20 val context = LocalContext.current 20 21 val scope = rememberCoroutineScope() 22 + 23 + BackHandler { onDismiss() } 21 24 22 25 // Settings state 23 26 var activeTimeoutSec by remember { mutableIntStateOf((identityStore.locationActiveTimeoutMs / 1000).toInt()) }
+5
android/app/src/main/java/sh/bentley/transponder/MapScreen.kt
··· 306 306 var isEditMode by remember { mutableStateOf(false) } 307 307 var friendToDelete by remember { mutableStateOf<Friend?>(null) } 308 308 var showDeleteConfirmation by remember { mutableStateOf(false) } 309 + 310 + // Exit edit mode on back press 311 + BackHandler(enabled = isEditMode) { 312 + isEditMode = false 313 + } 309 314 var myName by remember { mutableStateOf(identityStore.displayName ?: "Me") } 310 315 311 316 // Check if auto-share should be enabled (requires both setting AND permission)
+9
android/app/src/main/java/sh/bentley/transponder/OnboardingScreen.kt
··· 3 3 import android.Manifest 4 4 import android.content.pm.PackageManager 5 5 import android.os.Build 6 + import androidx.activity.compose.BackHandler 6 7 import androidx.activity.compose.rememberLauncherForActivityResult 7 8 import androidx.activity.result.contract.ActivityResultContracts 8 9 import androidx.compose.animation.AnimatedContent ··· 67 68 var currentPage by remember { mutableStateOf(OnboardingPage.Welcome) } 68 69 var hasLocationPermission by remember { mutableStateOf(false) } 69 70 var hasBackgroundPermission by remember { mutableStateOf(false) } 71 + 72 + BackHandler(enabled = currentPage != OnboardingPage.Welcome) { 73 + currentPage = when (currentPage) { 74 + OnboardingPage.Identity -> OnboardingPage.Location 75 + OnboardingPage.Location -> OnboardingPage.Welcome 76 + OnboardingPage.Welcome -> OnboardingPage.Welcome 77 + } 78 + } 70 79 71 80 Scaffold { innerPadding -> 72 81 AnimatedContent(
+1
flake.nix
··· 183 183 default = pkgs.mkShell { 184 184 buildInputs = [ 185 185 android-toolchain 186 + pkgs.android-studio 186 187 pkgs.rust-analyzer 187 188 pkgs.nodejs_24 188 189 pkgs.git