diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7a3144a..bad2f0f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,11 +1,6 @@ - - - - - diff --git a/app/src/main/java/eu/m724/pojavbackup/core/backup/BackupWorker.kt b/app/src/main/java/eu/m724/pojavbackup/core/backup/BackupWorker.kt index aa8e28d..6d5059a 100644 --- a/app/src/main/java/eu/m724/pojavbackup/core/backup/BackupWorker.kt +++ b/app/src/main/java/eu/m724/pojavbackup/core/backup/BackupWorker.kt @@ -21,6 +21,8 @@ import eu.m724.pojavbackup.core.data.GameDataRepository import eu.m724.pojavbackup.core.data.World import eu.m724.pojavbackup.core.datastore.SettingsRepository import eu.m724.pojavbackup.notification.NotificationChannels +import eu.m724.pojavbackup.proto.BackupSource +import kotlinx.coroutines.flow.first import java.time.LocalDate import java.time.format.DateTimeFormatter import java.util.UUID @@ -55,8 +57,13 @@ class BackupWorker @AssistedInject constructor( } private suspend fun doBackup(backup: Backup) { - val settings = settingsRepository.getSettings() - val worldIds = settingsRepository.getIncludedWorldIds(settings.worldOrder) + val settings = settingsRepository.settingsFlow.first() + val sources = settings.sourcesList + + // TODO other source types support + val worldIds = sources + .filter { it.type == BackupSource.SourceType.WORLD } + .map { it.id } // TODO multiple destinations support val destinationUri = settings.destinationsList.first().uri.toUri() diff --git a/app/src/main/java/eu/m724/pojavbackup/core/data/GameDataModule.kt b/app/src/main/java/eu/m724/pojavbackup/core/data/GameDataModule.kt index 6bba03b..692f5d5 100644 --- a/app/src/main/java/eu/m724/pojavbackup/core/data/GameDataModule.kt +++ b/app/src/main/java/eu/m724/pojavbackup/core/data/GameDataModule.kt @@ -2,6 +2,7 @@ package eu.m724.pojavbackup.core.data import android.content.Context import android.util.Log +import androidx.core.net.toUri import androidx.documentfile.provider.DocumentFile import dagger.Module import dagger.Provides @@ -12,6 +13,7 @@ import eu.m724.pojavbackup.core.data.World.Companion.getWorldFromDirectory import eu.m724.pojavbackup.core.data.World.InvalidWorldException import eu.m724.pojavbackup.core.datastore.SettingsRepository import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flow import java.io.File import javax.inject.Singleton @@ -27,8 +29,9 @@ object GameDataModule { settingsRepository: SettingsRepository ): GameDataRepository { return object : GameDataRepository { + override suspend fun listAllWorlds(): Flow { - val sourceUri = settingsRepository.getSource()!! + val sourceUri = settingsRepository.launcherDocumentUriFlow.first().toUri() val documentFile = DocumentFile.fromTreeUri(context, sourceUri)!!.findFile(".minecraft")!!.findFile("saves")!! return flow { @@ -43,7 +46,7 @@ object GameDataModule { } override suspend fun getWorld(id: String): World { - val sourceUri = settingsRepository.getSource()!! + val sourceUri = settingsRepository.launcherDocumentUriFlow.first().toUri() val documentFile = DocumentFile.fromTreeUri(context, sourceUri)!!.findFile(".minecraft")!!.findFile("saves")!! // TODO maybe we could cache this val worldFile = documentFile.findFile(id) ?: throw NoSuchFileException(File(id)) diff --git a/app/src/main/java/eu/m724/pojavbackup/core/data/World.kt b/app/src/main/java/eu/m724/pojavbackup/core/data/World.kt index f7b6146..b23c28a 100644 --- a/app/src/main/java/eu/m724/pojavbackup/core/data/World.kt +++ b/app/src/main/java/eu/m724/pojavbackup/core/data/World.kt @@ -24,20 +24,12 @@ data class World( val documentFile: DocumentFile? ) { - override fun equals(other: Any?): Boolean { - if (other !is World) return false - - // TODO compare only id or other stuff too? - return this.id == other.id - } - companion object { - val SEPARATOR = dummy("") - fun dummy(id: String, label: String = ""): World { return World(id, label, Instant.EPOCH.atZone(ZoneOffset.UTC), null, null) } + // TODO do below belong here? private val NBT = Nbt { @@ -82,4 +74,20 @@ data class World( class InvalidWorldException( override val message: String? ) : Exception() + + override fun equals(other: Any?): Boolean { + if (other !is World) return false + + // TODO compare only id or other stuff too? + return this.id == other.id + } + + override fun hashCode(): Int { + var result = id.hashCode() + result = 31 * result + displayName.hashCode() + result = 31 * result + lastPlayed.hashCode() + result = 31 * result + (icon?.hashCode() ?: 0) + result = 31 * result + (documentFile?.hashCode() ?: 0) + return result + } } \ No newline at end of file diff --git a/app/src/main/java/eu/m724/pojavbackup/core/datastore/SettingsRepository.kt b/app/src/main/java/eu/m724/pojavbackup/core/datastore/SettingsRepository.kt index d263523..a6864d2 100644 --- a/app/src/main/java/eu/m724/pojavbackup/core/datastore/SettingsRepository.kt +++ b/app/src/main/java/eu/m724/pojavbackup/core/datastore/SettingsRepository.kt @@ -1,13 +1,11 @@ package eu.m724.pojavbackup.core.datastore -import android.net.Uri -import androidx.core.net.toUri import androidx.datastore.core.DataStore import eu.m724.pojavbackup.proto.BackupDestination +import eu.m724.pojavbackup.proto.BackupSource import eu.m724.pojavbackup.proto.Settings -import eu.m724.pojavbackup.proto.WorldOrder import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map import javax.inject.Inject import javax.inject.Singleton @@ -15,68 +13,43 @@ import javax.inject.Singleton class SettingsRepository @Inject constructor( private val dataStore: DataStore ) { - fun getSettingsFlow(): Flow { - return dataStore.data - } + val settingsFlow = dataStore.data - suspend fun getSettings(): Settings { - return dataStore.data.first() - } + /* Getters */ - /* Worlds */ + val backupSourcesFlow: Flow> = + settingsFlow.map { it.sourcesList } - suspend fun getIncludedWorldIds(): List { - return getIncludedWorldIds(getSettings().worldOrder) - } + val backupDestinationsFlow: Flow> = + settingsFlow.map { it.destinationsList } - fun getIncludedWorldIds(worldOrder: WorldOrder): List { - return worldOrder.worldIdsList.subList(0, worldOrder.separatorIndex) - } + val launcherDocumentUriFlow: Flow = + settingsFlow.map { it.launcherDocumentUri } - suspend fun updateWorldOrder(worldOrder: WorldOrder) { + /* Setters */ + + suspend fun updateBackupDestinations(backupDestinations: (List) -> List) { dataStore.updateData { it.toBuilder() - .clearWorldOrder() - .setWorldOrder(worldOrder) + .clearDestinations() + .addAllDestinations(backupDestinations(it.destinationsList)) .build() } } - /* Destination */ - - suspend fun getDestinations(): List { - return getSettings().destinationsList - } - - suspend fun addDestination(destination: BackupDestination) { + suspend fun updateBackupSources(backupSources: (List) -> List) { dataStore.updateData { it.toBuilder() - .addDestinations(destination) + .clearSources() + .addAllSources(backupSources(it.sourcesList)) .build() } } - suspend fun removeDestination(index: Int) { + suspend fun updateLauncherDocumentUri(launcherDocumentUri: (String) -> String) { dataStore.updateData { it.toBuilder() - .removeDestinations(index) - .build() - } - } - - /* Source / launcher */ - - suspend fun getSource(): Uri? { - return getSettings().sourceUri.let { - if (it.isEmpty()) null - else it.toUri() - } - } - - suspend fun setSource(source: Uri) { - dataStore.updateData { - it.toBuilder() - .setSourceUri(source.toString()) + .setLauncherDocumentUri(launcherDocumentUri(it.launcherDocumentUri)) .build() } } diff --git a/app/src/main/java/eu/m724/pojavbackup/home/HomeViewModel.kt b/app/src/main/java/eu/m724/pojavbackup/home/HomeViewModel.kt index 21e8621..6b189e2 100644 --- a/app/src/main/java/eu/m724/pojavbackup/home/HomeViewModel.kt +++ b/app/src/main/java/eu/m724/pojavbackup/home/HomeViewModel.kt @@ -5,18 +5,19 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.util.Log +import androidx.core.net.toUri import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext -import eu.m724.pojavbackup.core.data.GameDataRepository import eu.m724.pojavbackup.core.datastore.SettingsRepository import eu.m724.pojavbackup.notification.NotificationChannels import eu.m724.pojavbackup.setup.SetupActivity import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @@ -24,8 +25,7 @@ import javax.inject.Inject @HiltViewModel class HomeViewModel @Inject constructor( @ApplicationContext private val appContext: Context, - private val settingsRepository: SettingsRepository, - private val gameDataRepository: GameDataRepository + private val settingsRepository: SettingsRepository ) : ViewModel() { private val TAG = javaClass.name @@ -45,9 +45,11 @@ class HomeViewModel @Inject constructor( onSetupRequired: (Intent) -> Unit ) { viewModelScope.launch { - val uri = settingsRepository.getSource() + val uri = settingsRepository.launcherDocumentUriFlow.first() - val storagePermission = uri?.let { checkForStoragePermission(uri) } == true + val storagePermission = if (uri.isNotEmpty()) { + checkForStoragePermission(uri.toUri()) + } else false if (!storagePermission || (!notificationPermissionGranted && !notificationPermissionRejected)) { val intent = Intent(appContext, SetupActivity::class.java) diff --git a/app/src/main/java/eu/m724/pojavbackup/home/screen/dashboard/DashboardScreen.kt b/app/src/main/java/eu/m724/pojavbackup/home/screen/dashboard/DashboardScreen.kt index 1cd7304..953f258 100644 --- a/app/src/main/java/eu/m724/pojavbackup/home/screen/dashboard/DashboardScreen.kt +++ b/app/src/main/java/eu/m724/pojavbackup/home/screen/dashboard/DashboardScreen.kt @@ -47,7 +47,7 @@ fun DashboardScreen( ) { DashboardCard( title = stringResource(R.string.dashboard_card_worlds), - value = settings.worldOrder.separatorIndex, + value = settings.sourcesList.size, iconResourceId = R.drawable.baseline_mosque_24, onClick = onWorldsIncludedClick ) diff --git a/app/src/main/java/eu/m724/pojavbackup/home/screen/dashboard/DashboardScreenViewModel.kt b/app/src/main/java/eu/m724/pojavbackup/home/screen/dashboard/DashboardScreenViewModel.kt index 095afc8..00e70b9 100644 --- a/app/src/main/java/eu/m724/pojavbackup/home/screen/dashboard/DashboardScreenViewModel.kt +++ b/app/src/main/java/eu/m724/pojavbackup/home/screen/dashboard/DashboardScreenViewModel.kt @@ -21,7 +21,7 @@ class DashboardScreenViewModel @Inject constructor( init { viewModelScope.launch { - settingsRepository.getSettingsFlow().collect { newSettings -> + settingsRepository.settingsFlow.collect { newSettings -> _settings.update { newSettings } } } diff --git a/app/src/main/java/eu/m724/pojavbackup/settings/SettingsViewModel.kt b/app/src/main/java/eu/m724/pojavbackup/settings/SettingsViewModel.kt index b9e41eb..febfbb7 100644 --- a/app/src/main/java/eu/m724/pojavbackup/settings/SettingsViewModel.kt +++ b/app/src/main/java/eu/m724/pojavbackup/settings/SettingsViewModel.kt @@ -35,7 +35,7 @@ class SettingsViewModel @Inject constructor( .build() viewModelScope.launch { - settingsRepository.addDestination(destination) + settingsRepository.updateBackupDestinations { it + destination } } } } diff --git a/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreen.kt b/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreen.kt index d5b6d77..6d72c43 100644 --- a/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreen.kt +++ b/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreen.kt @@ -33,7 +33,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.navigation.NavController import eu.m724.pojavbackup.R import org.burnoutcrew.reorderable.ReorderableItem import org.burnoutcrew.reorderable.detectReorderAfterLongPress @@ -45,9 +44,7 @@ import java.time.format.FormatStyle @Composable -fun ContentScreen( - navController: NavController, -) { +fun ContentScreen() { val viewModel: ContentScreenViewModel = hiltViewModel() val uiState by viewModel.uiState.collectAsStateWithLifecycle() @@ -59,7 +56,7 @@ fun ContentScreen( if (uiState.loading) { CircularProgressIndicator() } else { - if (uiState.worlds.size <= 1) { // separator + if (uiState.worldList.size <= 1) { // separator Text( text = stringResource(R.string.worlds_none), modifier = Modifier.padding(top = 50.dp) @@ -77,11 +74,11 @@ fun ContentScreen( horizontalAlignment = Alignment.CenterHorizontally ) { items( - items = uiState.worlds, - key = { it.id } + items = uiState.worldList, + key = { it?.id ?: "" } ) { world -> - ReorderableItem(state, key = world.id) { isDragging -> - if (!world.id.isEmpty()) { + ReorderableItem(state, key = world?.id ?: "" ) { isDragging -> + if (world != null) { WorldInfoCard( bitmap = world.icon, id = world.id, diff --git a/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreenUiState.kt b/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreenUiState.kt index 7e0638f..c737655 100644 --- a/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreenUiState.kt +++ b/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreenUiState.kt @@ -4,5 +4,5 @@ import eu.m724.pojavbackup.core.data.World data class ContentScreenUiState( val loading: Boolean = true, - val worlds: List = emptyList() + val worldList: List = emptyList() // null is separator ) \ No newline at end of file diff --git a/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreenViewModel.kt b/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreenViewModel.kt index de44fa2..6c9c611 100644 --- a/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreenViewModel.kt +++ b/app/src/main/java/eu/m724/pojavbackup/settings/screen/content/ContentScreenViewModel.kt @@ -1,25 +1,23 @@ package eu.m724.pojavbackup.settings.screen.content -import android.content.Context import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import dagger.hilt.android.qualifiers.ApplicationContext import eu.m724.pojavbackup.core.data.GameDataRepository import eu.m724.pojavbackup.core.data.World import eu.m724.pojavbackup.core.datastore.SettingsRepository -import eu.m724.pojavbackup.proto.WorldOrder +import eu.m724.pojavbackup.proto.BackupSource import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class ContentScreenViewModel @Inject constructor( - @ApplicationContext private val appContext: Context, private val gameDataRepository: GameDataRepository, private val settingsRepository: SettingsRepository ) : ViewModel() { @@ -28,26 +26,32 @@ class ContentScreenViewModel @Inject constructor( init { viewModelScope.launch { - settingsRepository.getSettingsFlow().collect { settings -> - val worlds = settings.worldOrder.worldIdsList.map { - try { - gameDataRepository.getWorld(it) - } catch (e: NoSuchFileException) { - World.dummy(it, "Deleted world") // TODO more clues that it's deleted - } catch (e: World.InvalidWorldException) { - World.dummy(it, "Corrupted world") // TODO do we want that - } - }.toMutableList() - worlds.add(settings.worldOrder.separatorIndex, World.SEPARATOR) + val savedWorlds = gameDataRepository.listAllWorlds().toList().associate { it.id to it } - gameDataRepository.listAllWorlds().collect { - if (!worlds.contains(it)) { - worlds.add(it) + settingsRepository.backupSourcesFlow.collect { sources -> + val worldStack = savedWorlds.toMutableMap() + + val backedUpWorlds = mutableListOf() + + // TODO support non-world sources + + sources.forEach { source -> + if (source.type != BackupSource.SourceType.WORLD) return@forEach + + val world = worldStack.remove(source.id) + if (world == null) { + backedUpWorlds.add(World.dummy(source.id, "Deleted world")) + return@forEach } + + backedUpWorlds.add(world) } _uiState.update { - it.copy(loading = false, worlds = worlds) + it.copy( + loading = false, + worldList = backedUpWorlds + null + worldStack.values + ) } } } @@ -55,7 +59,7 @@ class ContentScreenViewModel @Inject constructor( fun moveWorld(fromIndex: Int, toIndex: Int) { // Similar to mutableStateOf, create a NEW list - val currentList = _uiState.value.worlds.toMutableList() + val currentList = _uiState.value.worldList.toMutableList() // Check bounds for safety if (fromIndex in currentList.indices && toIndex >= 0 && toIndex <= currentList.size) { val item = currentList.removeAt(fromIndex) @@ -67,18 +71,31 @@ class ContentScreenViewModel @Inject constructor( } } - private fun updateWorldOrder(newList: List) { + private fun updateWorldOrder(newList: List) { _uiState.update { - it.copy(worlds = newList) + it.copy( + worldList = newList + ) + } + + val backupSources = mutableListOf() + + val iterator = newList.iterator() + while (iterator.hasNext()) { + val world = iterator.next() ?: break // remember the separator is null + + val backupSource = BackupSource.newBuilder() + .setId(world.id) + .setType(BackupSource.SourceType.WORLD) + .build() + + backupSources.add(backupSource) } viewModelScope.launch { - settingsRepository.updateWorldOrder( - WorldOrder.newBuilder() - .addAllWorldIds(newList.filter { it != World.SEPARATOR }.map { it.id }) - .setSeparatorIndex(newList.indexOf(World.SEPARATOR)) - .build() + settingsRepository.updateBackupSources( + backupSources = { backupSources } ) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/m724/pojavbackup/settings/screen/destination/DestinationScreen.kt b/app/src/main/java/eu/m724/pojavbackup/settings/screen/destination/DestinationScreen.kt index c8dd8e7..b673214 100644 --- a/app/src/main/java/eu/m724/pojavbackup/settings/screen/destination/DestinationScreen.kt +++ b/app/src/main/java/eu/m724/pojavbackup/settings/screen/destination/DestinationScreen.kt @@ -22,16 +22,14 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.navigation.NavController import eu.m724.pojavbackup.R @Composable fun DestinationScreen( - navController: NavController, onAddDestination: () -> Unit ) { val viewModel: DestinationScreenViewModel = hiltViewModel() - val destinations by viewModel.destinations.collectAsStateWithLifecycle() + val destinations by viewModel.destinationsFlow.collectAsStateWithLifecycle() Column { Column( diff --git a/app/src/main/java/eu/m724/pojavbackup/settings/screen/destination/DestinationScreenViewModel.kt b/app/src/main/java/eu/m724/pojavbackup/settings/screen/destination/DestinationScreenViewModel.kt index 6acd468..fb531ac 100644 --- a/app/src/main/java/eu/m724/pojavbackup/settings/screen/destination/DestinationScreenViewModel.kt +++ b/app/src/main/java/eu/m724/pojavbackup/settings/screen/destination/DestinationScreenViewModel.kt @@ -1,10 +1,8 @@ package eu.m724.pojavbackup.settings.screen.destination -import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import dagger.hilt.android.qualifiers.ApplicationContext import eu.m724.pojavbackup.core.datastore.SettingsRepository import eu.m724.pojavbackup.proto.BackupDestination import kotlinx.coroutines.flow.MutableStateFlow @@ -16,18 +14,15 @@ import javax.inject.Inject @HiltViewModel class DestinationScreenViewModel @Inject constructor( - @ApplicationContext private val appContext: Context, private val settingsRepository: SettingsRepository ) : ViewModel() { - private val _destinations = MutableStateFlow>(emptyList()) - val destinations: StateFlow> = _destinations.asStateFlow() + private val _destinationsFlow = MutableStateFlow>(emptyList()) + val destinationsFlow: StateFlow> = _destinationsFlow.asStateFlow() init { viewModelScope.launch { - settingsRepository.getSettingsFlow().collect { settings -> - _destinations.update { - settings.destinationsList - } + settingsRepository.backupDestinationsFlow.collect { destinations -> + _destinationsFlow.update { destinations } } } } diff --git a/app/src/main/java/eu/m724/pojavbackup/setup/SetupActivity.kt b/app/src/main/java/eu/m724/pojavbackup/setup/SetupActivity.kt index 7e03dda..f3ee58b 100644 --- a/app/src/main/java/eu/m724/pojavbackup/setup/SetupActivity.kt +++ b/app/src/main/java/eu/m724/pojavbackup/setup/SetupActivity.kt @@ -64,7 +64,7 @@ class SetupActivity : ComponentActivity() { if (!viewModel.checkIfCanProceed()) return startActivity(Intent(applicationContext, HomeActivity::class.java)) - finishActivity(0) + finish() } diff --git a/app/src/main/java/eu/m724/pojavbackup/setup/SetupViewModel.kt b/app/src/main/java/eu/m724/pojavbackup/setup/SetupViewModel.kt index bd325eb..0d945c1 100644 --- a/app/src/main/java/eu/m724/pojavbackup/setup/SetupViewModel.kt +++ b/app/src/main/java/eu/m724/pojavbackup/setup/SetupViewModel.kt @@ -2,7 +2,6 @@ package eu.m724.pojavbackup.setup import android.content.Context import android.content.Intent -import android.content.pm.PackageManager.NameNotFoundException import android.net.Uri import android.util.Log import androidx.documentfile.provider.DocumentFile @@ -25,11 +24,6 @@ class SetupViewModel @Inject constructor( ) : ViewModel() { private val TAG: String = javaClass.name - private val POJAV_PACKAGES = arrayOf( - "net.kdt.pojavlaunch", - "net.kdt.pojavlaunch.debug" - ) - private val _uiState = MutableStateFlow(SetupUiState()) val uiState: StateFlow = _uiState.asStateFlow() @@ -67,7 +61,7 @@ class SetupViewModel @Inject constructor( viewModelScope.launch { if (hasPermission) { - settingsRepository.setSource(uri) + settingsRepository.updateLauncherDocumentUri { uri.toString() } } } @@ -116,17 +110,4 @@ class SetupViewModel @Inject constructor( return true } - - fun detectInstalledLauncherPackage(): List { - val packageManager = appContext.packageManager - - return POJAV_PACKAGES.filter { - try { - packageManager.getPackageInfo(it, 0) - true - } catch (e: NameNotFoundException) { - false - } - } - } } \ No newline at end of file diff --git a/app/src/main/proto/settings.proto b/app/src/main/proto/settings.proto index b1f5089..c5ef4b3 100644 --- a/app/src/main/proto/settings.proto +++ b/app/src/main/proto/settings.proto @@ -3,32 +3,29 @@ syntax = "proto3"; option java_package = "eu.m724.pojavbackup.proto"; option java_multiple_files = true; -message WorldOrder { - repeated string worldIds = 1; - int32 separatorIndex = 2; +message BackupSource { + enum SourceType { + WORLD = 0; + } + + SourceType type = 1; + string id = 2; } message BackupDestination { + enum DestinationType { + EXTERNAL = 0; // currently the only one because we use DocumentFile + } + string label = 1; - string uri = 2; // TODO + DestinationType type = 2; + string uri = 3; // this should be changed after adding more types } message Settings { - WorldOrder worldOrder = 1; - repeated string extraPaths = 2; + string launcherDocumentUri = 1; + + repeated BackupSource sources = 2; repeated BackupDestination destinations = 3; - - string sourceUri = 4; -} - - -message BackupMeta { - string id = 1; - int64 timestamp = 2; - int32 status = 3; -} - -message BackupsMeta { - repeated BackupMeta backups = 1; } \ No newline at end of file