Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fun AppsScreen(nav: NavHostController) {
}

@Composable
private fun AppsContent(
internal fun AppsContent(
rows: List<AppRow>,
query: String,
icons: Map<String, android.graphics.drawable.Drawable?>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ fun BrokerScreen(nav: NavHostController) {

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun BrokerContent(
internal fun BrokerContent(
config: BrokerConfig,
testResult: String?,
saving: Boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private data class LanguageOption(
)

@Composable
private fun LanguageSettingsContent(
internal fun LanguageSettingsContent(
currentTag: String?,
onPick: (String?) -> Unit,
onBack: () -> Unit,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.nyasa.notifybridge.screenshot

import androidx.compose.ui.test.onRoot
import com.github.takahirom.roborazzi.captureRoboImage
import com.nyasa.notifybridge.ui.apps.AppRow
import com.nyasa.notifybridge.ui.apps.AppsContent
import org.junit.Test

/** Baselines for the app allow-list — populated and empty (mirrors @Preview). */
class AppsScreenScreenshotTest : ScreenshotTest() {

private val rows = listOf(
AppRow("Signal", "org.thoughtcrime.securesms", true),
AppRow("Gmail", "com.google.android.gm", false),
AppRow("Slack", "com.Slack", true),
AppRow("WhatsApp", "com.whatsapp", false),
)

private fun shoot(name: String, rows: List<AppRow>) {
setScreen {
AppsContent(
rows = rows,
query = "",
icons = emptyMap(),
onQueryChange = {},
onToggle = { _, _ -> },
onNavStatus = {},
onNavBroker = {},
onNavPermissions = {},
)
}
compose.onRoot().captureRoboImage("src/test/screenshots/AppsScreen_$name.png")
}

@Test
fun populated() = shoot("populated", rows)

@Test
fun empty() = shoot("empty", emptyList())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.nyasa.notifybridge.screenshot

import androidx.compose.ui.test.onRoot
import com.github.takahirom.roborazzi.captureRoboImage
import com.nyasa.notifybridge.domain.model.BrokerConfig
import com.nyasa.notifybridge.domain.model.TlsMode
import com.nyasa.notifybridge.ui.broker.BrokerContent
import org.junit.Test

/** Baselines for the broker config form — empty and filled+TLS+connected. */
class BrokerScreenScreenshotTest : ScreenshotTest() {

private fun shoot(name: String, config: BrokerConfig, testResult: String?) {
setScreen {
BrokerContent(
config = config,
testResult = testResult,
saving = false,
onHostChange = {},
onPortChange = {},
onDeviceNameChange = {},
onUsernameChange = {},
onPasswordChange = {},
onTlsModeChange = {},
onPickCertFile = {},
onTest = {},
onSave = {},
onBack = {},
onNavStatus = {},
onNavApps = {},
onNavPermissions = {},
)
}
compose.onRoot().captureRoboImage("src/test/screenshots/BrokerScreen_$name.png")
}

@Test
fun empty() = shoot("empty", BrokerConfig(), testResult = null)

@Test
fun filledTlsConnected() = shoot(
"filled_tls_connected",
BrokerConfig(host = "192.168.1.10", port = 1883, deviceName = "phone", tlsMode = TlsMode.SYSTEM_CA),
testResult = "Connected",
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.nyasa.notifybridge.screenshot

import androidx.compose.ui.test.onRoot
import com.github.takahirom.roborazzi.captureRoboImage
import com.nyasa.notifybridge.ui.language.LanguageSettingsContent
import org.junit.Test

/** Baselines for the language picker — system default and a selected locale. */
class LanguageSettingsScreenshotTest : ScreenshotTest() {

private fun shoot(name: String, currentTag: String?) {
setScreen {
LanguageSettingsContent(currentTag = currentTag, onPick = {}, onBack = {})
}
compose.onRoot().captureRoboImage("src/test/screenshots/LanguageSettings_$name.png")
}

@Test
fun systemDefault() = shoot("system_default", currentTag = null)

@Test
fun frenchSelected() = shoot("french_selected", currentTag = "fr")
}
Binary file added app/src/test/screenshots/AppsScreen_empty.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/test/screenshots/BrokerScreen_empty.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions config/detekt/baseline-debug.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<ID>ArgumentListWrapping:OnboardingScreen.kt$(alpha = 0.6f)</ID>
<ID>ArgumentListWrapping:OnboardingViewModel.kt$(when { !notifAccess -&gt; OnboardingStep.GRANT_ACCESS !brokerSet -&gt; OnboardingStep.CONNECT_BROKER !appsChosen -&gt; OnboardingStep.CHOOSE_APPS else -&gt; OnboardingStep.DONE })</ID>
<ID>ArgumentListWrapping:Theme.kt$( primary = Teal, background = BgBase, surface = Surface, error = ErrorRed)</ID>
<ID>CyclomaticComplexMethod:BrokerScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable private fun BrokerContent( config: BrokerConfig, testResult: String?, saving: Boolean, onHostChange: (String) -&gt; Unit, onPortChange: (String) -&gt; Unit, onDeviceNameChange: (String) -&gt; Unit, onUsernameChange: (String) -&gt; Unit, onPasswordChange: (String) -&gt; Unit, onTlsModeChange: (TlsMode) -&gt; Unit, onPickCertFile: () -&gt; Unit, onTest: () -&gt; Unit, onSave: () -&gt; Unit, onBack: () -&gt; Unit, onNavStatus: () -&gt; Unit, onNavApps: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>CyclomaticComplexMethod:BrokerScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable internal fun BrokerContent( config: BrokerConfig, testResult: String?, saving: Boolean, onHostChange: (String) -&gt; Unit, onPortChange: (String) -&gt; Unit, onDeviceNameChange: (String) -&gt; Unit, onUsernameChange: (String) -&gt; Unit, onPasswordChange: (String) -&gt; Unit, onTlsModeChange: (TlsMode) -&gt; Unit, onPickCertFile: () -&gt; Unit, onTest: () -&gt; Unit, onSave: () -&gt; Unit, onBack: () -&gt; Unit, onNavStatus: () -&gt; Unit, onNavApps: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>FinalNewline:NotifyBridgeApp.kt$com.nyasa.notifybridge.NotifyBridgeApp.kt</ID>
<ID>IgnoredReturnValue:HiveMqClientManager.kt$HiveMqClientManager$sslWithDefaultConfig()</ID>
<ID>ImportOrdering:BrokerScreen.kt$import android.app.Activity import android.content.Intent import android.view.WindowManager import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Apps import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Dashboard import androidx.compose.material.icons.filled.Lock import androidx.compose.material.icons.filled.Router import androidx.compose.material.icons.filled.Security import androidx.compose.material.icons.filled.Shield import androidx.compose.material.icons.filled.Visibility import androidx.compose.material.icons.filled.VisibilityOff import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItemDefaults import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Switch import androidx.compose.material3.SwitchDefaults import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember 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.platform.LocalView import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import com.nyasa.notifybridge.domain.model.BrokerConfig import com.nyasa.notifybridge.domain.model.TlsMode import com.nyasa.notifybridge.localization.Dictionary import com.nyasa.notifybridge.localization.back import com.nyasa.notifybridge.localization.certificateHeading import com.nyasa.notifybridge.localization.comingSoon import com.nyasa.notifybridge.localization.fieldDevice import com.nyasa.notifybridge.localization.fieldDevicePlaceholder import com.nyasa.notifybridge.localization.fieldDeviceSupporting import com.nyasa.notifybridge.localization.fieldHost import com.nyasa.notifybridge.localization.fieldHostPlaceholder import com.nyasa.notifybridge.localization.fieldPassword import com.nyasa.notifybridge.localization.fieldPort import com.nyasa.notifybridge.localization.fieldPortPlaceholder import com.nyasa.notifybridge.localization.fieldUsername import com.nyasa.notifybridge.localization.localized import com.nyasa.notifybridge.localization.navAccess import com.nyasa.notifybridge.localization.navApps import com.nyasa.notifybridge.localization.navBroker import com.nyasa.notifybridge.localization.navStatus import com.nyasa.notifybridge.localization.passwordHide import com.nyasa.notifybridge.localization.passwordShow import com.nyasa.notifybridge.localization.pinnedCertNote import com.nyasa.notifybridge.localization.saveButton import com.nyasa.notifybridge.localization.saveButtonSaving import com.nyasa.notifybridge.localization.sectionAuthentication import com.nyasa.notifybridge.localization.sectionConnection import com.nyasa.notifybridge.localization.sectionTls import com.nyasa.notifybridge.localization.selectCertFile import com.nyasa.notifybridge.localization.testButton import com.nyasa.notifybridge.localization.testResultConnected import com.nyasa.notifybridge.localization.tlsPinnedButton import com.nyasa.notifybridge.localization.tlsSystemCaButton import com.nyasa.notifybridge.localization.title import com.nyasa.notifybridge.localization.useTls import com.nyasa.notifybridge.service.MqttForegroundService import com.nyasa.notifybridge.ui.theme.Amber import com.nyasa.notifybridge.ui.theme.NotifyBridgeTheme import com.nyasa.notifybridge.ui.theme.Teal</ID>
Expand All @@ -48,8 +48,8 @@
<ID>InjectDispatcher:NotifListenerService.kt$NotifListenerService$IO</ID>
<ID>InjectDispatcher:StatusScreen.kt$IO</ID>
<ID>LongMethod:AppsScreen.kt$@Composable private fun AppRowItem( row: AppRow, icon: android.graphics.drawable.Drawable?, onToggle: (Boolean) -&gt; Unit, )</ID>
<ID>LongMethod:AppsScreen.kt$@Composable private fun AppsContent( rows: List&lt;AppRow&gt;, query: String, icons: Map&lt;String, android.graphics.drawable.Drawable?&gt;, onQueryChange: (String) -&gt; Unit, onToggle: (String, Boolean) -&gt; Unit, onNavStatus: () -&gt; Unit, onNavBroker: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>LongMethod:BrokerScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable private fun BrokerContent( config: BrokerConfig, testResult: String?, saving: Boolean, onHostChange: (String) -&gt; Unit, onPortChange: (String) -&gt; Unit, onDeviceNameChange: (String) -&gt; Unit, onUsernameChange: (String) -&gt; Unit, onPasswordChange: (String) -&gt; Unit, onTlsModeChange: (TlsMode) -&gt; Unit, onPickCertFile: () -&gt; Unit, onTest: () -&gt; Unit, onSave: () -&gt; Unit, onBack: () -&gt; Unit, onNavStatus: () -&gt; Unit, onNavApps: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>LongMethod:AppsScreen.kt$@Composable internal fun AppsContent( rows: List&lt;AppRow&gt;, query: String, icons: Map&lt;String, android.graphics.drawable.Drawable?&gt;, onQueryChange: (String) -&gt; Unit, onToggle: (String, Boolean) -&gt; Unit, onNavStatus: () -&gt; Unit, onNavBroker: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>LongMethod:BrokerScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable internal fun BrokerContent( config: BrokerConfig, testResult: String?, saving: Boolean, onHostChange: (String) -&gt; Unit, onPortChange: (String) -&gt; Unit, onDeviceNameChange: (String) -&gt; Unit, onUsernameChange: (String) -&gt; Unit, onPasswordChange: (String) -&gt; Unit, onTlsModeChange: (TlsMode) -&gt; Unit, onPickCertFile: () -&gt; Unit, onTest: () -&gt; Unit, onSave: () -&gt; Unit, onBack: () -&gt; Unit, onNavStatus: () -&gt; Unit, onNavApps: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>LongMethod:HiveMqClientManager.kt$HiveMqClientManager$override suspend fun connect(config: BrokerConfig)</ID>
<ID>LongMethod:OnboardingScreen.kt$@Composable internal fun OnboardingContent( state: OnboardingUiState, onGrantAccess: () -&gt; Unit, onConfigureBroker: () -&gt; Unit, onChooseApps: () -&gt; Unit, )</ID>
<ID>LongMethod:OnboardingScreen.kt$@Composable private fun StepCard( number: Int, title: String, description: String, buttonLabel: String, buttonIcon: (@Composable () -&gt; Unit)?, isActive: Boolean, isEnabled: Boolean, onClick: () -&gt; Unit, )</ID>
Expand Down
6 changes: 3 additions & 3 deletions config/detekt/baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<ID>ArgumentListWrapping:SettingsRepositoryImplTest.kt$SettingsRepositoryImplTest$(ApplicationProvider.getApplicationContext&lt;android.content.Context&gt;() .cacheDir, "t${System.nanoTime()}.preferences_pb")</ID>
<ID>ArgumentListWrapping:SettingsRepositoryImplTest.kt$SettingsRepositoryImplTest$(host = "h", port = 8883, tlsMode = TlsMode.PINNED, deviceName = "Pixel 7")</ID>
<ID>ArgumentListWrapping:Theme.kt$( primary = Teal, background = BgBase, surface = Surface, error = ErrorRed)</ID>
<ID>CyclomaticComplexMethod:BrokerScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable private fun BrokerContent( config: BrokerConfig, testResult: String?, saving: Boolean, onHostChange: (String) -&gt; Unit, onPortChange: (String) -&gt; Unit, onDeviceNameChange: (String) -&gt; Unit, onUsernameChange: (String) -&gt; Unit, onPasswordChange: (String) -&gt; Unit, onTlsModeChange: (TlsMode) -&gt; Unit, onPickCertFile: () -&gt; Unit, onTest: () -&gt; Unit, onSave: () -&gt; Unit, onBack: () -&gt; Unit, onNavStatus: () -&gt; Unit, onNavApps: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>CyclomaticComplexMethod:BrokerScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable internal fun BrokerContent( config: BrokerConfig, testResult: String?, saving: Boolean, onHostChange: (String) -&gt; Unit, onPortChange: (String) -&gt; Unit, onDeviceNameChange: (String) -&gt; Unit, onUsernameChange: (String) -&gt; Unit, onPasswordChange: (String) -&gt; Unit, onTlsModeChange: (TlsMode) -&gt; Unit, onPickCertFile: () -&gt; Unit, onTest: () -&gt; Unit, onSave: () -&gt; Unit, onBack: () -&gt; Unit, onNavStatus: () -&gt; Unit, onNavApps: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>EmptyFunctionBlock:BrokerSeedTest.kt$BrokerSeedTest.FakeSettings${}</ID>
<ID>EmptyFunctionBlock:DrainPrunesOutboxTest.kt$RecordingOutbox${}</ID>
<ID>EmptyFunctionBlock:UseCasesTest.kt$MemOutbox${}</ID>
Expand All @@ -61,8 +61,8 @@
<ID>Indentation:NotificationMapperImpl.kt$NotificationMapperImpl$ </ID>
<ID>Indentation:StatusScreen.kt$ </ID>
<ID>LongMethod:AppsScreen.kt$@Composable private fun AppRowItem( row: AppRow, icon: android.graphics.drawable.Drawable?, onToggle: (Boolean) -&gt; Unit, )</ID>
<ID>LongMethod:AppsScreen.kt$@Composable private fun AppsContent( rows: List&lt;AppRow&gt;, query: String, icons: Map&lt;String, android.graphics.drawable.Drawable?&gt;, onQueryChange: (String) -&gt; Unit, onToggle: (String, Boolean) -&gt; Unit, onNavStatus: () -&gt; Unit, onNavBroker: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>LongMethod:BrokerScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable private fun BrokerContent( config: BrokerConfig, testResult: String?, saving: Boolean, onHostChange: (String) -&gt; Unit, onPortChange: (String) -&gt; Unit, onDeviceNameChange: (String) -&gt; Unit, onUsernameChange: (String) -&gt; Unit, onPasswordChange: (String) -&gt; Unit, onTlsModeChange: (TlsMode) -&gt; Unit, onPickCertFile: () -&gt; Unit, onTest: () -&gt; Unit, onSave: () -&gt; Unit, onBack: () -&gt; Unit, onNavStatus: () -&gt; Unit, onNavApps: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>LongMethod:AppsScreen.kt$@Composable internal fun AppsContent( rows: List&lt;AppRow&gt;, query: String, icons: Map&lt;String, android.graphics.drawable.Drawable?&gt;, onQueryChange: (String) -&gt; Unit, onToggle: (String, Boolean) -&gt; Unit, onNavStatus: () -&gt; Unit, onNavBroker: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>LongMethod:BrokerScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable internal fun BrokerContent( config: BrokerConfig, testResult: String?, saving: Boolean, onHostChange: (String) -&gt; Unit, onPortChange: (String) -&gt; Unit, onDeviceNameChange: (String) -&gt; Unit, onUsernameChange: (String) -&gt; Unit, onPasswordChange: (String) -&gt; Unit, onTlsModeChange: (TlsMode) -&gt; Unit, onPickCertFile: () -&gt; Unit, onTest: () -&gt; Unit, onSave: () -&gt; Unit, onBack: () -&gt; Unit, onNavStatus: () -&gt; Unit, onNavApps: () -&gt; Unit, onNavPermissions: () -&gt; Unit, )</ID>
<ID>LongMethod:HiveMqClientManager.kt$HiveMqClientManager$override suspend fun connect(config: BrokerConfig)</ID>
<ID>LongMethod:OnboardingScreen.kt$@Composable internal fun OnboardingContent( state: OnboardingUiState, onGrantAccess: () -&gt; Unit, onConfigureBroker: () -&gt; Unit, onChooseApps: () -&gt; Unit, )</ID>
<ID>LongMethod:OnboardingScreen.kt$@Composable private fun StepCard( number: Int, title: String, description: String, buttonLabel: String, buttonIcon: (@Composable () -&gt; Unit)?, isActive: Boolean, isEnabled: Boolean, onClick: () -&gt; Unit, )</ID>
Expand Down
Loading
Loading