Don't use app-specific dir as default download dir
This commit is contained in:
1 parent
11b09f187c
commit
e322878b95
11 files changed
+67
-71
No files matched your search
@@ -1029,7 +1029,7 @@ var downloadLocation: UniFile
|
||||
encodedQuery(downloadQuery)
|
||||
encodedFragment(downloadFragment)
|
||||
}.build()
|
||||
uri.asUniFileOrNull() ?: requireNotNull(AppConfig.defaultDownloadDir).asUniFile()
|
||||
uri.asUniFileOrNull() ?: AppConfig.defaultDownloadDir?.asUniFile() ?: UniFile.Stub
|
||||
}
|
||||
set(value) = with(value.uri) {
|
||||
Settings.edit {
|
||||
|
||||
@@ -91,12 +91,14 @@ private fun ensureNoMediaFile(downloadDir: UniFile) {
|
||||
|
||||
private val lck = Mutex()
|
||||
|
||||
suspend fun keepNoMediaFileStatus() {
|
||||
lck.withLock {
|
||||
if (Settings.mediaScan) {
|
||||
removeNoMediaFile(downloadLocation)
|
||||
} else {
|
||||
ensureNoMediaFile(downloadLocation)
|
||||
suspend fun keepNoMediaFileStatus(downloadDir: UniFile = downloadLocation) {
|
||||
if (downloadDir.isDirectory) {
|
||||
lck.withLock {
|
||||
if (Settings.mediaScan) {
|
||||
removeNoMediaFile(downloadDir)
|
||||
} else {
|
||||
ensureNoMediaFile(downloadDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ import com.hippo.ehviewer.download.downloadLocation
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.filled.Subscriptions
|
||||
import com.hippo.ehviewer.image.Image.Companion.decodeBitmap
|
||||
import com.hippo.ehviewer.ui.destinations.DownloadScreenDestination
|
||||
import com.hippo.ehviewer.ui.destinations.DownloadsScreenDestination
|
||||
import com.hippo.ehviewer.ui.destinations.FavouritesScreenDestination
|
||||
import com.hippo.ehviewer.ui.destinations.GalleryDetailScreenDestination
|
||||
@@ -223,9 +224,35 @@ class MainActivity : EhActivity() {
|
||||
callback()
|
||||
}
|
||||
|
||||
suspend fun DialogState.checkDownloadLocation() {
|
||||
val valid = withIOContext { downloadLocation.ensureDir() }
|
||||
if (!valid) {
|
||||
awaitPermissionOrCancel(
|
||||
confirmText = R.string.open_settings,
|
||||
title = R.string.waring,
|
||||
showCancelButton = false,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.invalid_download_location),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
)
|
||||
}
|
||||
navController.navigate(DownloadScreenDestination)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
launch { dialogState.checkDownloadLocation() }.join()
|
||||
launch { dialogState.checkAppLinkVerify() }
|
||||
runCatching { dialogState.checkDownloadLocation() }
|
||||
runCatching { dialogState.checkAppLinkVerify() }
|
||||
runSuspendCatching {
|
||||
withIOContext {
|
||||
AppUpdater.checkForUpdate()?.let {
|
||||
dialogState.showNewVersion(this@MainActivity, it)
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
showTip(getString(R.string.update_failed, ExceptionUtils.getReadableString(it)))
|
||||
}
|
||||
}
|
||||
|
||||
val cannotParse = stringResource(R.string.error_cannot_parse_the_url)
|
||||
@@ -267,17 +294,6 @@ class MainActivity : EhActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
runSuspendCatching {
|
||||
withIOContext {
|
||||
AppUpdater.checkForUpdate()?.let {
|
||||
dialogState.showNewVersion(this@MainActivity, it)
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
showTip(getString(R.string.update_failed, ExceptionUtils.getReadableString(it)))
|
||||
}
|
||||
}
|
||||
val snackbarState = remember { SnackbarHostState() }
|
||||
LaunchedEffect(Unit) {
|
||||
tipFlow.collectLatest {
|
||||
@@ -477,22 +493,6 @@ class MainActivity : EhActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun DialogState.checkDownloadLocation() {
|
||||
val valid = withIOContext { downloadLocation.ensureDir() }
|
||||
if (!valid) {
|
||||
awaitPermissionOrCancel(
|
||||
confirmText = R.string.get_it,
|
||||
title = R.string.waring,
|
||||
showCancelButton = false,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.invalid_download_location),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showTip(@StringRes id: Int, useToast: Boolean = false) {
|
||||
showTip(getString(id), useToast)
|
||||
}
|
||||
|
||||
@@ -42,12 +42,11 @@ import com.hippo.ehviewer.spider.SpiderQueen.Companion.SPIDER_INFO_FILENAME
|
||||
import com.hippo.ehviewer.spider.readComicInfo
|
||||
import com.hippo.ehviewer.spider.readCompatFromUniFile
|
||||
import com.hippo.ehviewer.ui.keepNoMediaFileStatus
|
||||
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
|
||||
import com.hippo.ehviewer.ui.tools.observed
|
||||
import com.hippo.ehviewer.ui.tools.rememberedAccessor
|
||||
import com.hippo.ehviewer.util.AppConfig
|
||||
import com.hippo.unifile.UniFile
|
||||
import com.hippo.unifile.asUniFile
|
||||
import com.hippo.unifile.toPathOrNull
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
import eu.kanade.tachiyomi.util.lang.launchNonCancellable
|
||||
@@ -88,7 +87,7 @@ fun DownloadScreen(navigator: DestinationsNavigator) {
|
||||
contentResolver.takePersistableUriPermission(treeUri, FLAG_GRANT_READ_URI_PERMISSION or FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
downloadLocationState = treeUri.asUniFile()
|
||||
coroutineScope.launchNonCancellable {
|
||||
keepNoMediaFileStatus()
|
||||
keepNoMediaFileStatus(downloadLocationState)
|
||||
}
|
||||
}.onFailure {
|
||||
launchSnackBar(cannotGetDownloadLocation)
|
||||
@@ -98,27 +97,9 @@ fun DownloadScreen(navigator: DestinationsNavigator) {
|
||||
}
|
||||
Preference(
|
||||
title = stringResource(id = R.string.settings_download_download_location),
|
||||
summary = downloadLocationState.uri.toString(),
|
||||
summary = downloadLocationState.uri.run { toPathOrNull() ?: toString() },
|
||||
) {
|
||||
val file = downloadLocationState
|
||||
if (!UniFile.isFileUri(downloadLocationState.uri)) {
|
||||
BaseDialogBuilder(context)
|
||||
.setTitle(R.string.settings_download_download_location)
|
||||
.setMessage(file.uri.toString())
|
||||
.setPositiveButton(R.string.pick_new_download_location) { _, _ -> selectDownloadDirLauncher.launch(null) }
|
||||
.setNeutralButton(R.string.reset_download_location) { _, _ ->
|
||||
val uniFile = AppConfig.defaultDownloadDir?.asUniFile()
|
||||
if (uniFile != null) {
|
||||
downloadLocationState = uniFile
|
||||
coroutineScope.launchNonCancellable { keepNoMediaFileStatus() }
|
||||
} else {
|
||||
launchSnackBar(cannotGetDownloadLocation)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
selectDownloadDirLauncher.launch(null)
|
||||
}
|
||||
selectDownloadDirLauncher.launch(null)
|
||||
}
|
||||
val mediaScan = Settings::mediaScan.observed
|
||||
SwitchPreference(
|
||||
|
||||
@@ -37,10 +37,11 @@ object AppConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getDirInExternalAppDir(filename: String) = externalAppDir?.run { File(this, filename).takeIf { it.ensureDirectory() } }
|
||||
private fun getDirInExternalAppDir(filename: String, create: Boolean = true) =
|
||||
externalAppDir?.run { File(this, filename).takeIf { if (create) it.ensureDirectory() else it.isDirectory } }
|
||||
|
||||
val defaultDownloadDir: File?
|
||||
get() = getDirInExternalAppDir(DOWNLOAD)
|
||||
get() = getDirInExternalAppDir(DOWNLOAD, false)
|
||||
|
||||
val externalTempDir: File?
|
||||
get() = appCtx.externalCacheDir?.run { File(this, TEMP).takeIf { it.ensureDirectory() } }
|
||||
|
||||
@@ -235,11 +235,11 @@ abstract class UniFile internal constructor(private val parent: UniFile?) {
|
||||
companion object {
|
||||
fun fromFile(file: File) = RawFile(null, file)
|
||||
|
||||
fun fromSingleUri(singleUri: Uri) = SingleDocumentFile(null, singleUri)
|
||||
private fun fromSingleUri(singleUri: Uri) = SingleDocumentFile(null, singleUri)
|
||||
|
||||
fun fromTreeUri(treeUri: Uri) = TreeDocumentFile(null, DocumentsContractApi21.prepareTreeUri(treeUri))
|
||||
private fun fromTreeUri(treeUri: Uri) = TreeDocumentFile(null, DocumentsContractApi21.prepareTreeUri(treeUri))
|
||||
|
||||
fun fromMediaUri(mediaUri: Uri) = MediaFile(mediaUri)
|
||||
private fun fromMediaUri(mediaUri: Uri) = MediaFile(mediaUri)
|
||||
|
||||
fun fromUri(uri: Uri) = when {
|
||||
isFileUri(uri) -> fromFile(uri.toFile())
|
||||
@@ -256,5 +256,7 @@ abstract class UniFile internal constructor(private val parent: UniFile?) {
|
||||
fun isTreeUri(uri: Uri) = DocumentsContractCompat.isTreeUri(uri)
|
||||
|
||||
fun isMediaUri(uri: Uri) = null != MediaContract.getName(uri)
|
||||
|
||||
val Stub = fromFile(File(""))
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.hippo.unifile
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.os.ParcelFileDescriptor.AutoCloseInputStream
|
||||
import android.os.ParcelFileDescriptor.AutoCloseOutputStream
|
||||
import android.provider.DocumentsContract
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
@@ -29,3 +31,18 @@ fun Path.asUniFile() = toFile().asUniFile()
|
||||
fun Uri.asUniFileOrNull() = UniFile.fromUri(this)
|
||||
|
||||
fun Uri.asUniFile() = requireNotNull(asUniFileOrNull())
|
||||
|
||||
fun Uri.toPathOrNull(): String? {
|
||||
if (UniFile.isFileUri(this)) {
|
||||
return path
|
||||
}
|
||||
if (UniFile.isDocumentUri(this)) {
|
||||
if (authority == "com.android.externalstorage.documents") {
|
||||
val (type, id) = DocumentsContract.getDocumentId(this).split(":", limit = 2)
|
||||
if (type == "primary") {
|
||||
return Environment.getExternalStorageDirectory().absolutePath + "/" + id
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -145,7 +145,6 @@
|
||||
<string name="toplist_pastyear">Forrige år</string>
|
||||
<string name="toplist_yesterday">I går</string>
|
||||
<string name="action_add_tag">Legg til etikett</string>
|
||||
<string name="reset_download_location">Tilbakestill til forvalg</string>
|
||||
<string name="dont_show_again">Ikke vis igjen</string>
|
||||
<string name="comment_user_uploader">%s (opplaster)</string>
|
||||
<string name="copy_trans">Kopier oversettelse</string>
|
||||
|
||||
@@ -480,8 +480,6 @@
|
||||
<string name="settings_eh_request_news">定时请求新闻页面</string>
|
||||
<string name="settings_eh_hide_hv_events">隐藏 HV 事件通知</string>
|
||||
<string name="copy_trans">复制翻译</string>
|
||||
<string name="reset_download_location">恢复默认路径</string>
|
||||
<string name="pick_new_download_location">选择新路径</string>
|
||||
<string name="dont_show_again">不再显示</string>
|
||||
<string name="open_settings">打开设置</string>
|
||||
<string name="app_link_not_verified_message">对于 Android 12 及更新的版本,您需要手动添加链接到已验证链接才能在 EhViewer 中打开 E-Hentai 链接。</string>
|
||||
|
||||
@@ -475,8 +475,6 @@
|
||||
<string name="settings_eh_request_news">啟動時請求新聞頁面</string>
|
||||
<string name="settings_eh_hide_hv_events">隱藏 HV 事件通知</string>
|
||||
<string name="copy_trans">複製翻譯</string>
|
||||
<string name="reset_download_location">恢復預設路徑</string>
|
||||
<string name="pick_new_download_location">選擇新路徑</string>
|
||||
<string name="dont_show_again">不再顯示</string>
|
||||
<string name="open_settings">打開設定</string>
|
||||
<string name="app_link_not_verified_message">對於 Android 12 及更新的版本,您需要手動增加連結到已驗證連結才能在 EhViewer 中打開 E-Hentai 連結。</string>
|
||||
|
||||
@@ -542,8 +542,6 @@
|
||||
<string name="settings_eh_request_news">Timed request news page</string>
|
||||
<string name="settings_eh_hide_hv_events">Hide HV event Notifications</string>
|
||||
<string name="copy_trans">Copy translation</string>
|
||||
<string name="reset_download_location">Reset to default</string>
|
||||
<string name="pick_new_download_location">Pick a new location</string>
|
||||
<string name="dont_show_again">Don\'t show again</string>
|
||||
<string name="open_settings">Open settings</string>
|
||||
<string name="app_link_not_verified_message">For Android 12 and newer, you need to manually add link to verified links in order to open E-Hentai links in EhViewer.</string>
|
||||
|
||||
Reference in new issue
Block a user