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) <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-03-18 17:53:53 +01:00
commit ebe1d18123
2 changed files with 15 additions and 0 deletions

View file

@ -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")
}

View file

@ -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<DashboardData> = 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
)