This commit is contained in:
Minecon724 2025-04-27 09:21:42 +02:00
commit e88efe5f2d
Signed by: Minecon724
GPG key ID: A02E6E67AB961189
5 changed files with 61 additions and 30 deletions

View file

@ -18,7 +18,6 @@ import eu.m724.pojavbackup.core.backup.Backup.BackupStatus
import eu.m724.pojavbackup.core.data.GameDataRepository
import eu.m724.pojavbackup.core.datastore.SettingsRepository
import eu.m724.pojavbackup.notification.NotificationChannels
import kotlinx.coroutines.delay
import org.apache.commons.compress.compressors.CompressorStreamFactory
import java.time.LocalDate
import java.time.format.DateTimeFormatter
@ -50,8 +49,6 @@ class BackupWorker @AssistedInject constructor(
updateStatus("Initializing")
delay(10000)
val settings = settingsRepository.getSettings()
val worldIds = settingsRepository.getIncludedWorldIds(settings.worldOrder)

View file

@ -30,7 +30,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.core.content.ContextCompat.startActivity
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.compose.NavHost
@ -43,8 +45,8 @@ import eu.m724.pojavbackup.home.screen.HomeScreen
import eu.m724.pojavbackup.home.screen.dashboard.DashboardScreen
import eu.m724.pojavbackup.home.screen.history.HistoryScreen
import eu.m724.pojavbackup.settings.SettingsActivity
import eu.m724.pojavbackup.setup.SetupActivity
import eu.m724.pojavbackup.ui.theme.PojavBackupTheme
import kotlinx.coroutines.launch
@AndroidEntryPoint
class HomeActivity : ComponentActivity() {
@ -62,8 +64,8 @@ class HomeActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
viewModel.load(
onSetupNeeded = {
setupResult.launch(Intent(applicationContext, SetupActivity::class.java))
onSetupRequired = {
setupResult.launch(it)
}
)

View file

@ -1,9 +1,13 @@
package eu.m724.pojavbackup.home
import android.Manifest
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
@ -12,6 +16,7 @@ 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
@ -38,14 +43,20 @@ class HomeViewModel @Inject constructor(
}
fun load(
onSetupNeeded: () -> Unit
onSetupRequired: (Intent) -> Unit
) {
viewModelScope.launch {
val uri = settingsRepository.getSource()
if (uri == null || !checkForStoragePermission(uri)) {
// TODO there could be that only one or two permissions are missing
onSetupNeeded()
val storagePermission = uri?.let { checkForStoragePermission(uri) } == true
val notificationPermission = checkForNotificationPermission()
if (!storagePermission || !notificationPermission) {
val intent = Intent(appContext, SetupActivity::class.java)
.putExtra("storagePermissionGranted", storagePermission)
.putExtra("notificationPermissionGranted", notificationPermission)
onSetupRequired(intent)
} else {
_uiState.update { it.copy(loading = false) }
}
@ -75,4 +86,9 @@ class HomeViewModel @Inject constructor(
return true
}
private fun checkForNotificationPermission(): Boolean {
// TODO check if rejected
return ContextCompat.checkSelfPermission(appContext, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
}
}

View file

@ -1,5 +1,6 @@
package eu.m724.pojavbackup.setup
import android.Manifest
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
@ -37,7 +38,7 @@ class SetupActivity : ComponentActivity() {
private val viewModel: SetupViewModel by viewModels()
private val openDocumentTree = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) {
viewModel.onOpenDocumentTree(applicationContext, it) { success ->
viewModel.onOpenDocumentTree(it) { success ->
if (success) {
onComplete()
} else {
@ -51,16 +52,18 @@ class SetupActivity : ComponentActivity() {
}
}
private val notificationGrant = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
onComplete()
} else {
// TODO instead red text?
Toast.makeText(
applicationContext,
"This is not a PojavLauncher directory.",
Toast.LENGTH_SHORT
).show()
private val notificationGrant = registerForActivityResult(ActivityResultContracts.RequestPermission()) {
viewModel.onNotificationGrant(it) { success ->
if (success) {
onComplete()
} else {
// TODO instead red text?
Toast.makeText(
applicationContext,
"This is not a PojavLauncher directory.",
Toast.LENGTH_SHORT
).show()
}
}
}
@ -95,7 +98,7 @@ class SetupActivity : ComponentActivity() {
openDocumentTree.launch(defaultUri)
},
onNotificationPermissionGrantClick = {
openDocumentTree.launch(defaultUri)
notificationGrant.launch(Manifest.permission.POST_NOTIFICATIONS)
}
)
}
@ -134,7 +137,7 @@ fun SetupScreen(
GrantCard(
title = "Notification permission",
description = "It's needed to notify you about backup status.",
granted = uiState.storagePermissionGranted,
granted = uiState.notificationPermissionGranted,
onClick = onNotificationPermissionGrantClick
)
}

View file

@ -2,7 +2,6 @@ package eu.m724.pojavbackup.setup
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.PackageManager.NameNotFoundException
import android.net.Uri
import android.util.Log
@ -10,6 +9,7 @@ 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.datastore.SettingsRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@ -20,6 +20,7 @@ import javax.inject.Inject
@HiltViewModel
class SetupViewModel @Inject constructor(
@ApplicationContext private val appContext: Context,
private val settingsRepository: SettingsRepository
) : ViewModel() {
private val TAG: String = javaClass.name
@ -51,16 +52,16 @@ class SetupViewModel @Inject constructor(
}
// TODO we could make the check call separate and not pass context here
fun onOpenDocumentTree(context: Context, uri: Uri?, result: (Boolean) -> Unit) {
fun onOpenDocumentTree(uri: Uri?, result: (Boolean) -> Unit) {
if (uri != null) {
Log.i(TAG, "Got URI: $uri")
context.contentResolver.takePersistableUriPermission(
appContext.contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val hasPermission = checkForStoragePermission(context, uri)
val hasPermission = checkForStoragePermission(uri)
viewModelScope.launch {
if (hasPermission) {
@ -72,11 +73,21 @@ class SetupViewModel @Inject constructor(
}
}
fun checkForStoragePermission(context: Context, uri: Uri): Boolean {
fun onNotificationGrant(isGranted: Boolean, result: (Boolean) -> Unit) {
if (isGranted) {
_uiState.update {
it.copy(notificationPermissionGranted = true)
}
}
result(isGranted)
}
fun checkForStoragePermission(uri: Uri): Boolean {
Log.i(TAG, "Checking for storage permission...")
// TODO Is this the right way? This isn't in https://developer.android.com/training/data-storage/shared/documents-files
val directory = DocumentFile.fromTreeUri(context, uri)
val directory = DocumentFile.fromTreeUri(appContext, uri)
if (directory == null || !directory.isDirectory) {
Log.i(TAG, "No permission or not a directory")
@ -100,7 +111,9 @@ class SetupViewModel @Inject constructor(
return true
}
fun detectInstalledLauncherPackage(packageManager: PackageManager): List<String> {
fun detectInstalledLauncherPackage(): List<String> {
val packageManager = appContext.packageManager
return POJAV_PACKAGES.filter {
try {
packageManager.getPackageInfo(it, 0)