Remove storage permissions
Requires adjusting some file reading to first copy to a temporary file in cache that we have permissions to read from. This is only applicable for things like ZIP files where we need an actual File rather than just some Android content URI shenanigans. (cherry picked from commit 4fcdde4913df28bbd678ae1be4a2971ed77179d3) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt # app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt # source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt
This commit is contained in:
@@ -35,7 +35,6 @@ import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen
|
||||
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
|
||||
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
|
||||
import eu.kanade.presentation.permissions.PermissionRequestHelper
|
||||
import eu.kanade.presentation.util.relativeTimeSpanString
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
||||
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||
@@ -73,8 +72,6 @@ object SettingsDataScreen : SearchableSettings {
|
||||
val backupPreferences = Injekt.get<BackupPreferences>()
|
||||
val storagePreferences = Injekt.get<StoragePreferences>()
|
||||
|
||||
PermissionRequestHelper.requestStoragePermission()
|
||||
|
||||
return listOf(
|
||||
getStorageLocationPref(storagePreferences = storagePreferences),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.pref_storage_location_info)),
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package eu.kanade.presentation.permissions
|
||||
|
||||
import android.Manifest
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
|
||||
/**
|
||||
* Launches request for [Manifest.permission.WRITE_EXTERNAL_STORAGE] permission
|
||||
*/
|
||||
object PermissionRequestHelper {
|
||||
|
||||
@Composable
|
||||
fun requestStoragePermission() {
|
||||
val permissionState = rememberPermissionState(permission = Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
LaunchedEffect(Unit) {
|
||||
permissionState.launchPermissionRequest()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,6 @@ import com.elvishew.xlog.XLog
|
||||
import com.elvishew.xlog.printer.AndroidPrinter
|
||||
import com.elvishew.xlog.printer.Printer
|
||||
import com.elvishew.xlog.printer.file.backup.NeverBackupStrategy
|
||||
import com.elvishew.xlog.printer.file.clean.FileLastModifiedCleanStrategy
|
||||
import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator
|
||||
import eu.kanade.domain.DomainModule
|
||||
import eu.kanade.domain.SYDomainModule
|
||||
@@ -67,7 +66,6 @@ import logcat.LogPriority
|
||||
import logcat.LogcatLogger
|
||||
import org.conscrypt.Conscrypt
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.storage.toFile
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.storage.service.StorageManager
|
||||
import tachiyomi.i18n.MR
|
||||
@@ -78,7 +76,6 @@ import uy.kohesive.injekt.injectLazy
|
||||
import java.security.Security
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import kotlin.time.Duration.Companion.days
|
||||
|
||||
class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
|
||||
|
||||
@@ -250,8 +247,6 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
|
||||
val printers = mutableListOf<Printer>(AndroidPrinter())
|
||||
|
||||
val logFolder = Injekt.get<StorageManager>().getLogsDirectory()
|
||||
?.toFile()
|
||||
?.absolutePath
|
||||
|
||||
if (logFolder != null) {
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())
|
||||
@@ -269,7 +264,6 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
|
||||
flattener { timeMillis, level, tag, message ->
|
||||
"${dateFormat.format(timeMillis)} ${LogLevel.getShortLevelName(level)}/$tag: $message"
|
||||
}
|
||||
cleanStrategy = FileLastModifiedCleanStrategy(7.days.inWholeMilliseconds)
|
||||
backupStrategy = NeverBackupStrategy()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import cafe.adriel.voyager.navigator.tab.TabOptions
|
||||
import eu.kanade.core.preference.asState
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.presentation.components.TabbedScreen
|
||||
import eu.kanade.presentation.permissions.PermissionRequestHelper
|
||||
import eu.kanade.presentation.util.Tab
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreenModel
|
||||
@@ -91,9 +90,6 @@ data class BrowseTab(
|
||||
onChangeSearchQuery = extensionsScreenModel::search,
|
||||
)
|
||||
|
||||
// For local source
|
||||
PermissionRequestHelper.requestStoragePermission()
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
(context as? MainActivity)?.ready = true
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.source.online.all.MergedSource
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.storage.toTempFile
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
@@ -124,13 +125,13 @@ class ChapterLoader(
|
||||
source is LocalSource -> source.getFormat(chapter.chapter).let { format ->
|
||||
when (format) {
|
||||
is Format.Directory -> DirectoryPageLoader(format.file)
|
||||
is Format.Zip -> ZipPageLoader(format.file)
|
||||
is Format.Zip -> ZipPageLoader(format.file.toTempFile(context))
|
||||
is Format.Rar -> try {
|
||||
RarPageLoader(format.file)
|
||||
RarPageLoader(format.file.toTempFile(context))
|
||||
} catch (e: UnsupportedRarV5Exception) {
|
||||
error(context.stringResource(MR.strings.loader_rar5_error))
|
||||
}
|
||||
is Format.Epub -> EpubPageLoader(format.file)
|
||||
is Format.Epub -> EpubPageLoader(format.file.toTempFile(context))
|
||||
}
|
||||
}
|
||||
else -> error(context.stringResource(MR.strings.loader_not_implemented_error))
|
||||
@@ -141,13 +142,13 @@ class ChapterLoader(
|
||||
source is LocalSource -> source.getFormat(chapter.chapter).let { format ->
|
||||
when (format) {
|
||||
is Format.Directory -> DirectoryPageLoader(format.file)
|
||||
is Format.Zip -> ZipPageLoader(format.file)
|
||||
is Format.Zip -> ZipPageLoader(format.file.toTempFile(context))
|
||||
is Format.Rar -> try {
|
||||
RarPageLoader(format.file)
|
||||
RarPageLoader(format.file.toTempFile(context))
|
||||
} catch (e: UnsupportedRarV5Exception) {
|
||||
error(context.stringResource(MR.strings.loader_rar5_error))
|
||||
}
|
||||
is Format.Epub -> EpubPageLoader(format.file)
|
||||
is Format.Epub -> EpubPageLoader(format.file.toTempFile(context))
|
||||
}
|
||||
}
|
||||
source is HttpSource -> HttpPageLoader(chapter, source)
|
||||
|
||||
@@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||
import tachiyomi.core.storage.toTempFile
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
@@ -46,7 +47,7 @@ internal class DownloadPageLoader(
|
||||
}
|
||||
|
||||
private suspend fun getPagesFromArchive(chapterPath: UniFile): List<ReaderPage> {
|
||||
val loader = ZipPageLoader(chapterPath).also { zipPageLoader = it }
|
||||
val loader = ZipPageLoader(chapterPath.toTempFile(context)).also { zipPageLoader = it }
|
||||
return loader.getPages()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package eu.kanade.tachiyomi.ui.reader.loader
|
||||
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||
import eu.kanade.tachiyomi.util.storage.EpubFile
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Loader used to load a chapter from a .epub file.
|
||||
*/
|
||||
internal class EpubPageLoader(file: UniFile) : PageLoader() {
|
||||
internal class EpubPageLoader(file: File) : PageLoader() {
|
||||
|
||||
private val epub = EpubFile(file)
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
||||
import tachiyomi.core.storage.toFile
|
||||
import tachiyomi.core.util.system.ImageUtil
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
@@ -19,9 +18,9 @@ import java.io.PipedOutputStream
|
||||
/**
|
||||
* Loader used to load a chapter from a .rar or .cbr file.
|
||||
*/
|
||||
internal class RarPageLoader(file: UniFile) : PageLoader() {
|
||||
internal class RarPageLoader(file: File) : PageLoader() {
|
||||
|
||||
private val rar = Archive(file.toFile())
|
||||
private val rar = Archive(file)
|
||||
|
||||
// SY -->
|
||||
private val context: Application by injectLazy()
|
||||
@@ -33,7 +32,7 @@ internal class RarPageLoader(file: UniFile) : PageLoader() {
|
||||
init {
|
||||
if (readerPreferences.cacheArchiveMangaOnDisk().get()) {
|
||||
tmpDir.mkdirs()
|
||||
Archive(file.toFile()).use { rar ->
|
||||
Archive(file).use { rar ->
|
||||
rar.fileHeaders.asSequence()
|
||||
.filterNot { it.isDirectory }
|
||||
.forEach { header ->
|
||||
|
||||
@@ -9,7 +9,6 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.storage.toFile
|
||||
import tachiyomi.core.util.system.ImageUtil
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
@@ -21,7 +20,7 @@ import net.lingala.zip4j.ZipFile as Zip4jFile
|
||||
/**
|
||||
* Loader used to load a chapter from a .zip or .cbz file.
|
||||
*/
|
||||
internal class ZipPageLoader(file: UniFile) : PageLoader() {
|
||||
internal class ZipPageLoader(file: File) : PageLoader() {
|
||||
|
||||
// SY -->
|
||||
private val context: Application by injectLazy()
|
||||
@@ -29,12 +28,12 @@ internal class ZipPageLoader(file: UniFile) : PageLoader() {
|
||||
private val tmpDir = File(context.externalCacheDir, "reader_${file.hashCode()}").also {
|
||||
it.deleteRecursively()
|
||||
}
|
||||
private val zip4j: Zip4jFile = Zip4jFile(file.toFile())
|
||||
private val zip4j: Zip4jFile = Zip4jFile(file)
|
||||
private val zip: ZipFile? =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
if (!zip4j.isEncrypted) ZipFile(file.toFile(), StandardCharsets.ISO_8859_1) else null
|
||||
if (!zip4j.isEncrypted) ZipFile(file, StandardCharsets.ISO_8859_1) else null
|
||||
} else {
|
||||
if (!zip4j.isEncrypted) ZipFile(file.toFile()) else null
|
||||
if (!zip4j.isEncrypted) ZipFile(file) else null
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -42,7 +41,7 @@ internal class ZipPageLoader(file: UniFile) : PageLoader() {
|
||||
zip4j.charset = StandardCharsets.ISO_8859_1
|
||||
}
|
||||
|
||||
Zip4jFile(file.toFile()).use { zip ->
|
||||
Zip4jFile(file).use { zip ->
|
||||
if (zip.isEncrypted) {
|
||||
if (!CbzCrypto.checkCbzPassword(zip, CbzCrypto.getDecryptedPasswordCbz())) {
|
||||
this.recycle()
|
||||
|
||||
Reference in New Issue
Block a user