Compare commits

..
Author SHA1 Message Date
nacabaro fa8641c874 Added logger
Logger is a class (AppLogger) that sits between Log class and allows me to store debug information inside the app.

This debug information can be seen at anytime from within the application settings, and it's not sent out to any server.
2026-05-19 22:29:41 +00:00
nacabaro 366f425539 Updated libraries
Moved library definitions to the catalog, and updated the catalog
2026-01-28 02:05:43 +01:00
nacabaro 37076a9bf0 VERSION UP 2026-01-25 20:00:55 +01:00
nacabaroandGitHub 8c99046edb Merge pull request #47 from nacabaro/specialMissions/fix
Fix Special Missions a bit more
2026-01-25 19:58:39 +01:00
18 changed files with 177 additions and 78 deletions
+28 -20
View File
@@ -1,21 +1,23 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
id("com.google.devtools.ksp") version "2.0.21-1.0.27"
id("com.google.devtools.ksp") version "2.3.0"
id("com.google.protobuf")
}
android {
namespace = "com.github.nacabaro.vbhelper"
compileSdk = 35
compileSdk = 36
defaultConfig {
applicationId = "com.github.nacabaro.vbhelper"
minSdk = 28
targetSdk = 35
targetSdk = 36
versionCode = 1
versionName = "Alpha 0.6.2"
versionName = "Alpha 0.6.3.2"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
@@ -33,9 +35,7 @@ android {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
@@ -45,14 +45,17 @@ android {
}
}
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_11
}
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:4.27.0"
}
// Generates the java Protobuf-lite code for the Protobufs in this project. See
// https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
// for more information.
generateProtoTasks {
all().forEach { task ->
task.builtins {
@@ -68,10 +71,13 @@ dependencies {
implementation(libs.androidx.room.runtime)
implementation(libs.vb.nfc.reader)
implementation(libs.dim.reader)
ksp(libs.androidx.room.compiler)
annotationProcessor(libs.androidx.room.compiler)
implementation(libs.androidx.core.ktx)
implementation("androidx.room:room-ktx:2.6.1")
implementation(libs.androidx.room.ktx)
implementation(libs.androidx.datastore.preferences)
implementation(libs.androidx.navigation.compose)
implementation(libs.material)
implementation(libs.protobuf.javalite)
implementation(libs.androidx.compose.material)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
@@ -80,16 +86,18 @@ dependencies {
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.androidx.compose.material.icons.extended)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
testImplementation(libs.junit)
ksp(libs.androidx.room.compiler)
annotationProcessor(libs.androidx.room.compiler)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
implementation("androidx.navigation:navigation-compose:2.7.0")
implementation("com.google.android.material:material:1.2.0")
implementation(libs.protobuf.javalite)
implementation("androidx.compose.material:material")
implementation("androidx.datastore:datastore-preferences:1.1.7")
}
@@ -1,7 +1,6 @@
package com.github.nacabaro.vbhelper
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
@@ -68,13 +67,10 @@ class MainActivity : ComponentActivity() {
)
}
}
Log.i("MainActivity", "Activity onCreated")
}
override fun onPause() {
super.onPause()
Log.i("MainActivity", "onPause")
for(activityListener in onActivityLifecycleListeners) {
activityListener.value.onPause()
}
@@ -82,7 +78,6 @@ class MainActivity : ComponentActivity() {
override fun onResume() {
super.onResume()
Log.i("MainActivity", "Resume")
for(activityListener in onActivityLifecycleListeners) {
activityListener.value.onResume()
}
@@ -0,0 +1,25 @@
import android.util.Log
object AppLogger {
private val logs = StringBuilder()
fun d(tag: String, message: String) {
Log.d(tag, message)
append("DEBUG", tag, message)
}
fun e(tag: String, message: String, tr: Throwable? = null) {
Log.e(tag, message, tr)
append("ERROR", tag, message + (tr?.stackTraceToString() ?: ""))
}
private fun append(level: String, tag: String, message: String) {
logs.append("${System.currentTimeMillis()} [$level][$tag] $message\n")
}
fun getLogs(): String = logs.toString()
fun clear() {
logs.clear()
}
}
@@ -36,6 +36,7 @@ import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenContr
import com.github.nacabaro.vbhelper.screens.cardScreen.CardAdventureScreen
import com.github.nacabaro.vbhelper.screens.cardScreen.CardScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.settingsScreen.CreditsScreen
import com.github.nacabaro.vbhelper.screens.settingsScreen.LoggerScreen
import com.github.nacabaro.vbhelper.screens.spriteViewer.SpriteViewerControllerImpl
import com.github.nacabaro.vbhelper.screens.storageScreen.StorageScreenControllerImpl
import com.github.nacabaro.vbhelper.source.StorageRepository
@@ -182,6 +183,11 @@ fun AppNavigation(
)
}
}
composable(NavigationItems.Logger.route) {
LoggerScreen(
navController = navController
)
}
}
}
}
@@ -98,4 +98,10 @@ sealed class NavigationItems(
R.drawable.baseline_data_24,
R.string.nav_credits
)
object Logger : NavigationItems(
"Logger",
R.drawable.baseline_bug_report,
R.string.nav_logs
)
}
@@ -1,6 +1,5 @@
package com.github.nacabaro.vbhelper.screens.cardScreen
import android.util.Log
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
@@ -98,8 +97,8 @@ fun CardsScreen(
selectedCard.value = null
},
onRename = { newName ->
Log.d("CardsScreen", "New name: $newName")
Log.d("CardsScreen", "Card: ${selectedCard.value.toString()}")
AppLogger.d("CardsScreen", "New name: $newName")
AppLogger.d("CardsScreen", "Card: ${selectedCard.value.toString()}")
cardScreenController
.renameCard(
cardId = selectedCard.value!!.cardId,
@@ -6,7 +6,6 @@ import android.nfc.Tag
import android.nfc.tech.NfcA
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
@@ -127,18 +126,18 @@ class ScanScreenControllerImpl(
handleTag(secrets) { tagCommunicator ->
try {
if (nfcCharacter is VBNfcCharacter) {
Log.d("SendCharacter", "VBNfcCharacter")
AppLogger.d("SendCharacter", "VBNfcCharacter")
val castNfcCharacter: VBNfcCharacter = nfcCharacter
tagCommunicator.sendCharacter(castNfcCharacter)
} else if (nfcCharacter is BENfcCharacter) {
Log.d("SendCharacter", "BENfcCharacter")
AppLogger.d("SendCharacter", "BENfcCharacter")
val castNfcCharacter: BENfcCharacter = nfcCharacter
tagCommunicator.sendCharacter(castNfcCharacter)
}
onComplete.invoke()
componentActivity.getString(R.string.scan_sent_character_success)
} catch (e: Throwable) {
Log.e("TAG", e.stackTraceToString())
AppLogger.e("TAG", e.stackTraceToString())
componentActivity.getString(R.string.scan_error_generic)
}
}
@@ -178,7 +177,7 @@ class ScanScreenControllerImpl(
)
val character = nfcGenerator.characterToNfc(characterId)
Log.d("CharacterType", character.toString())
AppLogger.d("CharacterType", character.toString())
return character
}
@@ -2,7 +2,6 @@ package com.github.nacabaro.vbhelper.screens.scanScreen.converters
import android.icu.util.Calendar
import android.icu.util.TimeZone
import android.util.Log
import androidx.activity.ComponentActivity
import com.github.cfogrady.vbnfc.be.BENfcCharacter
import com.github.cfogrady.vbnfc.be.FirmwareVersion
@@ -161,7 +160,7 @@ class ToNfcConverter(
}
nfcVitalsHistory.map {
Log.d("NFC", it.toString())
AppLogger.d("NFC", it.toString())
}
return nfcVitalsHistory
@@ -247,7 +246,7 @@ class ToNfcConverter(
val calendar = android.icu.util.GregorianCalendar(TimeZone.getTimeZone("UTC"))
calendar.time = date
Log.d(
AppLogger.d(
"TransformationHistory",
"Year: ${calendar.get(Calendar.YEAR)}, " +
"Month: ${calendar.get(Calendar.MONTH) + 1}, " +
@@ -0,0 +1,44 @@
package com.github.nacabaro.vbhelper.screens.settingsScreen
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.R
import com.github.nacabaro.vbhelper.components.TopBanner
@Composable
fun LoggerScreen(
navController: NavController
) {
Scaffold (
topBar = {
TopBanner(
text = stringResource(R.string.logs_title),
onBackClick = {
navController.popBackStack()
}
)
},
modifier = Modifier
.fillMaxSize()
) { contentPadding ->
Column (
modifier = Modifier
.padding(top = contentPadding.calculateTopPadding())
) {
Text(
text = AppLogger.getLogs(),
modifier = Modifier
.verticalScroll(rememberScrollState())
)
}
}
}
@@ -1,7 +1,6 @@
package com.github.nacabaro.vbhelper.screens.settingsScreen
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -24,6 +23,7 @@ import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.navigation.NavigationItems
import com.github.nacabaro.vbhelper.R
import androidx.core.net.toUri
@Composable
@@ -80,10 +80,16 @@ fun SettingsScreen(
) {
val browserIntent = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://github.com/nacabaro/vbhelper/")
"https://github.com/nacabaro/vbhelper/".toUri()
)
context.startActivity(browserIntent)
}
SettingsEntry(
title = stringResource(R.string.settings_logs_title),
description = stringResource(R.string.settings_logs_desc)
) {
navController.navigate(NavigationItems.Logger.route)
}
SettingsSection(title = stringResource(R.string.settings_section_data))
SettingsEntry(
@@ -1,6 +1,5 @@
package com.github.nacabaro.vbhelper.screens.settingsScreen.controllers
import android.util.Log
import com.github.cfogrady.vb.dim.card.BemCard
import com.github.cfogrady.vb.dim.card.DimCard
import com.github.cfogrady.vb.dim.card.DimReader
@@ -154,7 +153,7 @@ class CardImportController(
cardId: Long,
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
) {
Log.d("importAdventureMissions", "Importing adventure missions")
AppLogger.d("importAdventureMissions", "Importing adventure missions")
if (card is BemCard) {
card.adventureLevels.levels.forEach {
database
@@ -190,13 +189,13 @@ class CardImportController(
cardId: Long,
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
) {
Log.d("importCardFusions", "Importing card fusions")
AppLogger.d("importCardFusions", "Importing card fusions")
if (card is DimCard) {
card
.attributeFusions
.entries
.forEach {
Log.d("importCardFusions", "Importing fusion: ${it.attribute1Fusion}")
AppLogger.d("importCardFusions", "Importing fusion: ${it.attribute1Fusion}")
if (it.attribute1Fusion != 65535 && it.characterIndex != 65535) {
database
.cardFusionsDao()
@@ -2,7 +2,6 @@ package com.github.nacabaro.vbhelper.screens.settingsScreen.controllers
import android.net.Uri
import android.provider.OpenableColumns
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
@@ -41,7 +40,7 @@ class DatabaseManagementController(
componentActivity.finishAffinity()
}
} catch (e: Exception) {
Log.e("ScanScreenController", "Error exporting database $e")
AppLogger.e("ScanScreenController", "Error exporting database $e")
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, "Error exporting database: ${e.message}", Toast.LENGTH_LONG).show()
}
@@ -84,7 +83,7 @@ class DatabaseManagementController(
componentActivity.finishAffinity()
}
} catch (e: Exception) {
Log.e("ScanScreenController", "Error importing database $e")
AppLogger.e("ScanScreenController", "Error importing database $e")
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, "Error importing database: ${e.message}", Toast.LENGTH_LONG).show()
}
@@ -1,7 +1,6 @@
package com.github.nacabaro.vbhelper.screens.spriteViewer
import android.graphics.Bitmap
import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@@ -13,7 +12,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.unit.dp
@@ -27,8 +25,6 @@ fun SpriteViewer(
) {
val spriteList = remember { mutableStateListOf<Bitmap>() }
Log.d("SpriteViewer", "spriteList: $spriteList")
LaunchedEffect(spriteViewerController) {
val sprites = spriteViewerController.getAllSprites()
val bitmapData = spriteViewerController.convertToBitmap(sprites)
@@ -1,13 +1,11 @@
package com.github.nacabaro.vbhelper.screens.spriteViewer
import android.graphics.Bitmap
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.asImageBitmap
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.characters.Sprite
import java.nio.ByteBuffer
import androidx.core.graphics.createBitmap
class SpriteViewerControllerImpl(
private val context: ComponentActivity
@@ -24,41 +22,40 @@ class SpriteViewerControllerImpl(
val bitmapList = mutableListOf<Bitmap>()
for (sprite in sprites) {
Log.d("SpriteViewer", "sprite: $sprite")
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteIdle1))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteIdle2))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteWalk1))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteWalk2))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteRun1))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteRun2))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteTrain1))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteTrain2))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteHappy))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteSleep))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteAttack))
})
bitmapList.add(Bitmap.createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
bitmapList.add(createBitmap(sprite.width, sprite.height, Bitmap.Config.RGB_565).apply {
copyPixelsFromBuffer(ByteBuffer.wrap(sprite.spriteDodge))
})
}
@@ -1,6 +1,5 @@
package com.github.nacabaro.vbhelper.screens.storageScreen
import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.scrollable
@@ -149,7 +148,7 @@ fun StorageScreen(
.deleteCharacter(
characterId = selectedCharacter!!,
onCompletion = {
Log.d("StorageScreen", "Character deleted")
AppLogger.d("StorageScreen", "Character deleted")
}
)
selectedCharacter = null
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="M480,760q66,0 113,-47t47,-113v-160q0,-66 -47,-113t-113,-47q-66,0 -113,47t-47,113v160q0,66 47,113t113,47ZM400,640h160v-80L400,560v80ZM400,480h160v-80L400,400v80ZM480,520ZM480,840q-65,0 -120.5,-32T272,720L160,720v-80h84q-3,-20 -3.5,-40t-0.5,-40h-80v-80h80q0,-20 0.5,-40t3.5,-40h-84v-80h112q14,-23 31.5,-43t40.5,-35l-64,-66 56,-56 86,86q28,-9 57,-9t57,9l88,-86 56,56 -66,66q23,15 41.5,34.5T688,320h112v80h-84q3,20 3.5,40t0.5,40h80v80h-80q0,20 -0.5,40t-3.5,40h84v80L688,720q-32,56 -87.5,88T480,840Z"
android:fillColor="#000000"/>
</vector>
+4
View File
@@ -225,5 +225,9 @@
<string name="home_special_mission_delete_main">Are you sure you want to delete this special mission with this progress?</string>
<string name="home_special_mission_delete_dismiss">Dismiss</string>
<string name="home_special_mission_delete_remove">Remove</string>
<string name="nav_logs">Logs</string>
<string name="settings_logs_title">Log viewer</string>
<string name="settings_logs_desc">Check logs generated within the app</string>
<string name="logs_title">Application logs</string>
</resources>
+20 -11
View File
@@ -1,24 +1,32 @@
[versions]
agp = "8.13.2"
datastore = "1.1.2"
kotlin = "2.0.0"
coreKtx = "1.15.0"
datastore = "1.2.0"
datastorePreferences = "1.2.0"
kotlin = "2.3.0"
coreKtx = "1.17.0"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
lifecycleRuntimeKtx = "2.8.7"
activityCompose = "1.10.0"
composeBom = "2025.01.00"
protobufGradlePlugin = "0.9.4"
protobufJavalite = "4.27.0"
roomRuntime = "2.6.1"
junitVersion = "1.3.0"
espressoCore = "3.7.0"
lifecycleRuntimeKtx = "2.10.0"
activityCompose = "1.12.2"
composeBom = "2026.01.00"
material = "1.13.0"
navigationCompose = "2.9.6"
protobufGradlePlugin = "0.9.6"
protobufJavalite = "4.33.4"
roomRuntime = "2.8.4"
vbNfcReader = "0.2.0-SNAPSHOT"
dimReader = "2.1.0"
[libraries]
androidx-compose-material = { module = "androidx.compose.material:material" }
androidx-compose-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-datastore = { module = "androidx.datastore:datastore", version.ref = "datastore" }
androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomRuntime" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomRuntime" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
@@ -33,6 +41,7 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
material = { module = "com.google.android.material:material", version.ref = "material" }
protobuf-gradle-plugin = { module = "com.google.protobuf:protobuf-gradle-plugin", version.ref = "protobufGradlePlugin" }
protobuf-javalite = { module = "com.google.protobuf:protobuf-javalite", version.ref = "protobufJavalite" }
vb-nfc-reader = { module = "com.github.cfogrady:vb-nfc-reader", version.ref = "vbNfcReader" }