diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt b/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt index eaa7d0e..cee99cb 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt @@ -1,26 +1,16 @@ package com.github.nacabaro.vbhelper -import android.content.Intent import android.os.Bundle import android.util.Log -import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.runtime.Composable -import androidx.lifecycle.lifecycleScope -import com.github.cfogrady.vb.dim.card.BemCard -import com.github.cfogrady.vb.dim.card.DimReader import com.github.nacabaro.vbhelper.navigation.AppNavigation import com.github.cfogrady.vbnfc.be.BENfcCharacter import com.github.cfogrady.vbnfc.data.NfcCharacter import com.github.cfogrady.vbnfc.vb.VBNfcCharacter import com.github.nacabaro.vbhelper.di.VBHelper -import com.github.nacabaro.vbhelper.domain.characters.Card -import com.github.nacabaro.vbhelper.domain.Sprites -import com.github.nacabaro.vbhelper.domain.characters.Character import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter import com.github.nacabaro.vbhelper.navigation.AppNavigationHandlers @@ -30,15 +20,12 @@ import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControl import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme import com.github.nacabaro.vbhelper.utils.DeviceType import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.launch import java.util.GregorianCalendar class MainActivity : ComponentActivity() { private var nfcCharacter = MutableStateFlow(null) - private lateinit var activityResultLauncher: ActivityResultLauncher - private val onActivityLifecycleListeners = HashMap() private fun registerActivityLifecycleListener(key: String, activityLifecycleListener: ActivityLifecycleListener) { @@ -53,8 +40,6 @@ class MainActivity : ComponentActivity() { } override fun onCreate(savedInstanceState: Bundle?) { - registerFileActivityResult() - val application = applicationContext as VBHelper val scanScreenController = ScanScreenControllerImpl( application.container.dataStoreSecretsRepository.secretsFlow, @@ -67,7 +52,9 @@ class MainActivity : ComponentActivity() { val itemsScreenController = ItemsScreenControllerImpl(this) super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContent { VBHelperTheme { MainApplication( @@ -77,6 +64,7 @@ class MainActivity : ComponentActivity() { ) } } + Log.i("MainActivity", "Activity onCreated") } @@ -96,122 +84,18 @@ class MainActivity : ComponentActivity() { } } - private fun registerFileActivityResult() { - activityResultLauncher = registerForActivityResult( - ActivityResultContracts.StartActivityForResult() - ) { - lifecycleScope.launch { - val application = applicationContext as VBHelper - val storageRepository = application.container.db - - if (it.resultCode != RESULT_OK) { - Toast.makeText(applicationContext, "Import operation cancelled.", Toast.LENGTH_SHORT).show() - } - val contentResolver = applicationContext.contentResolver - val inputStream = contentResolver.openInputStream(it.data!!.data!!) - inputStream.use { fileReader -> - val dimReader = DimReader() - val card = dimReader.readCard(fileReader, false) - - Log.i("MainActivity", "Card name: ${card is BemCard}") - - val cardModel = Card( - dimId = card.header.dimId, - logo = card.spriteData.sprites[0].pixelData, - name = card.spriteData.text, // TODO Make user write card name - stageCount = card.adventureLevels.levels.size, - logoHeight = card.spriteData.sprites[0].height, - logoWidth = card.spriteData.sprites[0].width, - isBEm = card is BemCard - ) - - val dimId = storageRepository - .dimDao() - .insertNewDim(cardModel) - - val characters = card.characterStats.characterEntries - - var spriteCounter = when (card is BemCard) { - true -> 55 - false -> 10 - } - - val domainCharacters = mutableListOf() - - for (index in 0 until characters.size) { - domainCharacters.add( - Character( - dimId = dimId, - monIndex = index, - name = card.spriteData.sprites[spriteCounter].pixelData, - stage = characters[index].stage, - attribute = characters[index].attribute, - baseHp = characters[index].hp, - baseBp = characters[index].dp, - baseAp = characters[index].ap, - sprite1 = card.spriteData.sprites[spriteCounter + 1].pixelData, - sprite2 = card.spriteData.sprites[spriteCounter + 2].pixelData, - nameWidth = card.spriteData.sprites[spriteCounter].width, - nameHeight = card.spriteData.sprites[spriteCounter].height, - spritesWidth = card.spriteData.sprites[spriteCounter + 1].width, - spritesHeight = card.spriteData.sprites[spriteCounter + 1].height - ) - ) - - // TODO: Improve this - if (card is BemCard) { - spriteCounter += 14 - } else { - when (index) { - 0 -> spriteCounter += 6 - 1 -> spriteCounter += 7 - else -> spriteCounter += 14 - } - } - } - - storageRepository - .characterDao() - .insertCharacter(*domainCharacters.toTypedArray()) - - val sprites = card.spriteData.sprites.map { sprite -> - Sprites( - id = 0, - sprite = sprite.pixelData, - width = sprite.width, - height = sprite.height - ) - } - storageRepository - .characterDao() - .insertSprite(*sprites.toTypedArray()) - } - inputStream?.close() - Toast.makeText(applicationContext, "Import successful!", Toast.LENGTH_SHORT).show() - } - } - } - @Composable private fun MainApplication( scanScreenController: ScanScreenControllerImpl, settingsScreenController: SettingsScreenControllerImpl, itemsScreenController: ItemsScreenControllerImpl ) { - AppNavigation( applicationNavigationHandlers = AppNavigationHandlers( settingsScreenController, scanScreenController, itemsScreenController - ), - onClickImportCard = { - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = "*/*" - } - activityResultLauncher.launch(intent) - } + ) ) } diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt index 13e8fd4..541a80c 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt @@ -30,7 +30,6 @@ data class AppNavigationHandlers( @Composable fun AppNavigation( applicationNavigationHandlers: AppNavigationHandlers, - onClickImportCard: () -> Unit, ) { val navController = rememberNavController() @@ -76,8 +75,7 @@ fun AppNavigation( composable(NavigationItems.Settings.route) { SettingsScreen( navController = navController, - settingsScreenController = applicationNavigationHandlers.settingsScreenController, - onClickImportCard = onClickImportCard, + settingsScreenController = applicationNavigationHandlers.settingsScreenController ) } composable(NavigationItems.Viewer.route) { diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreen.kt index 6c0051f..02dfc6a 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreen.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreen.kt @@ -23,7 +23,6 @@ import com.github.nacabaro.vbhelper.components.TopBanner fun SettingsScreen( navController: NavController, settingsScreenController: SettingsScreenControllerImpl, - onClickImportCard: () -> Unit ) { Scaffold ( topBar = { @@ -55,7 +54,9 @@ fun SettingsScreen( settingsScreenController.onClickImportDatabase() } SettingsSection("DiM/BEm management") - SettingsEntry(title = "Import DiM card", description = "Import DiM/BEm card file", onClick = onClickImportCard) + SettingsEntry(title = "Import DiM card", description = "Import DiM/BEm card file") { + settingsScreenController.onClickImportCard() + } SettingsEntry(title = "Rename DiM/BEm", description = "Set card name") { } SettingsSection("About and credits") SettingsEntry(title = "Credits", description = "Credits") { } diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenController.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenController.kt index 94fffee..ea0fb19 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenController.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenController.kt @@ -4,4 +4,5 @@ interface SettingsScreenController { fun onClickOpenDirectory() fun onClickImportDatabase() fun onClickImportApk() + fun onClickImportCard() } \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt index 8cae654..94be077 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt @@ -9,7 +9,13 @@ import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts +import com.github.cfogrady.vb.dim.card.BemCard +import com.github.cfogrady.vb.dim.card.DimReader +import com.github.nacabaro.vbhelper.database.AppDatabase import com.github.nacabaro.vbhelper.di.VBHelper +import com.github.nacabaro.vbhelper.domain.Sprites +import com.github.nacabaro.vbhelper.domain.characters.Card +import com.github.nacabaro.vbhelper.domain.characters.Character import com.github.nacabaro.vbhelper.source.ApkSecretsImporter import com.github.nacabaro.vbhelper.source.SecretsImporter import com.github.nacabaro.vbhelper.source.SecretsRepository @@ -27,9 +33,11 @@ class SettingsScreenControllerImpl( private val filePickerLauncher: ActivityResultLauncher private val filePickerOpenerLauncher: ActivityResultLauncher> private val filePickerApk: ActivityResultLauncher> + private val filePickerCard: ActivityResultLauncher> private val secretsImporter: SecretsImporter = ApkSecretsImporter() private val application = context.applicationContext as VBHelper private val secretsRepository: SecretsRepository = application.container.dataStoreSecretsRepository + private val database: AppDatabase = application.container.db init { filePickerLauncher = context.registerForActivityResult( @@ -68,6 +76,18 @@ class SettingsScreenControllerImpl( } } } + + filePickerCard = context.registerForActivityResult( + ActivityResultContracts.OpenDocument() + ) { uri -> + if (uri != null) { + importCard(uri) + } else { + context.runOnUiThread { + Toast.makeText(context, "Card import cancelled", Toast.LENGTH_SHORT).show() + } + } + } } override fun onClickOpenDirectory() { @@ -82,6 +102,96 @@ class SettingsScreenControllerImpl( filePickerApk.launch(arrayOf("*/*")) } + override fun onClickImportCard() { + filePickerCard.launch(arrayOf("*/*")) + } + + private fun importCard(uri: Uri) { + context.lifecycleScope.launch(Dispatchers.IO) { + val contentResolver = context.contentResolver + val inputStream = contentResolver.openInputStream(uri) + inputStream.use { fileReader -> + val dimReader = DimReader() + val card = dimReader.readCard(fileReader, false) + + val cardModel = Card( + dimId = card.header.dimId, + logo = card.spriteData.sprites[0].pixelData, + name = card.spriteData.text, // TODO Make user write card name// TODO Make user write card name + stageCount = card.adventureLevels.levels.size, + logoHeight = card.spriteData.sprites[0].height, + logoWidth = card.spriteData.sprites[0].width, + isBEm = card is BemCard + ) + + val dimId = database + .dimDao() + .insertNewDim(cardModel) + + val characters = card.characterStats.characterEntries + + var spriteCounter = when (card is BemCard) { + true -> 55 + false -> 10 + } + + val domainCharacters = mutableListOf() + + for (index in 0 until characters.size) { + domainCharacters.add( + Character( + dimId = dimId, + monIndex = index, + name = card.spriteData.sprites[spriteCounter].pixelData, + stage = characters[index].stage, + attribute = characters[index].attribute, + baseHp = characters[index].hp, + baseBp = characters[index].dp, + baseAp = characters[index].ap, + sprite1 = card.spriteData.sprites[spriteCounter + 1].pixelData, + sprite2 = card.spriteData.sprites[spriteCounter + 2].pixelData, + nameWidth = card.spriteData.sprites[spriteCounter].width, + nameHeight = card.spriteData.sprites[spriteCounter].height, + spritesWidth = card.spriteData.sprites[spriteCounter + 1].width, + spritesHeight = card.spriteData.sprites[spriteCounter + 1].height + ) + ) + + spriteCounter += if (card is BemCard) { + 14 + } else { + when (index) { + 0 -> 6 + 1 -> 7 + else -> 14 + } + } + } + + database + .characterDao() + .insertCharacter(*domainCharacters.toTypedArray()) + + val sprites = card.spriteData.sprites.map { sprite -> + Sprites( + id = 0, + sprite = sprite.pixelData, + width = sprite.width, + height = sprite.height + ) + } + database + .characterDao() + .insertSprite(*sprites.toTypedArray()) + } + + inputStream?.close() + context.runOnUiThread { + Toast.makeText(context, "Import successful!", Toast.LENGTH_SHORT).show() + } + } + } + private fun exportDatabase(destinationUri: Uri) { context.lifecycleScope.launch(Dispatchers.IO) { try {