feat: portal-wide device selector — session-based, all pages now use selected device
- _portal_device_id() reads from session, falls back to DEVICE_NAME env var - GET/POST /api/v1/portal/select-device for selector data + set - Dropdown in server base.html topbar, JS populates from API, page reloads on change - All portal pages (overview, trips, dashcam, DTC, device settings) now use selected device
This commit is contained in:
@@ -21,6 +21,7 @@ import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -43,6 +44,7 @@ fun DashcamScreen(
|
||||
retentionDays: Int,
|
||||
isLoading: Boolean,
|
||||
error: String?,
|
||||
downloadProgress: Map<String, DownloadProgress>,
|
||||
onRefresh: () -> Unit,
|
||||
onDownload: (VideoFile) -> Unit,
|
||||
onDelete: (VideoFile) -> Unit,
|
||||
@@ -146,8 +148,10 @@ fun DashcamScreen(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
items(videos, key = { it.path }) { video ->
|
||||
val progress = downloadProgress[video.path]
|
||||
VideoRow(
|
||||
video = video,
|
||||
downloadProgress = progress,
|
||||
onDownload = { onDownload(video) },
|
||||
onDelete = { onDelete(video) },
|
||||
)
|
||||
@@ -161,6 +165,7 @@ fun DashcamScreen(
|
||||
@Composable
|
||||
private fun VideoRow(
|
||||
video: VideoFile,
|
||||
downloadProgress: DownloadProgress?,
|
||||
onDownload: () -> Unit,
|
||||
onDelete: () -> Unit,
|
||||
) {
|
||||
@@ -224,6 +229,20 @@ private fun VideoRow(
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.tertiary
|
||||
)
|
||||
} else if (downloadProgress != null) {
|
||||
LinearProgressIndicator(
|
||||
progress = {
|
||||
if (downloadProgress.totalBytes > 0)
|
||||
downloadProgress.bytesDownloaded.toFloat() / downloadProgress.totalBytes
|
||||
else 0f
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth().padding(top = 4.dp),
|
||||
)
|
||||
Text(
|
||||
text = "Downloading ${downloadProgress.bytesDownloaded / 1_000_000}MB / ${downloadProgress.totalBytes / 1_000_000}MB",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
text = if (video.uploaded) "Uploaded" else "Pending",
|
||||
|
||||
@@ -12,8 +12,11 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
@@ -49,10 +52,20 @@ fun YarisMainScreen(client: OkHttpClient) {
|
||||
val retentionDays by dashcamVm.retentionDays.collectAsState()
|
||||
val isLoading by dashcamVm.isLoading.collectAsState()
|
||||
val error by dashcamVm.error.collectAsState()
|
||||
val downloadProgress by dashcamVm.downloadProgress.collectAsState()
|
||||
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
var selectedTab by remember { mutableIntStateOf(0) }
|
||||
|
||||
// Show download/delete events as snackbars
|
||||
LaunchedEffect(Unit) {
|
||||
dashcamVm.downloadEvents.collect { event ->
|
||||
snackbarHostState.showSnackbar(event)
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||
bottomBar = {
|
||||
NavigationBar {
|
||||
NavigationBarItem(
|
||||
@@ -78,6 +91,7 @@ fun YarisMainScreen(client: OkHttpClient) {
|
||||
retentionDays = retentionDays,
|
||||
isLoading = isLoading,
|
||||
error = error,
|
||||
downloadProgress = downloadProgress,
|
||||
onRefresh = { dashcamVm.loadVideos() },
|
||||
onDownload = { dashcamVm.downloadVideo(it) },
|
||||
onDelete = { dashcamVm.deleteVideo(it) },
|
||||
|
||||
Reference in New Issue
Block a user