OXYGENHUB
# c1b5d82f16cd oxygenhub-android / app / src / main / java / io / oxygenhub / android / OxygenHubApp.kt
2.2 KiB · last changed Alerts from the hub: the phone registers its Cloud Messaging token and an X25519 key kept by the Keystore, and opens and shows what the hub seals to it with the Rust core; Firebase from google-services.json (the release job's firebase-config secret); pins OxygenFlow main (refs #16) 8 days ago source blame history raw
1
package io.oxygenhub.android
2
3
import android.app.Application
4
import android.os.Build
5
import android.util.Log
6
import io.oxygenhub.android.alerts.PushAlerts
7
import io.oxygenhub.android.api.DeviceAuth
8
import io.oxygenhub.android.api.HubClient
9
import io.oxygenhub.android.api.HubDeviceAuth
10
import io.oxygenhub.android.api.hubHttpClient
11
import io.oxygenhub.android.auth.KeystoreSessionStore
12
import io.oxygenhub.android.auth.SessionManager
13
import kotlinx.coroutines.CoroutineScope
14
import kotlinx.coroutines.Dispatchers
15
import kotlinx.coroutines.SupervisorJob
16
import kotlinx.coroutines.flow.distinctUntilChanged
17
import kotlinx.coroutines.flow.filterNotNull
18
import kotlinx.coroutines.launch
19
import okhttp3.OkHttpClient
20
21
/** The hub the app signs in to unless told otherwise. */
22
const val DEFAULT_HUB = "https://oxygenhub.io"
23
24
/** The app's shared objects, made once. A small hand-made container: no DI framework yet. */
25
class AppContainer(app: Application) {
26
    val http: OkHttpClient = hubHttpClient()
27
28
    val sessions = SessionManager(KeystoreSessionStore(app)) { session, onUnauthorized ->
29
        HubClient(session.hub, session.token, http, onUnauthorized)
30
    }
31
32
    fun deviceAuth(hub: String): DeviceAuth = HubDeviceAuth(hub, http)
33
34
    /** What the app calls itself on the hub's /device page and token list. */
35
    val clientName: String = "OxygenHub for Android on ${Build.MODEL}".take(80)
36
}
37
38
class OxygenHubApp : Application() {
39
    lateinit var container: AppContainer
40
        private set
41
42
    override fun onCreate() {
43
        super.onCreate()
44
        container = AppContainer(this)
45
        // Alerts from the hub (#16): each signed-in session registers this
46
        // phone; signing out revokes the token, which ends it on the hub.
47
        if (PushAlerts.available) {
48
            PushAlerts.start(this)
49
            CoroutineScope(SupervisorJob() + Dispatchers.IO).launch {
50
                container.sessions.session.filterNotNull().distinctUntilChanged().collect {
51
                    val api = container.sessions.api() ?: return@collect
52
                    runCatching { PushAlerts.register(this@OxygenHubApp, api) }
53
                        .onFailure { Log.w("OxygenHubApp", "alerts: registering with the hub: ${it.message}") }
54
                }
55
            }
56
        }
57
    }
58
}