From ebe1d18123e8c09169997220e3fe3602af27adb6 Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Wed, 18 Mar 2026 17:53:53 +0100 Subject: [PATCH] feat: add open-in-browser button to dashboard Opens {baseUrl}/{siteId} in the default browser so users can quickly access the full Plausible web interface for their site. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../implausibly/ui/dashboard/DashboardScreen.kt | 13 +++++++++++++ .../implausibly/ui/dashboard/DashboardViewModel.kt | 2 ++ 2 files changed, 15 insertions(+) diff --git a/app/src/main/java/no/naiv/implausibly/ui/dashboard/DashboardScreen.kt b/app/src/main/java/no/naiv/implausibly/ui/dashboard/DashboardScreen.kt index 6c7fff9..71c5c5d 100644 --- a/app/src/main/java/no/naiv/implausibly/ui/dashboard/DashboardScreen.kt +++ b/app/src/main/java/no/naiv/implausibly/ui/dashboard/DashboardScreen.kt @@ -7,8 +7,11 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.lazy.LazyColumn +import android.content.Intent +import android.net.Uri import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Language +import androidx.compose.material.icons.filled.OpenInBrowser import androidx.compose.material.icons.filled.SwapHoriz import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon @@ -21,6 +24,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import no.naiv.implausibly.domain.model.DashboardData @@ -47,12 +51,21 @@ fun DashboardScreen( viewModel: DashboardViewModel = hiltViewModel() ) { val uiState by viewModel.uiState.collectAsState() + val context = LocalContext.current Scaffold( topBar = { TopAppBar( title = { Text(uiState.siteId) }, actions = { + if (uiState.baseUrl.isNotEmpty()) { + IconButton(onClick = { + val url = "${uiState.baseUrl}/${uiState.siteId}" + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) + }) { + Icon(Icons.Default.OpenInBrowser, contentDescription = "Open in browser") + } + } IconButton(onClick = { onNavigateToSites(uiState.instanceId) }) { Icon(Icons.Default.Language, contentDescription = "Switch site") } diff --git a/app/src/main/java/no/naiv/implausibly/ui/dashboard/DashboardViewModel.kt b/app/src/main/java/no/naiv/implausibly/ui/dashboard/DashboardViewModel.kt index ed22fac..7f5b4f4 100644 --- a/app/src/main/java/no/naiv/implausibly/ui/dashboard/DashboardViewModel.kt +++ b/app/src/main/java/no/naiv/implausibly/ui/dashboard/DashboardViewModel.kt @@ -21,6 +21,7 @@ import javax.inject.Inject data class DashboardUiState( val instanceId: String = "", val siteId: String = "", + val baseUrl: String = "", val dateRange: DateRange = DateRange.ThirtyDays, val dataState: UiState = UiState.Loading, val isRefreshing: Boolean = false @@ -76,6 +77,7 @@ class DashboardViewModel @Inject constructor( _uiState.update { it.copy( + baseUrl = instance.baseUrl, dataState = UiState.Success(data), isRefreshing = false )