diff options
author | Iván Ávalos <avalos@disroot.org> | 2023-09-26 19:36:27 -0600 |
---|---|---|
committer | Iván Ávalos <avalos@disroot.org> | 2023-09-26 19:36:27 -0600 |
commit | 3e72d9b02e864f4f79ae494c67418031b7625659 (patch) | |
tree | 3d6d7ae3997b9372d50932e0e489dced12e5b07c /shared | |
parent | 8765d82d3ad055945c6221e4f46bc38d903bf58d (diff) | |
parent | 3022b877d0cf9b7546c80953237c7bca5a4afa50 (diff) | |
download | etbsa-trackermap-mobile-3e72d9b02e864f4f79ae494c67418031b7625659.tar.gz etbsa-trackermap-mobile-3e72d9b02e864f4f79ae494c67418031b7625659.tar.bz2 etbsa-trackermap-mobile-3e72d9b02e864f4f79ae494c67418031b7625659.zip |
Merge branch 'main' of https://git.sr.ht/~avalos/trackermap-mobile
Diffstat (limited to 'shared')
10 files changed, 118 insertions, 19 deletions
diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 67acdb8..6517f7f 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -19,6 +19,11 @@ kotlin { ).forEach { it.binaries.framework { baseName = "shared" + + // Fix builds in Xcode 15 + if (System.getenv("XCODE_VERSION_MAJOR") == "1500") { + linkerOpts += "-ld64" + } } } diff --git a/shared/src/androidMain/AndroidManifest.xml b/shared/src/androidMain/AndroidManifest.xml index 568741e..f0f34af 100644 --- a/shared/src/androidMain/AndroidManifest.xml +++ b/shared/src/androidMain/AndroidManifest.xml @@ -1,2 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> -<manifest />
\ No newline at end of file +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> +</manifest>
\ No newline at end of file diff --git a/shared/src/androidMain/kotlin/mx/trackermap/TrackerMap/controllers/NetworkController.kt b/shared/src/androidMain/kotlin/mx/trackermap/TrackerMap/controllers/NetworkController.kt new file mode 100644 index 0000000..eecd7de --- /dev/null +++ b/shared/src/androidMain/kotlin/mx/trackermap/TrackerMap/controllers/NetworkController.kt @@ -0,0 +1,55 @@ +package mx.trackermap.TrackerMap.controllers + +import android.content.Context +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import android.os.Build +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import mx.trackermap.TrackerMap.Injectable + +actual class NetworkController(context: Context): Injectable { + private val networkRequest = NetworkRequest.Builder().build() + private val connectivityManager: ConnectivityManager + private val _networkAvailable = MutableStateFlow<Boolean?>(null) + actual val networkAvailable = _networkAvailable.asStateFlow() + + private val networkCallback = object: ConnectivityManager.NetworkCallback() { + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities + ) { + super.onCapabilitiesChanged(network, networkCapabilities) + _networkAvailable.value = checkNetworkAccess(networkCapabilities) + } + + override fun onLost(network: Network) { + super.onLost(network) + _networkAvailable.value = false + } + } + + init { + connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + _networkAvailable.value = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + checkNetworkAccess(connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)) + } else { + connectivityManager.activeNetworkInfo?.isConnected == true + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + connectivityManager.registerDefaultNetworkCallback(networkCallback) + } else { + connectivityManager.registerNetworkCallback(networkRequest, networkCallback) + } + } + + private fun checkNetworkAccess(capabilities: NetworkCapabilities?) = + capabilities != null + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + && if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + } else true +}
\ No newline at end of file diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/ApiClient.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/ApiClient.kt index 937b2dd..8238f7e 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/ApiClient.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/ApiClient.kt @@ -168,7 +168,7 @@ open class ApiClient( } } - if (sessionManager.token.isNotEmpty()) { + if (sessionManager.hasSession) { request.headers["Cookie"] = sessionManager.token } val response: HttpResponse = client.request(request) diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/SessionManager.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/SessionManager.kt index caf2da1..71ae5d0 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/SessionManager.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/infrastructure/SessionManager.kt @@ -28,6 +28,8 @@ class SessionManager( settings[ACCESS_TOKEN_KEY] = token } + val hasSession: Boolean get() = settings.hasKey(ACCESS_TOKEN_KEY) + fun clearSession() { settings.remove(ACCESS_TOKEN_KEY) settings.remove(SERVER_URL_KEY) diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/UnitInformation.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/UnitInformation.kt index 6afa350..33e85ee 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/UnitInformation.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/UnitInformation.kt @@ -53,5 +53,15 @@ data class UnitInformation( } ?: EngineStop.UNKNOWN } else EngineStop.UNKNOWN - fun getHourmeter() = position?.attributes?.get("hours")?.longOrNull + fun getHourmeter() = position?.attributes?.let { attrs -> + if ("io16" in attrs) { + // Minutes + attrs["io16"]?.longOrNull?.let { it * 60 * 1000 } + } else if ("hours" in attrs) { + // Milliseconds + attrs["hours"]?.longOrNull + } else { + null + } + } }
\ No newline at end of file diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/NetworkController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/NetworkController.kt new file mode 100644 index 0000000..08dcc87 --- /dev/null +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/NetworkController.kt @@ -0,0 +1,8 @@ +package mx.trackermap.TrackerMap.controllers + +import kotlinx.coroutines.flow.StateFlow +import mx.trackermap.TrackerMap.Injectable + +expect class NetworkController: Injectable { + val networkAvailable: StateFlow<Boolean?> +}
\ No newline at end of file diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/SessionController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/SessionController.kt index a63bba2..5cfdf96 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/SessionController.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/SessionController.kt @@ -25,13 +25,15 @@ import kotlinx.serialization.json.JsonPrimitive import mx.trackermap.TrackerMap.Injectable import mx.trackermap.TrackerMap.client.apis.SessionApi import mx.trackermap.TrackerMap.client.apis.UsersApi +import mx.trackermap.TrackerMap.client.infrastructure.SessionManager import mx.trackermap.TrackerMap.client.models.SessionBody import mx.trackermap.TrackerMap.client.models.User @DelicateCoroutinesApi class SessionController( + private val sessionManager: SessionManager, private val sessionApi: SessionApi, - private val usersApi: UsersApi + private val usersApi: UsersApi, ): Injectable { sealed class LoginState { object Nothing: LoginState() @@ -46,6 +48,7 @@ class SessionController( val loginStateFlow = MutableStateFlow<LoginState?>(null) val userFlow = MutableStateFlow<User?>(null) + val hasSession: Boolean get() = sessionManager.hasSession fun getSession() { loginStateFlow.value = LoginState.Loading @@ -59,19 +62,6 @@ class SessionController( } } - fun restoreSession() { - loginStateFlow.value = LoginState.Loading - GlobalScope.launch { - try { - userFlow.value = sessionApi.sessionGet() - loginStateFlow.value = LoginState.Success - } catch (e: Exception) { - e.printStackTrace() - loginStateFlow.value = LoginState.Nothing - } - } - } - fun login(body: SessionBody) { val url = body.url.trim() val email = body.email.trim() diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/ReportDates.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/ReportDates.kt index 5298df3..9f3a142 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/ReportDates.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/ReportDates.kt @@ -22,6 +22,8 @@ import kotlinx.datetime.* @DelicateCoroutinesApi class ReportDates { + + // Don't remove! Used by iOS enum class PeriodTypes { TODAY, LAST_24, @@ -35,7 +37,7 @@ class ReportDates { sealed class ReportPeriod { val timezone = TimeZone.currentSystemDefault() - val clock = Clock.System + private val clock = Clock.System val instant = clock.now() val dateTime = instant.toLocalDateTime(timezone) val date = dateTime.date @@ -47,7 +49,7 @@ class ReportDates { return formatDateTime(from) to formatDateTime(to) } - fun formatDateTime(dateTime: LocalDateTime) = + private fun formatDateTime(dateTime: LocalDateTime) = dateTime.toInstant(timezone).toString() class Today : ReportPeriod() { diff --git a/shared/src/iosMain/kotlin/mx/trackermap/TrackerMap/controllers/NetworkController.kt b/shared/src/iosMain/kotlin/mx/trackermap/TrackerMap/controllers/NetworkController.kt new file mode 100644 index 0000000..d112c11 --- /dev/null +++ b/shared/src/iosMain/kotlin/mx/trackermap/TrackerMap/controllers/NetworkController.kt @@ -0,0 +1,25 @@ +package mx.trackermap.TrackerMap.controllers + +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import mx.trackermap.TrackerMap.Injectable +import platform.Network.* +import platform.darwin.* + +actual class NetworkController: Injectable { + private val monitor = nw_path_monitor_create() + private val queue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND.toLong(), 0u) + private val _networkAvailable = MutableStateFlow<Boolean?>(null) + actual val networkAvailable = _networkAvailable.asStateFlow() + + private val updateHandler: nw_path_monitor_update_handler_t = { path: nw_path_t -> + val status = nw_path_get_status(path) + _networkAvailable.value = status in arrayOf(nw_path_status_satisfied, nw_path_status_satisfiable) + } + + init { + nw_path_monitor_set_update_handler(monitor, updateHandler) + nw_path_monitor_set_queue(monitor, queue) + nw_path_monitor_start(monitor) + } +}
\ No newline at end of file |