OXYGENHUB

Coverage / app/src/main/java/io/oxygenhub/android/MainActivity.kt 0.0%

0 of 38 lines run, 0 of 12 functions, 0 of 20 branches · run #1664 on main · run missed

1
package io.oxygenhub.android
2
3
import android.content.Intent
4
import android.os.Bundle
5
import androidx.activity.ComponentActivity
6
import androidx.activity.compose.setContent
7
import androidx.activity.enableEdgeToEdge
8
import androidx.compose.runtime.getValue
9
import androidx.compose.runtime.key
10
import androidx.compose.runtime.mutableStateOf
11
import androidx.glance.appwidget.updateAll
12
import androidx.lifecycle.compose.collectAsStateWithLifecycle
13
import androidx.lifecycle.lifecycleScope
14
import io.oxygenhub.android.alerts.LandAlerts
15
import io.oxygenhub.android.ui.nav.ProposalRoute
16
import io.oxygenhub.android.ui.nav.SignedInApp
17
import io.oxygenhub.android.ui.nav.rememberViewModel
18
import io.oxygenhub.android.ui.signin.SignInScreen
19
import io.oxygenhub.android.ui.signin.SignInViewModel
20
import io.oxygenhub.android.ui.theme.OxygenHubTheme
21
import io.oxygenhub.android.widget.HubWidget
22
import io.oxygenhub.android.widget.WidgetTaps
23
import kotlinx.coroutines.launch
24
import uniffi.rust_core.oxygenGreeting
25
26
class MainActivity : ComponentActivity() {
27
    /** A proposal a notification asked to open (#20), until it is shown. */
28
    /** A screen to open, as a notification or the widget asks: a route of the app's navigation. */
29
    private val opening = mutableStateOf<Any?>(null)
30
31
    override fun onCreate(savedInstanceState: Bundle?) {
32
        super.onCreate(savedInstanceState)
33
        if (savedInstanceState == null) opening.value = routeIn(intent)
34
        enableEdgeToEdge()
35
        val container = (application as OxygenHubApp).container
36
        val sessions = container.sessions
37
        setContent {
38
            OxygenHubTheme {
39
                val session by sessions.session.collectAsStateWithLifecycle()
40
                val signedIn = session
41
                val api = signedIn?.let { sessions.api() }
42
                if (signedIn == null || api == null) {
43
                    SignInScreen(
44
                        rememberViewModel { SignInViewModel(sessions, container::deviceAuth, container.clientName, DEFAULT_HUB) },
45
                    )
46
                } else {
47
                    // A new session starts the signed-in app afresh: nothing of the last account's is kept.
48
                    key(signedIn) {
49
                        SignedInApp(
50
                            session = signedIn,
51
                            api = api,
52
                            nativeCore = { oxygenGreeting(signedIn.username) },
53
                            onSignOut = { sessions.signOut() },
54
                            open = opening.value,
55
                            onOpened = { opening.value = null },
56
                        )
57
                    }
58
                }
59
            }
60
        }
61
    }
62
63
    /** The widget (#28) shows what the app knows now, whenever the app comes to the front. */
64
    override fun onResume() {
65
        super.onResume()
66
        lifecycleScope.launch { runCatching { HubWidget().updateAll(this@MainActivity) } }
67
    }
68
69
    override fun onNewIntent(intent: Intent) {
70
        super.onNewIntent(intent)
71
        routeIn(intent)?.let { opening.value = it }
72
    }
73
74
    /** A land alert's proposal, or the screen a tap on the widget's counts names (#31). */
75
    private fun routeIn(intent: Intent?): Any? = proposalIn(intent) ?: WidgetTaps.route(intent)
76
77
    private fun proposalIn(intent: Intent?): ProposalRoute? {
78
        val repository = intent?.getStringExtra(LandAlerts.EXTRA_REPOSITORY) ?: return null
79
        val number = intent.getLongExtra(LandAlerts.EXTRA_NUMBER, 0)
80
        if ('/' !in repository || number <= 0) return null
81
        return ProposalRoute(repository.substringBefore('/'), repository.substringAfter('/'), number)
82
    }
83
}