🛠️ Create PermissionRepository
* Created PermissionRepository that manages all permissions
This commit is contained in:
parent
9866641367
commit
9670470f7e
8 changed files with 271 additions and 219 deletions
|
|
@ -23,12 +23,14 @@ import ua.acclorite.book_story.data.repository.ColorPresetRepositoryImpl
|
||||||
import ua.acclorite.book_story.data.repository.DataStoreRepositoryImpl
|
import ua.acclorite.book_story.data.repository.DataStoreRepositoryImpl
|
||||||
import ua.acclorite.book_story.data.repository.FileSystemRepositoryImpl
|
import ua.acclorite.book_story.data.repository.FileSystemRepositoryImpl
|
||||||
import ua.acclorite.book_story.data.repository.HistoryRepositoryImpl
|
import ua.acclorite.book_story.data.repository.HistoryRepositoryImpl
|
||||||
|
import ua.acclorite.book_story.data.repository.PermissionRepositoryImpl
|
||||||
import ua.acclorite.book_story.data.repository.RemoteRepositoryImpl
|
import ua.acclorite.book_story.data.repository.RemoteRepositoryImpl
|
||||||
import ua.acclorite.book_story.domain.repository.BookRepository
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
import ua.acclorite.book_story.domain.repository.ColorPresetRepository
|
import ua.acclorite.book_story.domain.repository.ColorPresetRepository
|
||||||
import ua.acclorite.book_story.domain.repository.DataStoreRepository
|
import ua.acclorite.book_story.domain.repository.DataStoreRepository
|
||||||
import ua.acclorite.book_story.domain.repository.FileSystemRepository
|
import ua.acclorite.book_story.domain.repository.FileSystemRepository
|
||||||
import ua.acclorite.book_story.domain.repository.HistoryRepository
|
import ua.acclorite.book_story.domain.repository.HistoryRepository
|
||||||
|
import ua.acclorite.book_story.domain.repository.PermissionRepository
|
||||||
import ua.acclorite.book_story.domain.repository.RemoteRepository
|
import ua.acclorite.book_story.domain.repository.RemoteRepository
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
|
@ -77,6 +79,12 @@ abstract class RepositoryModule {
|
||||||
remoteRepositoryImpl: RemoteRepositoryImpl
|
remoteRepositoryImpl: RemoteRepositoryImpl
|
||||||
): RemoteRepository
|
): RemoteRepository
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
abstract fun bindPermissionRepository(
|
||||||
|
permissionRepositoryImpl: PermissionRepositoryImpl
|
||||||
|
): PermissionRepository
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@Singleton
|
@Singleton
|
||||||
abstract fun bindBookMapper(
|
abstract fun bindBookMapper(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
package ua.acclorite.book_story.data.repository
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Environment
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
|
import com.google.accompanist.permissions.PermissionState
|
||||||
|
import com.google.accompanist.permissions.isGranted
|
||||||
|
import com.google.accompanist.permissions.shouldShowRationale
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.yield
|
||||||
|
import ua.acclorite.book_story.domain.repository.PermissionRepository
|
||||||
|
import ua.acclorite.book_story.presentation.core.util.launchActivity
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
private const val STORAGE_PERMISSION = "STORAGE PERM, REPO"
|
||||||
|
private const val NOTIFICATIONS_PERMISSION = "NOTIFIC PERM, REPO"
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class PermissionRepositoryImpl @Inject constructor() : PermissionRepository {
|
||||||
|
|
||||||
|
@SuppressLint("InlinedApi")
|
||||||
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
|
override suspend fun grantStoragePermission(
|
||||||
|
activity: ComponentActivity,
|
||||||
|
storagePermissionState: PermissionState
|
||||||
|
): Boolean {
|
||||||
|
Log.i(STORAGE_PERMISSION, "Requested storage permission")
|
||||||
|
val legacyStoragePermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
||||||
|
|
||||||
|
val permissionGranted = if (legacyStoragePermission) {
|
||||||
|
storagePermissionState.status.isGranted
|
||||||
|
} else Environment.isExternalStorageManager()
|
||||||
|
|
||||||
|
if (permissionGranted) {
|
||||||
|
Log.i(STORAGE_PERMISSION, "Granted: Storage Permission is already granted")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
when (legacyStoragePermission) {
|
||||||
|
true -> {
|
||||||
|
if (!storagePermissionState.status.shouldShowRationale) {
|
||||||
|
storagePermissionState.launchPermissionRequest()
|
||||||
|
} else {
|
||||||
|
val uri = Uri.parse("package:${activity.packageName}")
|
||||||
|
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, uri)
|
||||||
|
|
||||||
|
intent.launchActivity(activity) {
|
||||||
|
Log.e(
|
||||||
|
STORAGE_PERMISSION,
|
||||||
|
"Could not launch \"ACTION_APPLICATION_DETAILS_SETTINGS\" activity"
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false -> {
|
||||||
|
val uri = Uri.parse("package:${activity.packageName}")
|
||||||
|
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri)
|
||||||
|
|
||||||
|
intent.launchActivity(activity) {
|
||||||
|
Log.e(
|
||||||
|
STORAGE_PERMISSION,
|
||||||
|
"Could not launch \"ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION\" activity"
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in 1..30) {
|
||||||
|
val granted = if (legacyStoragePermission) {
|
||||||
|
storagePermissionState.status.isGranted
|
||||||
|
} else Environment.isExternalStorageManager()
|
||||||
|
|
||||||
|
if (!granted) {
|
||||||
|
delay(1000)
|
||||||
|
yield()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
yield()
|
||||||
|
|
||||||
|
Log.i(STORAGE_PERMISSION, "Successfully granted")
|
||||||
|
return true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.e(STORAGE_PERMISSION, "Not granted: Timeout")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
|
override suspend fun grantNotificationsPermission(
|
||||||
|
activity: ComponentActivity,
|
||||||
|
notificationsPermissionState: PermissionState
|
||||||
|
): Boolean {
|
||||||
|
Log.i(NOTIFICATIONS_PERMISSION, "Requested notifications permission")
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
Log.w(NOTIFICATIONS_PERMISSION, "Granted: API is below 33")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationsPermissionState.status.isGranted) {
|
||||||
|
Log.i(NOTIFICATIONS_PERMISSION, "Granted: Notifications Permission is already granted")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!notificationsPermissionState.status.shouldShowRationale) {
|
||||||
|
notificationsPermissionState.launchPermissionRequest()
|
||||||
|
} else {
|
||||||
|
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
|
||||||
|
intent.putExtra(Settings.EXTRA_APP_PACKAGE, activity.packageName)
|
||||||
|
|
||||||
|
intent.launchActivity(activity) {
|
||||||
|
Log.e(
|
||||||
|
NOTIFICATIONS_PERMISSION,
|
||||||
|
"Could not launch \"APP_NOTIFICATION_SETTINGS\" activity"
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in 1..20) {
|
||||||
|
if (!notificationsPermissionState.status.isGranted) {
|
||||||
|
delay(1000)
|
||||||
|
yield()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
yield()
|
||||||
|
|
||||||
|
Log.i(NOTIFICATIONS_PERMISSION, "Successfully granted")
|
||||||
|
return true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.e(NOTIFICATIONS_PERMISSION, "Not granted: Timeout")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package ua.acclorite.book_story.domain.repository
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
|
import com.google.accompanist.permissions.PermissionState
|
||||||
|
|
||||||
|
interface PermissionRepository {
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
|
suspend fun grantStoragePermission(
|
||||||
|
activity: ComponentActivity,
|
||||||
|
storagePermissionState: PermissionState
|
||||||
|
): Boolean
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
|
suspend fun grantNotificationsPermission(
|
||||||
|
activity: ComponentActivity,
|
||||||
|
notificationsPermissionState: PermissionState
|
||||||
|
): Boolean
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package ua.acclorite.book_story.domain.use_case.permission
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
|
import com.google.accompanist.permissions.PermissionState
|
||||||
|
import ua.acclorite.book_story.domain.repository.PermissionRepository
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class GrantNotificationsPermission @Inject constructor(
|
||||||
|
private val repository: PermissionRepository
|
||||||
|
) {
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
|
suspend fun execute(
|
||||||
|
activity: ComponentActivity,
|
||||||
|
notificationsPermissionState: PermissionState
|
||||||
|
): Boolean {
|
||||||
|
return repository.grantNotificationsPermission(
|
||||||
|
activity = activity,
|
||||||
|
notificationsPermissionState = notificationsPermissionState
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package ua.acclorite.book_story.domain.use_case.permission
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
|
import com.google.accompanist.permissions.PermissionState
|
||||||
|
import ua.acclorite.book_story.domain.repository.PermissionRepository
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class GrantStoragePermission @Inject constructor(
|
||||||
|
private val repository: PermissionRepository
|
||||||
|
) {
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
|
suspend fun execute(
|
||||||
|
activity: ComponentActivity,
|
||||||
|
storagePermissionState: PermissionState
|
||||||
|
): Boolean {
|
||||||
|
return repository.grantStoragePermission(
|
||||||
|
activity = activity,
|
||||||
|
storagePermissionState = storagePermissionState
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,11 @@
|
||||||
package ua.acclorite.book_story.ui.browse
|
package ua.acclorite.book_story.ui.browse
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.Settings
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
import com.google.accompanist.permissions.isGranted
|
import com.google.accompanist.permissions.isGranted
|
||||||
import com.google.accompanist.permissions.shouldShowRationale
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
|
@ -31,7 +27,7 @@ import ua.acclorite.book_story.domain.library.book.SelectableNullableBook
|
||||||
import ua.acclorite.book_story.domain.use_case.book.InsertBook
|
import ua.acclorite.book_story.domain.use_case.book.InsertBook
|
||||||
import ua.acclorite.book_story.domain.use_case.file_system.GetBookFromFile
|
import ua.acclorite.book_story.domain.use_case.file_system.GetBookFromFile
|
||||||
import ua.acclorite.book_story.domain.use_case.file_system.GetFilesFromDevice
|
import ua.acclorite.book_story.domain.use_case.file_system.GetFilesFromDevice
|
||||||
import ua.acclorite.book_story.presentation.core.util.launchActivity
|
import ua.acclorite.book_story.domain.use_case.permission.GrantStoragePermission
|
||||||
import ua.acclorite.book_story.presentation.core.util.showToast
|
import ua.acclorite.book_story.presentation.core.util.showToast
|
||||||
import ua.acclorite.book_story.ui.library.LibraryScreen
|
import ua.acclorite.book_story.ui.library.LibraryScreen
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -40,6 +36,7 @@ import kotlin.collections.map
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class BrowseModel @Inject constructor(
|
class BrowseModel @Inject constructor(
|
||||||
|
private val grantStoragePermission: GrantStoragePermission,
|
||||||
private val getFilesFromDevice: GetFilesFromDevice,
|
private val getFilesFromDevice: GetFilesFromDevice,
|
||||||
private val getBookFromFile: GetBookFromFile,
|
private val getBookFromFile: GetBookFromFile,
|
||||||
private val insertBook: InsertBook
|
private val insertBook: InsertBook
|
||||||
|
|
@ -274,72 +271,13 @@ class BrowseModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BrowseEvent.OnActionPermissionDialog -> {
|
is BrowseEvent.OnActionPermissionDialog -> {
|
||||||
viewModelScope.launch {
|
|
||||||
val legacyStoragePermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
|
||||||
val isPermissionGranted = if (legacyStoragePermission) {
|
|
||||||
event.storagePermissionState.status.isGranted
|
|
||||||
} else {
|
|
||||||
Environment.isExternalStorageManager()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPermissionGranted) {
|
|
||||||
_state.update {
|
|
||||||
it.copy(
|
|
||||||
dialog = null,
|
|
||||||
isError = false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onEvent(
|
|
||||||
BrowseEvent.OnRefreshList(
|
|
||||||
showIndicator = true,
|
|
||||||
hideSearch = false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
|
|
||||||
if (legacyStoragePermission) {
|
|
||||||
if (!event.storagePermissionState.status.shouldShowRationale) {
|
|
||||||
event.storagePermissionState.launchPermissionRequest()
|
|
||||||
} else {
|
|
||||||
val uri = Uri.parse("package:${event.activity.packageName}")
|
|
||||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, uri)
|
|
||||||
|
|
||||||
intent.launchActivity(event.activity) {
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!legacyStoragePermission) {
|
|
||||||
val uri = Uri.parse("package:${event.activity.packageName}")
|
|
||||||
val intent = Intent(
|
|
||||||
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
|
|
||||||
uri
|
|
||||||
)
|
|
||||||
|
|
||||||
intent.launchActivity(event.activity) {
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
storagePermissionJob?.cancel()
|
storagePermissionJob?.cancel()
|
||||||
storagePermissionJob = launch {
|
storagePermissionJob = viewModelScope.launch(Dispatchers.IO) {
|
||||||
while (true) {
|
grantStoragePermission.execute(
|
||||||
val granted = if (legacyStoragePermission) {
|
activity = event.activity,
|
||||||
event.storagePermissionState.status.isGranted
|
storagePermissionState = event.storagePermissionState
|
||||||
} else {
|
).apply {
|
||||||
Environment.isExternalStorageManager()
|
if (this) {
|
||||||
}
|
|
||||||
|
|
||||||
if (!granted) {
|
|
||||||
delay(1000)
|
|
||||||
yield()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
yield()
|
|
||||||
|
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
dialog = null,
|
dialog = null,
|
||||||
|
|
@ -352,7 +290,6 @@ class BrowseModel @Inject constructor(
|
||||||
hideSearch = false
|
hideSearch = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -361,19 +298,22 @@ class BrowseModel @Inject constructor(
|
||||||
is BrowseEvent.OnDismissPermissionDialog -> {
|
is BrowseEvent.OnDismissPermissionDialog -> {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val legacyPermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
val legacyPermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
||||||
val isPermissionGranted = if (!legacyPermission) {
|
val permissionGranted = if (!legacyPermission) {
|
||||||
Environment.isExternalStorageManager()
|
Environment.isExternalStorageManager()
|
||||||
} else event.storagePermissionState.status.isGranted
|
} else event.storagePermissionState.status.isGranted
|
||||||
|
|
||||||
storagePermissionJob?.cancel()
|
storagePermissionJob?.cancel()
|
||||||
_state.update { it.copy(dialog = null) }
|
_state.update {
|
||||||
|
it.copy(
|
||||||
|
isError = !permissionGranted,
|
||||||
|
dialog = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (isPermissionGranted) {
|
if (permissionGranted) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
getFilesFromDownloads()
|
getFilesFromDownloads()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
_state.update { it.copy(isError = true) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,12 @@
|
||||||
package ua.acclorite.book_story.ui.settings
|
package ua.acclorite.book_story.ui.settings
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
|
||||||
import android.provider.Settings
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
import com.google.accompanist.permissions.isGranted
|
|
||||||
import com.google.accompanist.permissions.shouldShowRationale
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -27,15 +21,16 @@ import ua.acclorite.book_story.domain.use_case.color_preset.GetColorPresets
|
||||||
import ua.acclorite.book_story.domain.use_case.color_preset.ReorderColorPresets
|
import ua.acclorite.book_story.domain.use_case.color_preset.ReorderColorPresets
|
||||||
import ua.acclorite.book_story.domain.use_case.color_preset.SelectColorPreset
|
import ua.acclorite.book_story.domain.use_case.color_preset.SelectColorPreset
|
||||||
import ua.acclorite.book_story.domain.use_case.color_preset.UpdateColorPreset
|
import ua.acclorite.book_story.domain.use_case.color_preset.UpdateColorPreset
|
||||||
|
import ua.acclorite.book_story.domain.use_case.permission.GrantNotificationsPermission
|
||||||
import ua.acclorite.book_story.presentation.core.constants.Constants
|
import ua.acclorite.book_story.presentation.core.constants.Constants
|
||||||
import ua.acclorite.book_story.presentation.core.constants.provideDefaultColorPreset
|
import ua.acclorite.book_story.presentation.core.constants.provideDefaultColorPreset
|
||||||
import ua.acclorite.book_story.presentation.core.util.launchActivity
|
|
||||||
import ua.acclorite.book_story.presentation.core.util.showToast
|
import ua.acclorite.book_story.presentation.core.util.showToast
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class SettingsModel @Inject constructor(
|
class SettingsModel @Inject constructor(
|
||||||
|
private val grantNotificationsPermission: GrantNotificationsPermission,
|
||||||
private val getColorPresets: GetColorPresets,
|
private val getColorPresets: GetColorPresets,
|
||||||
private val updateColorPreset: UpdateColorPreset,
|
private val updateColorPreset: UpdateColorPreset,
|
||||||
private val selectColorPreset: SelectColorPreset,
|
private val selectColorPreset: SelectColorPreset,
|
||||||
|
|
@ -98,45 +93,20 @@ class SettingsModel @Inject constructor(
|
||||||
fun onEvent(event: SettingsEvent) {
|
fun onEvent(event: SettingsEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is SettingsEvent.OnChangeCheckForUpdates -> {
|
is SettingsEvent.OnChangeCheckForUpdates -> {
|
||||||
|
notificationsPermissionJob?.cancel()
|
||||||
|
notificationsPermissionJob = viewModelScope.launch(Dispatchers.IO) {
|
||||||
if (!event.enable) {
|
if (!event.enable) {
|
||||||
event.onChangeCheckForUpdates(false)
|
event.onChangeCheckForUpdates(false)
|
||||||
return
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
grantNotificationsPermission.execute(
|
||||||
|
activity = event.activity,
|
||||||
|
notificationsPermissionState = event.notificationsPermissionState
|
||||||
|
).apply {
|
||||||
|
if (this) {
|
||||||
event.onChangeCheckForUpdates(true)
|
event.onChangeCheckForUpdates(true)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.notificationsPermissionState.status.isGranted) {
|
|
||||||
event.onChangeCheckForUpdates(true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!event.notificationsPermissionState.status.shouldShowRationale) {
|
|
||||||
event.notificationsPermissionState.launchPermissionRequest()
|
|
||||||
} else {
|
|
||||||
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
|
|
||||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, event.activity.packageName)
|
|
||||||
|
|
||||||
intent.launchActivity(event.activity) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationsPermissionJob?.cancel()
|
|
||||||
notificationsPermissionJob = viewModelScope.launch {
|
|
||||||
for (i in 1..10) {
|
|
||||||
if (!event.notificationsPermissionState.status.isGranted) {
|
|
||||||
delay(1000)
|
|
||||||
yield()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
yield()
|
|
||||||
|
|
||||||
event.onChangeCheckForUpdates(true)
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,28 @@
|
||||||
package ua.acclorite.book_story.ui.start
|
package ua.acclorite.book_story.ui.start
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.Settings
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
import com.google.accompanist.permissions.isGranted
|
import com.google.accompanist.permissions.isGranted
|
||||||
import com.google.accompanist.permissions.shouldShowRationale
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.yield
|
import kotlinx.coroutines.yield
|
||||||
import ua.acclorite.book_story.presentation.core.util.launchActivity
|
import ua.acclorite.book_story.domain.use_case.permission.GrantNotificationsPermission
|
||||||
|
import ua.acclorite.book_story.domain.use_case.permission.GrantStoragePermission
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class StartModel @Inject constructor(
|
class StartModel @Inject constructor(
|
||||||
|
private val grantStoragePermission: GrantStoragePermission,
|
||||||
|
private val grantNotificationsPermission: GrantNotificationsPermission
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val mutex = Mutex()
|
private val mutex = Mutex()
|
||||||
|
|
@ -62,113 +59,36 @@ class StartModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is StartEvent.OnStoragePermissionRequest -> {
|
is StartEvent.OnStoragePermissionRequest -> {
|
||||||
viewModelScope.launch {
|
|
||||||
val legacyStoragePermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
|
||||||
|
|
||||||
val isPermissionGranted = if (legacyStoragePermission) {
|
|
||||||
event.storagePermissionState.status.isGranted
|
|
||||||
} else Environment.isExternalStorageManager()
|
|
||||||
|
|
||||||
if (isPermissionGranted) {
|
|
||||||
_state.update {
|
|
||||||
it.copy(
|
|
||||||
storagePermissionGranted = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
|
|
||||||
if (legacyStoragePermission) {
|
|
||||||
if (!event.storagePermissionState.status.shouldShowRationale) {
|
|
||||||
event.storagePermissionState.launchPermissionRequest()
|
|
||||||
} else {
|
|
||||||
val uri = Uri.parse("package:${event.activity.packageName}")
|
|
||||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, uri)
|
|
||||||
|
|
||||||
intent.launchActivity(event.activity) {
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!legacyStoragePermission) {
|
|
||||||
val uri = Uri.parse("package:${event.activity.packageName}")
|
|
||||||
val intent = Intent(
|
|
||||||
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
|
|
||||||
uri
|
|
||||||
)
|
|
||||||
|
|
||||||
intent.launchActivity(event.activity) {
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
storagePermissionJob?.cancel()
|
storagePermissionJob?.cancel()
|
||||||
storagePermissionJob = viewModelScope.launch {
|
storagePermissionJob = viewModelScope.launch(Dispatchers.IO) {
|
||||||
while (true) {
|
grantStoragePermission.execute(
|
||||||
val granted = if (legacyStoragePermission) {
|
activity = event.activity,
|
||||||
event.storagePermissionState.status.isGranted
|
storagePermissionState = event.storagePermissionState
|
||||||
} else Environment.isExternalStorageManager()
|
).apply {
|
||||||
|
if (this) {
|
||||||
if (!granted) {
|
|
||||||
delay(1000)
|
|
||||||
yield()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
yield()
|
|
||||||
|
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
storagePermissionGranted = true
|
storagePermissionGranted = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is StartEvent.OnNotificationsPermissionRequest -> {
|
is StartEvent.OnNotificationsPermissionRequest -> {
|
||||||
viewModelScope.launch {
|
|
||||||
if (event.notificationsPermissionState.status.isGranted) {
|
|
||||||
_state.update {
|
|
||||||
it.copy(
|
|
||||||
notificationsPermissionGranted = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!event.notificationsPermissionState.status.shouldShowRationale) {
|
|
||||||
event.notificationsPermissionState.launchPermissionRequest()
|
|
||||||
} else {
|
|
||||||
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
|
|
||||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, event.activity.packageName)
|
|
||||||
|
|
||||||
intent.launchActivity(event.activity) {
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationsPermissionJob?.cancel()
|
notificationsPermissionJob?.cancel()
|
||||||
notificationsPermissionJob = viewModelScope.launch {
|
notificationsPermissionJob = viewModelScope.launch(Dispatchers.IO) {
|
||||||
while (true) {
|
grantNotificationsPermission.execute(
|
||||||
if (!event.notificationsPermissionState.status.isGranted) {
|
activity = event.activity,
|
||||||
delay(1000)
|
notificationsPermissionState = event.notificationsPermissionState
|
||||||
yield()
|
).apply {
|
||||||
continue
|
if (this) {
|
||||||
}
|
|
||||||
|
|
||||||
yield()
|
|
||||||
|
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
notificationsPermissionGranted = true
|
notificationsPermissionGranted = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue