diff --git a/android/build.gradle b/android/build.gradle index a115055..c1ab1fb 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -126,6 +126,9 @@ dependencies { // Authentication only for tests androidTestImplementation 'dev.turingcomplete:kotlin-onetimepassword:2.4.0' androidTestImplementation 'commons-codec:commons-codec:1.16.1' + + debugImplementation("androidx.compose.ui:ui-tooling") + implementation("androidx.compose.ui:ui-tooling-preview") } def getLocalProperty(key) { diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/AboutView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/AboutView.kt index f0247b4..e7d179c 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/AboutView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/AboutView.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tailscale.ipn.BuildConfig import com.tailscale.ipn.R @@ -80,3 +81,9 @@ fun AboutView(backToSettings: BackNavigation) { } } } + +@Preview +@Composable +fun AboutPreview() { + AboutView({}) +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/BugReportView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/BugReportView.kt index 55dab43..3a2da43 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/BugReportView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/BugReportView.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.R import com.tailscale.ipn.ui.Links @@ -29,6 +30,7 @@ import com.tailscale.ipn.ui.theme.defaultTextColor import com.tailscale.ipn.ui.theme.link import com.tailscale.ipn.ui.util.ClipboardValueView import com.tailscale.ipn.ui.util.Lists +import com.tailscale.ipn.ui.util.set import com.tailscale.ipn.ui.viewModel.BugReportViewModel @Composable @@ -81,3 +83,11 @@ fun contactText(): AnnotatedString { } return annotatedString } + +@Preview +@Composable +fun BugReportPreview() { + val vm = BugReportViewModel() + vm.bugReportID.set("12345678ABCDEF-12345678ABCDEF") + BugReportView({}, vm) +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/DNSSettingsView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/DNSSettingsView.kt index 89febab..7e98f22 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/DNSSettingsView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/DNSSettingsView.kt @@ -17,6 +17,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.R @@ -26,6 +27,7 @@ import com.tailscale.ipn.ui.util.ClipboardValueView import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.util.LoadingIndicator import com.tailscale.ipn.ui.util.itemsWithDividers +import com.tailscale.ipn.ui.util.set import com.tailscale.ipn.ui.viewModel.DNSEnablementState import com.tailscale.ipn.ui.viewModel.DNSSettingsViewModel import com.tailscale.ipn.ui.viewModel.DNSSettingsViewModelFactory @@ -99,3 +101,11 @@ fun DNSSettingsView( } } } + +@Preview +@Composable +fun DNSSettingsViewPreview() { + val vm = DNSSettingsViewModel() + vm.enablementState.set(DNSEnablementState.ENABLED) + DNSSettingsView(backToSettings = { }, vm) +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/ErrorDialog.kt b/android/src/main/java/com/tailscale/ipn/ui/view/ErrorDialog.kt index 0615edb..24aa907 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/ErrorDialog.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/ErrorDialog.kt @@ -8,7 +8,9 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import com.tailscale.ipn.R +import com.tailscale.ipn.ui.theme.AppTheme enum class ErrorDialogType { @@ -59,11 +61,19 @@ fun ErrorDialog( @StringRes buttonText: Int = R.string.ok, onDismiss: () -> Unit = {} ) { - AlertDialog( + AppTheme { + AlertDialog( onDismissRequest = onDismiss, title = { Text(text = stringResource(id = title)) }, text = { Text(text = stringResource(id = message)) }, confirmButton = { PrimaryActionButton(onClick = onDismiss) { Text(text = stringResource(id = buttonText)) } }) + } +} + +@Preview +@Composable +fun ErrorDialogPreview() { + ErrorDialog(ErrorDialogType.LOGOUT_FAILED) } diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/IntroView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/IntroView.kt index 4b6cdde..c8dde66 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/IntroView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/IntroView.kt @@ -16,14 +16,17 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tailscale.ipn.R +import com.tailscale.ipn.ui.theme.AppTheme @Composable fun IntroView(onContinue: () -> Unit) { @@ -57,3 +60,9 @@ fun IntroView(onContinue: () -> Unit) { } } } + +@Composable +@Preview +fun IntroViewPreview() { + AppTheme { Surface { IntroView({}) } } +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/LoginQRView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/LoginQRView.kt index 9e3af24..695bb1e 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/LoginQRView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/LoginQRView.kt @@ -24,10 +24,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.R +import com.tailscale.ipn.ui.theme.AppTheme +import com.tailscale.ipn.ui.util.set import com.tailscale.ipn.ui.viewModel.LoginQRViewModel @OptIn(ExperimentalMaterial3Api::class) @@ -66,3 +69,11 @@ fun LoginQRView(onDismiss: () -> Unit = {}, model: LoginQRViewModel = viewModel( } } } + +@Composable +@Preview +fun LoginQRViewPreview() { + val vm = LoginQRViewModel() + vm.qrCode.set(vm.generateQRCode("https://tailscale.com", 200, 0)) + AppTheme { LoginQRView({}, vm) } +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/MainView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/MainView.kt index d35cd95..7123ee3 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/MainView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/MainView.kt @@ -59,6 +59,7 @@ import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.google.accompanist.permissions.ExperimentalPermissionsApi @@ -509,3 +510,16 @@ fun PromptPermissionsIfNecessary() { } } } + +@Preview +@Composable +fun MainViewPreview() { + val vm = MainViewModel() + MainView( + {}, + MainViewNavigation( + onNavigateToSettings = {}, + onNavigateToPeerDetails = {}, + onNavigateToExitNodes = {}), + vm) +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/ManagedByView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/ManagedByView.kt index a26c3e6..4be2d44 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/ManagedByView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/ManagedByView.kt @@ -16,6 +16,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.R @@ -46,3 +47,10 @@ fun ManagedByView(backToSettings: BackNavigation, model: IpnViewModel = viewMode } } } + +@Preview +@Composable +fun ManagedByViewPreview() { + val vm = IpnViewModel() + ManagedByView(backToSettings = {}, vm) +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt index 055e2f8..a91bd6d 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.BuildConfig import com.tailscale.ipn.R @@ -29,6 +30,7 @@ import com.tailscale.ipn.ui.Links import com.tailscale.ipn.ui.theme.link import com.tailscale.ipn.ui.theme.listItem import com.tailscale.ipn.ui.util.Lists +import com.tailscale.ipn.ui.util.set import com.tailscale.ipn.ui.viewModel.SettingsNav import com.tailscale.ipn.ui.viewModel.SettingsViewModel @@ -177,3 +179,14 @@ fun AdminTextView(onNavigateToAdminConsole: () -> Unit) { Lists.InfoItem(adminStr, onClick = onNavigateToAdminConsole) } + +@Preview +@Composable +fun SettingsPreview() { + val vm = SettingsViewModel() + vm.corpDNSEnabled.set(true) + vm.tailNetLockEnabled.set(true) + vm.isAdmin.set(true) + vm.managedByOrganization.set("Tails and Scales Inc.") + SettingsView(SettingsNav({}, {}, {}, {}, {}, {}, {}, {}, {}, {}), vm) +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/TailnetLockSetupView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/TailnetLockSetupView.kt index 6dd347b..136be0a 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/TailnetLockSetupView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/TailnetLockSetupView.kt @@ -23,6 +23,7 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.R import com.tailscale.ipn.ui.Links @@ -31,6 +32,7 @@ import com.tailscale.ipn.ui.theme.link import com.tailscale.ipn.ui.util.ClipboardValueView import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.util.LoadingIndicator +import com.tailscale.ipn.ui.util.set import com.tailscale.ipn.ui.viewModel.TailnetLockSetupViewModel import com.tailscale.ipn.ui.viewModel.TailnetLockSetupViewModelFactory @@ -115,3 +117,12 @@ fun explainerText(): AnnotatedString { } return annotatedString } + +@Composable +@Preview +fun TailnetLockSetupViewPreview() { + val vm = TailnetLockSetupViewModel() + vm.nodeKey.set("8BADF00D-EA7-1337-DEAD-BEEF") + vm.tailnetLockKey.set("C0FFEE-CAFE-50DA") + TailnetLockSetupView(backToSettings = {}, vm) +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/UserSwitcherView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/UserSwitcherView.kt index e9f3f11..9599411 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/UserSwitcherView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/UserSwitcherView.kt @@ -32,6 +32,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.R @@ -189,3 +190,10 @@ fun FusMenu(viewModel: UserSwitcherViewModel) { }) } } + +@Composable +@Preview +fun UserSwitcherViewPreview() { + val vm = UserSwitcherViewModel() + UserSwitcherView(backToSettings = {}, onNavigateHome = {}, vm) +}