Reorder settings
This commit is contained in:
parent
392c0efc83
commit
115c3e2b6e
17 changed files with 136 additions and 163 deletions
|
@ -1,11 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Required to check which pojavlauncher is installed -->
|
||||
<queries>
|
||||
<package android:name="net.kdt.pojavlaunch" />
|
||||
<package android:name="net.kdt.pojavlaunch.debug" />
|
||||
</queries>
|
||||
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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<World> {
|
||||
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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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<Settings>
|
||||
) {
|
||||
fun getSettingsFlow(): Flow<Settings> {
|
||||
return dataStore.data
|
||||
}
|
||||
val settingsFlow = dataStore.data
|
||||
|
||||
suspend fun getSettings(): Settings {
|
||||
return dataStore.data.first()
|
||||
}
|
||||
/* Getters */
|
||||
|
||||
/* Worlds */
|
||||
val backupSourcesFlow: Flow<List<BackupSource>> =
|
||||
settingsFlow.map { it.sourcesList }
|
||||
|
||||
suspend fun getIncludedWorldIds(): List<String> {
|
||||
return getIncludedWorldIds(getSettings().worldOrder)
|
||||
}
|
||||
val backupDestinationsFlow: Flow<List<BackupDestination>> =
|
||||
settingsFlow.map { it.destinationsList }
|
||||
|
||||
fun getIncludedWorldIds(worldOrder: WorldOrder): List<String> {
|
||||
return worldOrder.worldIdsList.subList(0, worldOrder.separatorIndex)
|
||||
}
|
||||
val launcherDocumentUriFlow: Flow<String> =
|
||||
settingsFlow.map { it.launcherDocumentUri }
|
||||
|
||||
suspend fun updateWorldOrder(worldOrder: WorldOrder) {
|
||||
/* Setters */
|
||||
|
||||
suspend fun updateBackupDestinations(backupDestinations: (List<BackupDestination>) -> List<BackupDestination>) {
|
||||
dataStore.updateData {
|
||||
it.toBuilder()
|
||||
.clearWorldOrder()
|
||||
.setWorldOrder(worldOrder)
|
||||
.clearDestinations()
|
||||
.addAllDestinations(backupDestinations(it.destinationsList))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
/* Destination */
|
||||
|
||||
suspend fun getDestinations(): List<BackupDestination> {
|
||||
return getSettings().destinationsList
|
||||
}
|
||||
|
||||
suspend fun addDestination(destination: BackupDestination) {
|
||||
suspend fun updateBackupSources(backupSources: (List<BackupSource>) -> List<BackupSource>) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -21,7 +21,7 @@ class DashboardScreenViewModel @Inject constructor(
|
|||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
settingsRepository.getSettingsFlow().collect { newSettings ->
|
||||
settingsRepository.settingsFlow.collect { newSettings ->
|
||||
_settings.update { newSettings }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ class SettingsViewModel @Inject constructor(
|
|||
.build()
|
||||
|
||||
viewModelScope.launch {
|
||||
settingsRepository.addDestination(destination)
|
||||
settingsRepository.updateBackupDestinations { it + destination }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -4,5 +4,5 @@ import eu.m724.pojavbackup.core.data.World
|
|||
|
||||
data class ContentScreenUiState(
|
||||
val loading: Boolean = true,
|
||||
val worlds: List<World> = emptyList()
|
||||
val worldList: List<World?> = emptyList() // null is separator
|
||||
)
|
|
@ -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<World>()
|
||||
|
||||
// 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<World>) {
|
||||
private fun updateWorldOrder(newList: List<World?>) {
|
||||
_uiState.update {
|
||||
it.copy(worlds = newList)
|
||||
it.copy(
|
||||
worldList = newList
|
||||
)
|
||||
}
|
||||
|
||||
val backupSources = mutableListOf<BackupSource>()
|
||||
|
||||
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 }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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<List<BackupDestination>>(emptyList())
|
||||
val destinations: StateFlow<List<BackupDestination>> = _destinations.asStateFlow()
|
||||
private val _destinationsFlow = MutableStateFlow<List<BackupDestination>>(emptyList())
|
||||
val destinationsFlow: StateFlow<List<BackupDestination>> = _destinationsFlow.asStateFlow()
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
settingsRepository.getSettingsFlow().collect { settings ->
|
||||
_destinations.update {
|
||||
settings.destinationsList
|
||||
}
|
||||
settingsRepository.backupDestinationsFlow.collect { destinations ->
|
||||
_destinationsFlow.update { destinations }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ class SetupActivity : ComponentActivity() {
|
|||
if (!viewModel.checkIfCanProceed()) return
|
||||
|
||||
startActivity(Intent(applicationContext, HomeActivity::class.java))
|
||||
finishActivity(0)
|
||||
finish()
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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<SetupUiState> = _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<String> {
|
||||
val packageManager = appContext.packageManager
|
||||
|
||||
return POJAV_PACKAGES.filter {
|
||||
try {
|
||||
packageManager.getPackageInfo(it, 0)
|
||||
true
|
||||
} catch (e: NameNotFoundException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue