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
4 changes: 0 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import java.security.MessageDigest
import java.util.*
import okhttp3.OkHttpClient
import okhttp3.Request
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

val testConfig = Properties()
Expand Down Expand Up @@ -199,7 +196,6 @@ protobuf {
}
}


afterEvaluate {
tasks.named("clean") {
doLast {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,11 @@ import androidx.test.espresso.Espresso.pressBack
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import io.github.chrisimx.esclmockserver.EsclMockServer
import io.github.chrisimx.esclmockserver.EsclMockServerArgs
import io.github.chrisimx.esclmockserver.esclMockServerArgs
import io.github.chrisimx.scanbridge.datastore.appSettingsStore
import io.github.chrisimx.scanbridge.datastore.lastRouteStore
import io.github.chrisimx.scanbridge.datastore.shownMessagesStore
import io.github.chrisimx.scanbridge.datastore.updateSettings
import io.github.chrisimx.scanbridge.proto.copy
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Before
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.github.chrisimx.scanbridge.screenshot

import android.content.Context
import android.util.Log
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.junit4.createAndroidComposeRule
Expand All @@ -13,17 +12,13 @@ import androidx.compose.ui.test.swipeUp
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import io.github.chrisimx.esclmockserver.EsclMockServer
import io.github.chrisimx.esclmockserver.esclMockServerArgs
import io.github.chrisimx.scanbridge.BuildConfig
import io.github.chrisimx.scanbridge.MainActivity
import io.github.chrisimx.scanbridge.datastore.appSettingsStore
import io.github.chrisimx.scanbridge.datastore.lastRouteStore
import io.github.chrisimx.scanbridge.datastore.shownMessagesStore
import io.github.chrisimx.scanbridge.datastore.updateSettings
import io.github.chrisimx.scanbridge.proto.copy
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
Expand All @@ -46,8 +41,7 @@ class ScanBridgeScreenshotTest {
fun startServer(): EsclMockServer {
val context = InstrumentationRegistry.getInstrumentation().context

val imageFile = copyAssetToByteArray( context, "scan-1.jpg")

val imageFile = copyAssetToByteArray(context, "scan-1.jpg")

val server = EsclMockServer {
servedImage = imageFile
Expand All @@ -56,10 +50,9 @@ class ScanBridgeScreenshotTest {
return server
}

fun copyAssetToByteArray(testContext: Context, assetName: String): ByteArray =
testContext.assets.open(assetName).use {
it.readBytes()
}
fun copyAssetToByteArray(testContext: Context, assetName: String): ByteArray = testContext.assets.open(assetName).use {
it.readBytes()
}

@Before
fun cleanupForTest() {
Expand Down
71 changes: 54 additions & 17 deletions app/src/main/java/io/github/chrisimx/scanbridge/ScannerBrowser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
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.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -42,11 +45,13 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.getSystemService
import androidx.navigation.NavController
import io.github.chrisimx.scanbridge.data.model.EditedCustomScanner
import io.github.chrisimx.scanbridge.data.ui.CustomScannerViewModel
import io.github.chrisimx.scanbridge.db.entities.CustomScanner
import io.github.chrisimx.scanbridge.uicomponents.FoundScannerItem
import io.github.chrisimx.scanbridge.uicomponents.FullScreenError
import io.github.chrisimx.scanbridge.uicomponents.dialog.CustomScannerDialog
import io.github.chrisimx.scanbridge.uicomponents.dialog.DeletionDialog
import io.ktor.http.Url
import java.util.*
import kotlin.uuid.ExperimentalUuidApi
Expand Down Expand Up @@ -78,7 +83,9 @@ fun ScannerList(
navController: NavController,
statefulScannerMap: SnapshotStateMap<String, DiscoveredScanner>,
statefulScannerMapSecure: SnapshotStateMap<String, DiscoveredScanner>,
customScannerViewModel: CustomScannerViewModel
customScannerViewModel: CustomScannerViewModel,
setScannerToDelete: (Uuid?) -> Unit,
setScannerToEdit: (EditedCustomScanner?) -> Unit
) {
val customScanners by customScannerViewModel.customScanners.collectAsState()

Expand Down Expand Up @@ -129,7 +136,12 @@ fun ScannerList(
customScanner.url.toString(),
navController,
{
customScannerViewModel.deleteScanner(customScanner)
setScannerToDelete(customScanner.uuid)
},
{
setScannerToEdit(
EditedCustomScanner.EditingOld(customScanner)
)
}
)
}
Expand All @@ -152,20 +164,24 @@ fun ScannerList(
fun ScannerBrowser(
innerPadding: PaddingValues,
navController: NavController,
showCustomDialog: Boolean,
setShowCustomDialog: (Boolean) -> Unit,
currentlyEditedScanner: EditedCustomScanner?,
setEditedCustomDialog: (EditedCustomScanner?) -> Unit,
statefulScannerMap: SnapshotStateMap<String, DiscoveredScanner>,
statefulScannerMapSecure: SnapshotStateMap<String, DiscoveredScanner>
) {
val customScannerViewModel: CustomScannerViewModel = koinViewModel()
val customScanners by customScannerViewModel.customScanners.collectAsState()

var deletionScheduledScanner: Uuid? by remember { mutableStateOf(null) }

AnimatedContent(
targetState = statefulScannerMap.isNotEmpty() || customScanners.isNotEmpty(),
label = "ScannerList"
) {
if (it) {
ScannerList(innerPadding, navController, statefulScannerMap, statefulScannerMapSecure, customScannerViewModel)
ScannerList(innerPadding, navController, statefulScannerMap, statefulScannerMapSecure, customScannerViewModel, {
deletionScheduledScanner = it
}, setEditedCustomDialog)
} else {
FullScreenError(
R.drawable.twotone_wifi_find_24,
Expand All @@ -174,26 +190,47 @@ fun ScannerBrowser(
}
}

if (showCustomDialog) {
val deletionScheduledScannerImmutable = deletionScheduledScanner
if (deletionScheduledScannerImmutable != null) {
DeletionDialog(
R.string.custom_scanner_deletion,
R.string.custom_scanner_deletion_confirmation,
onDismiss = { deletionScheduledScanner = null },
onConfirmed = {
customScannerViewModel.deleteScannerByUuid(deletionScheduledScannerImmutable)
deletionScheduledScanner = null
}
)
}

if (currentlyEditedScanner != null) {
val context = LocalContext.current

CustomScannerDialog(
onDismiss = { setShowCustomDialog(false) },
onConnectClicked = { name, url, save ->
onDismiss = { setEditedCustomDialog(null) },
onConnectClicked = { name, url, save, navigate ->
val name = name.ifEmpty { context.getString(R.string.custom_scanner) }
val url = if (url.toString().endsWith("/")) url.toString() else "$url/"
val sessionID = Uuid.random()
val uuid = when (currentlyEditedScanner) {
is EditedCustomScanner.EditingOld -> currentlyEditedScanner.scanner.uuid
EditedCustomScanner.New -> Uuid.random()
}
if (save) {
customScannerViewModel.addScanner(CustomScanner(Uuid.random(), name, Url(url)))
customScannerViewModel.addScanner(CustomScanner(uuid, name, Url(url)))
}
setShowCustomDialog(false)
navController.navigate(
ScannerRoute(
name,
url,
sessionID.toString()
setEditedCustomDialog(null)
if (navigate) {
navController.navigate(
ScannerRoute(
name,
url,
sessionID.toString()
)
)
)
}
}
},
currentlyEditedScanner
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,8 @@ fun ScanningScreen(

if (scanningViewModel.scanningScreenData.confirmPageDeleteDialogShown) {
DeletionDialog(
R.string.delete_current_page,
R.string.page_deletion_confirmation,
onDismiss = { scanningViewModel.setDeletePageDialogShown(false) },
onConfirmed = {
Timber.d("Deleting page")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import io.github.chrisimx.scanbridge.data.model.EditedCustomScanner
import timber.log.Timber

@OptIn(ExperimentalMaterial3Api::class)
Expand All @@ -68,8 +69,8 @@ data class StartupScreen(
val screenComposable: @Composable (
innerPadding: PaddingValues,
navController: NavController,
showCustomDialog: Boolean,
setShowCustomDialog: (Boolean) -> Unit,
showCustomDialog: EditedCustomScanner?,
setShowCustomDialog: (EditedCustomScanner?) -> Unit,
statefulScannerMap: SnapshotStateMap<String, DiscoveredScanner>,
statefulScannerMapSecure: SnapshotStateMap<String, DiscoveredScanner>
) -> Unit
Expand Down Expand Up @@ -109,7 +110,7 @@ fun StartupScreen(navController: NavController) {
}
}

var showCustomDialog by remember { mutableStateOf(false) }
var showCustomDialog: EditedCustomScanner? by remember { mutableStateOf(null) }

Scaffold(
modifier = Modifier.fillMaxSize(),
Expand Down Expand Up @@ -137,7 +138,7 @@ fun StartupScreen(navController: NavController) {
FloatingActionButton(
modifier = Modifier.testTag("custom_scanner_fab"),
onClick = {
showCustomDialog = true
showCustomDialog = EditedCustomScanner.New
}
) {
Icon(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.github.chrisimx.scanbridge.data.model

import io.github.chrisimx.scanbridge.db.entities.CustomScanner

sealed class EditedCustomScanner {
data object New : EditedCustomScanner()
data class EditingOld(val scanner: CustomScanner) : EditedCustomScanner()
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import androidx.lifecycle.viewModelScope
import io.github.chrisimx.scanbridge.db.ScanBridgeDb
import io.github.chrisimx.scanbridge.db.entities.CustomScanner
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
Expand All @@ -42,10 +43,19 @@ class CustomScannerViewModel(application: Application, appDb: ScanBridgeDb) : An
}
}

suspend fun loadScannerByUuid(scanner: Uuid): CustomScanner? = customScannerDao.getById(scanner)

@OptIn(ExperimentalUuidApi::class)
fun deleteScanner(scanner: CustomScanner) {
viewModelScope.launch {
customScannerDao.delete(scanner)
}
}

@OptIn(ExperimentalUuidApi::class)
fun deleteScannerByUuid(scanner: Uuid) {
viewModelScope.launch {
customScannerDao.deleteById(scanner)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package io.github.chrisimx.scanbridge.db.daos
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import io.github.chrisimx.scanbridge.db.entities.CustomScanner
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid
import kotlinx.coroutines.flow.Flow

@Dao
Expand All @@ -18,12 +20,18 @@ interface CustomScannerDao {
@Query("SELECT * FROM customscanners")
suspend fun getAll(): List<CustomScanner>

@Insert
@Query("SELECT * FROM customscanners WHERE uuid = :id")
suspend fun getById(id: Uuid): CustomScanner?

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(vararg scanners: CustomScanner)

@Update
suspend fun update(vararg users: CustomScanner)

@Delete
suspend fun delete(scanner: CustomScanner)

@Query("DELETE FROM customscanners WHERE uuid = :id")
suspend fun deleteById(id: Uuid)
}
Loading
Loading