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 deae7b2..569662b 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt @@ -25,9 +25,7 @@ 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 import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl -import com.github.nacabaro.vbhelper.screens.settingsScreen.NewSettingsScreenControllerImpl -import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenController -import com.github.nacabaro.vbhelper.source.ApkSecretsImporter +import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme import com.github.nacabaro.vbhelper.utils.DeviceType import kotlinx.coroutines.flow.MutableStateFlow @@ -57,8 +55,6 @@ class MainActivity : ComponentActivity() { registerFileActivityResult() val application = applicationContext as VBHelper - val settingsScreenController = SettingsScreenController.Factory(this, ApkSecretsImporter(), application.container.dataStoreSecretsRepository) - .buildSettingScreenHandlers() val scanScreenController = ScanScreenControllerImpl( application.container.dataStoreSecretsRepository.secretsFlow, this::handleReceivedNfcCharacter, @@ -66,13 +62,13 @@ class MainActivity : ComponentActivity() { this::registerActivityLifecycleListener, this::unregisterActivityLifecycleListener ) - val newSettingsScreenController = NewSettingsScreenControllerImpl(this) + val settingsScreenController = SettingsScreenControllerImpl(this) super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { VBHelperTheme { - MainApplication(settingsScreenController, scanScreenController, newSettingsScreenController) + MainApplication(scanScreenController, settingsScreenController) } } Log.i("MainActivity", "Activity onCreated") @@ -192,16 +188,14 @@ class MainActivity : ComponentActivity() { @Composable private fun MainApplication( - settingsScreenController: SettingsScreenController, scanScreenController: ScanScreenControllerImpl, - newSettingsScreenController: NewSettingsScreenControllerImpl + settingsScreenController: SettingsScreenControllerImpl ) { AppNavigation( applicationNavigationHandlers = AppNavigationHandlers( settingsScreenController, scanScreenController, - newSettingsScreenController ), onClickImportCard = { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { 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 b0138b5..5d417b1 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 @@ -15,15 +15,13 @@ import com.github.nacabaro.vbhelper.screens.ItemsScreen import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreen import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreen -import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenController import com.github.nacabaro.vbhelper.screens.SpriteViewer import com.github.nacabaro.vbhelper.screens.StorageScreen -import com.github.nacabaro.vbhelper.screens.settingsScreen.NewSettingsScreenControllerImpl +import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl data class AppNavigationHandlers( - val settingsScreenController: SettingsScreenController, + val settingsScreenController: SettingsScreenControllerImpl, val scanScreenController: ScanScreenControllerImpl, - val newSettingsScreenController: NewSettingsScreenControllerImpl ) @Composable @@ -76,7 +74,6 @@ fun AppNavigation( SettingsScreen( navController = navController, settingsScreenController = applicationNavigationHandlers.settingsScreenController, - newSettingsScreenController = applicationNavigationHandlers.newSettingsScreenController, onClickImportCard = onClickImportCard, ) } diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/NewSettingsScreenController.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/NewSettingsScreenController.kt deleted file mode 100644 index 612406b..0000000 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/NewSettingsScreenController.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.github.nacabaro.vbhelper.screens.settingsScreen - -import android.net.Uri - -interface NewSettingsScreenController { - fun onClickOpenDirectory() - fun onClickImportDatabase() -} \ No newline at end of file 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 42b6e8d..6c0051f 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 @@ -1,9 +1,5 @@ package com.github.nacabaro.vbhelper.screens.settingsScreen -import android.net.Uri -import androidx.activity.ComponentActivity -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -22,14 +18,11 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController import com.github.nacabaro.vbhelper.components.TopBanner -import com.github.nacabaro.vbhelper.navigation.AppNavigation -import com.github.nacabaro.vbhelper.navigation.NavigationItems @Composable fun SettingsScreen( navController: NavController, - settingsScreenController: SettingsScreenController, - newSettingsScreenController: NewSettingsScreenControllerImpl, + settingsScreenController: SettingsScreenControllerImpl, onClickImportCard: () -> Unit ) { Scaffold ( @@ -52,14 +45,14 @@ fun SettingsScreen( ) { SettingsSection("NFC Communication") SettingsEntry(title = "Import APK", description = "Import Secrets From Vital Arean 2.1.0 APK") { - settingsScreenController.apkFilePickLauncher.launch(arrayOf("*/*")) + settingsScreenController.onClickImportApk() } SettingsSection("Data management") SettingsEntry(title = "Export data", description = "Export application database") { - newSettingsScreenController.onClickOpenDirectory() + settingsScreenController.onClickOpenDirectory() } SettingsEntry(title = "Import data", description = "Import application database") { - newSettingsScreenController.onClickImportDatabase() + settingsScreenController.onClickImportDatabase() } SettingsSection("DiM/BEm management") SettingsEntry(title = "Import DiM card", description = "Import DiM/BEm card file", onClick = onClickImportCard) @@ -71,12 +64,6 @@ fun SettingsScreen( } } -fun buildFilePickLauncher(activity: ComponentActivity, onItemPicked: (Uri?) -> Unit): ActivityResultLauncher> { - return activity.registerForActivityResult(ActivityResultContracts.OpenDocument()) { - onItemPicked.invoke(it) - } -} - @Composable fun SettingsEntry( title: String, 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 deleted file mode 100644 index 6f1f41a..0000000 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenController.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.github.nacabaro.vbhelper.screens.settingsScreen - -import android.net.Uri -import android.widget.Toast -import androidx.activity.ComponentActivity -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts -import androidx.lifecycle.lifecycleScope -import com.github.nacabaro.vbhelper.source.SecretsImporter -import com.github.nacabaro.vbhelper.source.SecretsRepository -import com.github.nacabaro.vbhelper.source.proto.Secrets -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch - -data class SettingsScreenController(val apkFilePickLauncher: ActivityResultLauncher>) { - - class Factory(private val componentActivity: ComponentActivity, private val secretsImporter: SecretsImporter, private val secretsRepository: SecretsRepository) { - - fun buildSettingScreenHandlers(): SettingsScreenController { - return SettingsScreenController( - apkFilePickLauncher = buildFilePickerActivityLauncher(this::importApk) - ) - } - - private fun buildFilePickerActivityLauncher(onResult : (Uri?) ->Unit): ActivityResultLauncher> { - return componentActivity.registerForActivityResult(ActivityResultContracts.OpenDocument()) { - onResult.invoke(it) - } - } - - private fun importApk(uri: Uri?) { - if(uri == null) { - componentActivity.runOnUiThread { - Toast.makeText(componentActivity, "APK Import Cancelled", Toast.LENGTH_SHORT) - .show() - } - return - } - componentActivity.lifecycleScope.launch(Dispatchers.IO) { - componentActivity.contentResolver.openInputStream(uri).use { - if(it == null) { - componentActivity.runOnUiThread { - Toast.makeText( - componentActivity, - "Selected file is empty!", - Toast.LENGTH_SHORT - ).show() - } - return@launch - } - var secrets: Secrets? = null - try { - secrets = secretsImporter.importSecrets(it) - } catch (e: Exception) { - componentActivity.runOnUiThread { - Toast.makeText(componentActivity, "Secrets import failed. Please only select the official Vital Arena App 2.1.0 APK.", Toast.LENGTH_SHORT).show() - } - return@launch - } - componentActivity.lifecycleScope.launch(Dispatchers.IO) { - secretsRepository.updateSecrets(secrets) - }.invokeOnCompletion { - componentActivity.runOnUiThread { - Toast.makeText(componentActivity, "Secrets successfully imported. Connections with devices are now possible.", Toast.LENGTH_SHORT).show() - } - } - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/NewSettingsScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt similarity index 68% rename from app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/NewSettingsScreenControllerImpl.kt rename to app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt index dc03802..8cae654 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/NewSettingsScreenControllerImpl.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt @@ -10,24 +10,33 @@ import androidx.activity.ComponentActivity import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import com.github.nacabaro.vbhelper.di.VBHelper +import com.github.nacabaro.vbhelper.source.ApkSecretsImporter +import com.github.nacabaro.vbhelper.source.SecretsImporter +import com.github.nacabaro.vbhelper.source.SecretsRepository +import com.github.nacabaro.vbhelper.source.proto.Secrets import kotlinx.coroutines.Dispatchers import java.io.File import java.io.InputStream import java.io.OutputStream -class NewSettingsScreenControllerImpl( +class SettingsScreenControllerImpl( private val context: ComponentActivity, -): NewSettingsScreenController { +): SettingsScreenController { + private val roomDbName = "internalDb" private val filePickerLauncher: ActivityResultLauncher private val filePickerOpenerLauncher: ActivityResultLauncher> + private val filePickerApk: ActivityResultLauncher> + private val secretsImporter: SecretsImporter = ApkSecretsImporter() + private val application = context.applicationContext as VBHelper + private val secretsRepository: SecretsRepository = application.container.dataStoreSecretsRepository init { filePickerLauncher = context.registerForActivityResult( ActivityResultContracts.CreateDocument("application/octet-stream") ) { uri -> if (uri != null) { - exportDatabase("internalDb", uri) + exportDatabase(uri) } else { context.runOnUiThread { Toast.makeText(context, "No destination selected", Toast.LENGTH_SHORT) @@ -40,13 +49,25 @@ class NewSettingsScreenControllerImpl( ActivityResultContracts.OpenDocument() ) { uri -> if (uri != null) { - importDatabase("internalDb", uri) + importDatabase(uri) } else { context.runOnUiThread { Toast.makeText(context, "No source selected", Toast.LENGTH_SHORT).show() } } } + + filePickerApk = context.registerForActivityResult( + ActivityResultContracts.OpenDocument() + ) { uri -> + if (uri != null) { + importApk(uri) + } else { + context.runOnUiThread { + Toast.makeText(context, "APK import cancelled", Toast.LENGTH_SHORT).show() + } + } + } } override fun onClickOpenDirectory() { @@ -57,10 +78,13 @@ class NewSettingsScreenControllerImpl( filePickerOpenerLauncher.launch(arrayOf("application/octet-stream")) } - private fun exportDatabase(roomDbName: String, destinationUri: Uri) { + override fun onClickImportApk() { + filePickerApk.launch(arrayOf("*/*")) + } + + private fun exportDatabase(destinationUri: Uri) { context.lifecycleScope.launch(Dispatchers.IO) { try { - val application = context.applicationContext as VBHelper val dbFile = File(context.getDatabasePath(roomDbName).absolutePath) if (!dbFile.exists()) { throw IllegalStateException("Database file does not exist!") @@ -88,11 +112,9 @@ class NewSettingsScreenControllerImpl( } } - private fun importDatabase(roomDbName: String, sourceUri: Uri) { + private fun importDatabase(sourceUri: Uri) { context.lifecycleScope.launch(Dispatchers.IO) { try { - var application = context.applicationContext as VBHelper - if (!getFileNameFromUri(sourceUri)!!.endsWith(".vbhelper")) { context.runOnUiThread { Toast.makeText(context, "Invalid file format", Toast.LENGTH_SHORT).show() @@ -153,4 +175,37 @@ class NewSettingsScreenControllerImpl( } outputStream.flush() } + + private fun importApk(uri: Uri) { + context.lifecycleScope.launch(Dispatchers.IO) { + context.contentResolver.openInputStream(uri).use { + if(it == null) { + context.runOnUiThread { + Toast.makeText( + context, + "Selected file is empty!", + Toast.LENGTH_SHORT + ).show() + } + return@launch + } + val secrets: Secrets? + try { + secrets = secretsImporter.importSecrets(it) + } catch (e: Exception) { + context.runOnUiThread { + Toast.makeText(context, "Secrets import failed. Please only select the official Vital Arena App 2.1.0 APK.", Toast.LENGTH_SHORT).show() + } + return@launch + } + context.lifecycleScope.launch(Dispatchers.IO) { + secretsRepository.updateSecrets(secrets) + }.invokeOnCompletion { + context.runOnUiThread { + Toast.makeText(context, "Secrets successfully imported. Connections with devices are now possible.", Toast.LENGTH_SHORT).show() + } + } + } + } + } } \ No newline at end of file