Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b64e4b4c authored by Ellen Poe's avatar Ellen Poe
Browse files

Merge branch 'ellenhp/more_viewmodel_tests' into 'main'

test: more viewmodel tests

See merge request e/os/cardinal!31
parents a8971ec9 e6101bb1
Loading
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ test:
    # Build debug APKs for each architecture
    - cd cardinal-android
    - touch local.properties
    - ./gradlew generateUniFFIBindings
    - ./gradlew test --info --stacktrace --no-daemon
    - ./gradlew assembleArm64Debug --info --stacktrace --no-daemon
  artifacts:
@@ -257,6 +258,7 @@ build_release:
    - touch local.properties
    - |
      # Build APKs for each architecture
      ./gradlew generateUniFFIBindings
      ./gradlew assembleArm64Release --info --stacktrace --no-daemon
      ./gradlew assembleX86_64Release --info --stacktrace --no-daemon
  artifacts:
+0 −9
Original line number Diff line number Diff line
@@ -137,15 +137,6 @@ android {
        dependsOn("buildCargoNdkArm64Release", "buildCargoNdkX86_64Release")
    }

    applicationVariants.all {
        val variant = this

        // Add dependency from Java compilation to the UniFFI binding generation task
        tasks.named("compile${variant.name.capitalize()}JavaWithJavac") {
            dependsOn(generateUniFFIBindings)
        }
    }

    sourceSets {
        getByName("main") {
            java.srcDir(layout.buildDirectory.dir("generated/source/uniffi"))
+45 −40
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.util.Log
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
@@ -39,6 +38,8 @@ import earth.maps.cardinal.tileserver.TileDownloadForegroundService
import earth.maps.cardinal.tileserver.calculateTileRange
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.math.min
@@ -60,6 +61,10 @@ class OfflineAreasViewModel @Inject constructor(
    val unifiedProgress = mutableFloatStateOf(0f) // 0.0 to 1.0
    val currentStage = mutableStateOf(DownloadStage.BASEMAP)

    // Error handling
    private val _errorMessage = MutableStateFlow<String?>(null)
    val errorMessage: StateFlow<String?> = _errorMessage

    // Service binding infrastructure
    private var serviceBinder: TileDownloadForegroundService.TileDownloadBinder? = null
    private var progressJob: Job? = null
@@ -67,14 +72,12 @@ class OfflineAreasViewModel @Inject constructor(

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            Log.d(TAG, "Connected to TileDownloadForegroundService")
            serviceBinder = service as TileDownloadForegroundService.TileDownloadBinder
            isBound = true
            syncWithOngoingDownloads()
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            Log.d(TAG, "Disconnected from TileDownloadForegroundService")
            serviceBinder = null
            isBound = false
            progressJob?.cancel()
@@ -84,7 +87,6 @@ class OfflineAreasViewModel @Inject constructor(
        }

        override fun onBindingDied(name: ComponentName?) {
            Log.d(TAG, "Binding to TileDownloadForegroundService died")
            serviceBinder = null
            isBound = false
            progressJob?.cancel()
@@ -93,7 +95,6 @@ class OfflineAreasViewModel @Inject constructor(
        }

        override fun onNullBinding(name: ComponentName?) {
            Log.d(TAG, "Null binding to TileDownloadForegroundService")
            serviceBinder = null
            isBound = false
            resetProgressState()
@@ -118,13 +119,8 @@ class OfflineAreasViewModel @Inject constructor(
                // Check if service is currently downloading
                val isServiceDownloading = service.isDownloading.value
                if (isServiceDownloading) {
                    Log.d(TAG, "Detected ongoing download in service, syncing UI state")
                    // The StateFlow observations should handle the rest
                } else {
                    Log.d(TAG, "No ongoing downloads detected in service")
                }
            } else {
                Log.d(TAG, "Service not bound yet, will sync when connection established")
            }
        }
    }
@@ -184,9 +180,12 @@ class OfflineAreasViewModel @Inject constructor(
     */
   private fun bindToService() {
       if (!isBound) {
            Log.d(TAG, "Binding to TileDownloadForegroundService")
           val intent = Intent(context, TileDownloadForegroundService::class.java)
           try {
               context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
           } catch (e: Exception) {
               _errorMessage.value = "Failed to bind to download service: ${e.message}"
           }
       }
   }

@@ -195,8 +194,11 @@ class OfflineAreasViewModel @Inject constructor(
     */
   private fun unbindFromService() {
       if (isBound) {
            Log.d(TAG, "Unbinding from TileDownloadForegroundService")
           try {
               context.unbindService(serviceConnection)
           } catch (e: Exception) {
               _errorMessage.value = "Failed to unbind from download service: ${e.message}"
           }
           serviceBinder = null
           isBound = false
       }
@@ -220,9 +222,6 @@ class OfflineAreasViewModel @Inject constructor(
           downloadProgress.intValue = 0
           totalTiles.intValue = 0
           currentAreaName.value = ""
            Log.d(TAG, "Reset progress state - no active downloads in database")
        } else {
            Log.d(TAG, "Not resetting progress state - active areas exist in database")
       }
    }

@@ -237,6 +236,12 @@ class OfflineAreasViewModel @Inject constructor(
    companion object {
        const val OFFLINE_AREA_MIN_ZOOM = 5
        const val OFFLINE_AREA_MAX_ZOOM = 14
        private const val TAG = "OfflineAreasViewModel"
    }

    /**
     * Clear any error message
     */
    fun clearErrorMessage() {
        _errorMessage.value = null
    }
}
+0 −18
Original line number Diff line number Diff line
@@ -28,14 +28,11 @@ import earth.maps.cardinal.data.Place
import earth.maps.cardinal.data.room.SavedPlaceDao
import earth.maps.cardinal.transit.StopTime
import earth.maps.cardinal.transit.TransitousService
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds

@HiltViewModel
class TransitStopCardViewModel @Inject constructor(
@@ -44,8 +41,6 @@ class TransitStopCardViewModel @Inject constructor(
    private val appPreferenceRepository: AppPreferenceRepository,
) : ViewModel() {

    private var refreshJob: Job? = null

    val isPlaceSaved = mutableStateOf(false)
    val stop = mutableStateOf<Place?>(null)
    val departures = MutableStateFlow<List<StopTime>>(emptyList())
@@ -73,15 +68,6 @@ class TransitStopCardViewModel @Inject constructor(

    val use24HourFormat = appPreferenceRepository.use24HourFormat

    init {
        refreshJob = viewModelScope.launch {
            while (true) {
                refreshDepartures()
                delay(30.seconds)
            }
        }
    }

    fun setStop(place: Place) {
        this.stop.value = place
    }
@@ -139,10 +125,6 @@ class TransitStopCardViewModel @Inject constructor(
        }
    }

    override fun onCleared() {
        super.onCleared()
        refreshJob?.cancel()
    }

    companion object {
        private const val TAG = "TransitStopViewModel"
+0 −8
Original line number Diff line number Diff line
@@ -158,12 +158,4 @@ class SettingsViewModel @Inject constructor(
        }
        return null
    }

    fun onCallToActionClicked() {
        val url = "https://github.com/ellenhp/cardinal"
        val i = Intent(Intent.ACTION_VIEW)
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        i.setData(url.toUri())
        context.startActivity(i)
    }
}
Loading