160 lines
5.6 KiB
Kotlin
160 lines
5.6 KiB
Kotlin
package de.timklge.karooheadwind.screens
|
|
|
|
import androidx.compose.foundation.Image
|
|
import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.clickable
|
|
import androidx.compose.foundation.layout.Column
|
|
import androidx.compose.foundation.layout.Spacer
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
import androidx.compose.foundation.layout.padding
|
|
import androidx.compose.foundation.layout.size
|
|
import androidx.compose.foundation.rememberScrollState
|
|
import androidx.compose.foundation.verticalScroll
|
|
import androidx.compose.material3.AlertDialog
|
|
import androidx.compose.material3.Button
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
import androidx.compose.material3.MaterialTheme
|
|
import androidx.compose.material3.Tab
|
|
import androidx.compose.material3.TabRow
|
|
import androidx.compose.material3.Text
|
|
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.DisposableEffect
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.mutableIntStateOf
|
|
import androidx.compose.runtime.mutableStateOf
|
|
import androidx.compose.runtime.remember
|
|
import androidx.compose.runtime.rememberCoroutineScope
|
|
import androidx.compose.runtime.setValue
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.platform.LocalContext
|
|
import androidx.compose.ui.res.painterResource
|
|
import androidx.compose.ui.unit.dp
|
|
import de.timklge.karooheadwind.HeadwindSettings
|
|
import de.timklge.karooheadwind.R
|
|
import de.timklge.karooheadwind.saveSettings
|
|
import de.timklge.karooheadwind.streamSettings
|
|
import io.hammerhead.karooext.KarooSystemService
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.flow.first
|
|
import kotlinx.coroutines.launch
|
|
|
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
@Composable
|
|
fun MainScreen(close: () -> Unit) {
|
|
var karooConnected by remember { mutableStateOf(false) }
|
|
val ctx = LocalContext.current
|
|
val coroutineScope = rememberCoroutineScope()
|
|
val karooSystem = remember { KarooSystemService(ctx) }
|
|
|
|
var welcomeDialogVisible by remember { mutableStateOf(false) }
|
|
var tabIndex by remember { mutableIntStateOf(0) }
|
|
|
|
var isRefreshing by remember { mutableStateOf(false) }
|
|
|
|
val tabs = listOf("Weather", "Settings")
|
|
|
|
fun refreshData() {
|
|
coroutineScope.launch {
|
|
isRefreshing = true
|
|
// Set the lastUpdateRequested value to trigger a weather update in the KarooHeadwindExtension
|
|
val settings = ctx.streamSettings(karooSystem).first()
|
|
saveSettings(ctx, settings.copy(lastUpdateRequested = System.currentTimeMillis()))
|
|
delay(1000) // Give some time to show the refreshing indicator
|
|
isRefreshing = false
|
|
}
|
|
}
|
|
|
|
LaunchedEffect(isRefreshing) {
|
|
if (isRefreshing) {
|
|
delay(2000) // Timeout after 2 seconds if the refresh doesn't complete
|
|
isRefreshing = false
|
|
}
|
|
}
|
|
|
|
fun onFinish() {
|
|
if (tabIndex > 0){
|
|
tabIndex--
|
|
} else {
|
|
close()
|
|
}
|
|
}
|
|
|
|
DisposableEffect(Unit) {
|
|
onDispose {
|
|
karooSystem.disconnect()
|
|
}
|
|
}
|
|
|
|
LaunchedEffect(Unit) {
|
|
ctx.streamSettings(karooSystem).collect { settings ->
|
|
welcomeDialogVisible = !settings.welcomeDialogAccepted
|
|
}
|
|
}
|
|
|
|
LaunchedEffect(Unit) {
|
|
karooSystem.connect { connected ->
|
|
karooConnected = connected
|
|
}
|
|
}
|
|
|
|
PullToRefreshBox(modifier = Modifier.fillMaxSize(), isRefreshing = isRefreshing, onRefresh = { refreshData() }) {
|
|
Column(modifier = Modifier
|
|
.fillMaxSize()
|
|
.background(MaterialTheme.colorScheme.background)) {
|
|
|
|
Column(modifier = Modifier.fillMaxWidth()) {
|
|
TabRow(selectedTabIndex = tabIndex) {
|
|
tabs.forEachIndexed { index, title ->
|
|
Tab(text = { Text(title) },
|
|
selected = tabIndex == index,
|
|
onClick = { tabIndex = index }
|
|
)
|
|
}
|
|
}
|
|
when (tabIndex) {
|
|
0 -> WeatherScreen(::onFinish)
|
|
1 -> SettingsScreen(::onFinish)
|
|
}
|
|
}
|
|
}
|
|
|
|
if (welcomeDialogVisible){
|
|
AlertDialog(onDismissRequest = { },
|
|
confirmButton = { Button(onClick = {
|
|
coroutineScope.launch {
|
|
saveSettings(ctx, HeadwindSettings(welcomeDialogAccepted = true))
|
|
}
|
|
}) { Text("OK") } },
|
|
text = {
|
|
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
|
|
Text("Welcome to karoo-headwind!")
|
|
|
|
Spacer(Modifier.padding(10.dp))
|
|
|
|
Text("You can add headwind direction and other fields to your data pages in your profile settings.")
|
|
|
|
Spacer(Modifier.padding(10.dp))
|
|
|
|
Text("Please note that this app periodically fetches weather data from OpenMeteo for your current location.")
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
Image(
|
|
painter = painterResource(id = R.drawable.back),
|
|
contentDescription = "Back",
|
|
modifier = Modifier
|
|
.align(Alignment.BottomStart)
|
|
.padding(bottom = 10.dp)
|
|
.size(54.dp)
|
|
.clickable {
|
|
onFinish()
|
|
}
|
|
)
|
|
}
|
|
} |