feat: request for writing storage permission when saving pictures (Android P & below)
This commit is contained in:
parent
c16ed41c2f
commit
ccde68f4f8
3 changed files with 61 additions and 3 deletions
|
|
@ -1,7 +1,10 @@
|
||||||
package eu.kanade.tachiyomi.ui.manga
|
package eu.kanade.tachiyomi.ui.manga
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
|
@ -462,12 +465,31 @@ class MangaScreen(
|
||||||
if (it == null) return@rememberLauncherForActivityResult
|
if (it == null) return@rememberLauncherForActivityResult
|
||||||
sm.editCover(context, it)
|
sm.editCover(context, it)
|
||||||
}
|
}
|
||||||
|
// KMK -->
|
||||||
|
val externalStoragePermissionNotGranted = Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
|
||||||
|
context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
|
||||||
|
PackageManager.PERMISSION_DENIED
|
||||||
|
val saveCoverPermissionRequester = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.RequestPermission(),
|
||||||
|
onResult = {
|
||||||
|
sm.saveCover(context)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
// KMK <--
|
||||||
MangaCoverDialog(
|
MangaCoverDialog(
|
||||||
coverDataProvider = { manga!! },
|
coverDataProvider = { manga!! },
|
||||||
snackbarHostState = sm.snackbarHostState,
|
snackbarHostState = sm.snackbarHostState,
|
||||||
isCustomCover = remember(manga) { manga!!.hasCustomCover() },
|
isCustomCover = remember(manga) { manga!!.hasCustomCover() },
|
||||||
onShareClick = { sm.shareCover(context) },
|
onShareClick = { sm.shareCover(context) },
|
||||||
onSaveClick = { sm.saveCover(context) },
|
onSaveClick = {
|
||||||
|
// KMK -->
|
||||||
|
if (externalStoragePermissionNotGranted) {
|
||||||
|
saveCoverPermissionRequester.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
} else {
|
||||||
|
// KMK <--
|
||||||
|
sm.saveCover(context)
|
||||||
|
}
|
||||||
|
},
|
||||||
onEditClick = {
|
onEditClick = {
|
||||||
when (it) {
|
when (it) {
|
||||||
EditCoverAction.EDIT -> getContent.launch("image/*")
|
EditCoverAction.EDIT -> getContent.launch("image/*")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.ui.reader
|
package eu.kanade.tachiyomi.ui.reader
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.assist.AssistContent
|
import android.app.assist.AssistContent
|
||||||
|
|
@ -7,6 +8,7 @@ import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.ColorMatrix
|
import android.graphics.ColorMatrix
|
||||||
|
|
@ -21,6 +23,8 @@ import android.view.View
|
||||||
import android.view.View.LAYER_TYPE_HARDWARE
|
import android.view.View.LAYER_TYPE_HARDWARE
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
|
@ -39,6 +43,7 @@ import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
|
|
@ -132,6 +137,7 @@ import tachiyomi.domain.manga.model.MangaCover
|
||||||
import tachiyomi.domain.manga.model.asMangaCover
|
import tachiyomi.domain.manga.model.asMangaCover
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
|
import tachiyomi.i18n.kmk.KMR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
import tachiyomi.presentation.core.util.collectAsState
|
import tachiyomi.presentation.core.util.collectAsState
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
|
@ -420,6 +426,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun dialogRootContent() {
|
fun dialogRootContent() {
|
||||||
|
val context = LocalContext.current
|
||||||
// KMK <--
|
// KMK <--
|
||||||
val state by viewModel.state.collectAsState()
|
val state by viewModel.state.collectAsState()
|
||||||
val settingsScreenModel = remember {
|
val settingsScreenModel = remember {
|
||||||
|
|
@ -479,6 +486,18 @@ class ReaderActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
val externalStoragePermissionNotGranted = Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
|
||||||
|
context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
|
||||||
|
PackageManager.PERMISSION_DENIED
|
||||||
|
val permissionRequester = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.RequestPermission(),
|
||||||
|
onResult = {
|
||||||
|
toast(KMR.strings.permission_writing_external_storage_succeed)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
ReaderContentOverlay(
|
ReaderContentOverlay(
|
||||||
brightness = state.brightnessOverlayValue,
|
brightness = state.brightnessOverlayValue,
|
||||||
color = colorOverlay.takeIf { colorOverlayEnabled },
|
color = colorOverlay.takeIf { colorOverlayEnabled },
|
||||||
|
|
@ -623,9 +642,25 @@ class ReaderActivity : BaseActivity() {
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
onSetAsCover = viewModel::setAsCover,
|
onSetAsCover = viewModel::setAsCover,
|
||||||
onShare = viewModel::shareImage,
|
onShare = viewModel::shareImage,
|
||||||
onSave = viewModel::saveImage,
|
onSave = { extra ->
|
||||||
|
// KMK -->
|
||||||
|
if (externalStoragePermissionNotGranted) {
|
||||||
|
permissionRequester.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
} else {
|
||||||
|
// KMK <--
|
||||||
|
viewModel.saveImage(extra)
|
||||||
|
}
|
||||||
|
},
|
||||||
onShareCombined = viewModel::shareImages,
|
onShareCombined = viewModel::shareImages,
|
||||||
onSaveCombined = viewModel::saveImages,
|
onSaveCombined = {
|
||||||
|
// KMK -->
|
||||||
|
if (externalStoragePermissionNotGranted) {
|
||||||
|
permissionRequester.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
} else {
|
||||||
|
// KMK <--
|
||||||
|
viewModel.saveImages()
|
||||||
|
}
|
||||||
|
},
|
||||||
hasExtraPage = (state.dialog as? ReaderViewModel.Dialog.PageActions)?.extraPage != null,
|
hasExtraPage = (state.dialog as? ReaderViewModel.Dialog.PageActions)?.extraPage != null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@
|
||||||
<string name="onboarding_permission_external_storage">Access media files permission</string>
|
<string name="onboarding_permission_external_storage">Access media files permission</string>
|
||||||
<string name="onboarding_permission_external_storage_description">Allow using custom covers in entry's Edit Info</string>
|
<string name="onboarding_permission_external_storage_description">Allow using custom covers in entry's Edit Info</string>
|
||||||
<string name="onboarding_permission_writing_external_storage_description">Allow saving covers & using custom covers in entry's Edit Info</string>
|
<string name="onboarding_permission_writing_external_storage_description">Allow saving covers & using custom covers in entry's Edit Info</string>
|
||||||
|
<string name="permission_writing_external_storage_succeed">Permission granted. Try action again.</string>
|
||||||
|
|
||||||
<!-- About section -->
|
<!-- About section -->
|
||||||
<string name="whats_coming">What\'s coming (soon)</string>
|
<string name="whats_coming">What\'s coming (soon)</string>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue