mirror of
https://github.com/rebelonion/Dantotsu.git
synced 2026-01-11 18:06:16 +00:00
feat: changing the downloads dir
This commit is contained in:
@@ -8,8 +8,12 @@ import ani.dantotsu.media.MediaType
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.anggrayudi.storage.callback.FolderCallback
|
||||
import com.anggrayudi.storage.file.deleteRecursively
|
||||
import com.anggrayudi.storage.file.findFolder
|
||||
import com.anggrayudi.storage.file.moveFileTo
|
||||
import com.anggrayudi.storage.file.moveFolderTo
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -123,6 +127,52 @@ class DownloadsManager(private val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
fun moveDownloadsDir(context: Context, oldUri: Uri, newUri: Uri, finished: (Boolean, String) -> Unit) {
|
||||
try {
|
||||
if (oldUri == newUri) {
|
||||
finished(false, "Source and destination are the same")
|
||||
return
|
||||
}
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
|
||||
val oldBase =
|
||||
DocumentFile.fromTreeUri(context, oldUri) ?: throw Exception("Old base is null")
|
||||
val newBase =
|
||||
DocumentFile.fromTreeUri(context, newUri) ?: throw Exception("New base is null")
|
||||
val folder =
|
||||
oldBase.findFolder(BASE_LOCATION) ?: throw Exception("Base folder not found")
|
||||
folder.moveFolderTo(context, newBase, false, BASE_LOCATION, object:
|
||||
FolderCallback() {
|
||||
override fun onFailed(errorCode: ErrorCode) {
|
||||
when (errorCode) {
|
||||
ErrorCode.CANCELED -> finished(false, "Move canceled")
|
||||
ErrorCode.CANNOT_CREATE_FILE_IN_TARGET -> finished(false, "Cannot create file in target")
|
||||
ErrorCode.INVALID_TARGET_FOLDER -> finished(true, "Invalid target folder") // seems to still work
|
||||
ErrorCode.NO_SPACE_LEFT_ON_TARGET_PATH -> finished(false, "No space left on target path")
|
||||
ErrorCode.UNKNOWN_IO_ERROR -> finished(false, "Unknown IO error")
|
||||
ErrorCode.SOURCE_FOLDER_NOT_FOUND -> finished(false, "Source folder not found")
|
||||
ErrorCode.STORAGE_PERMISSION_DENIED -> finished(false, "Storage permission denied")
|
||||
ErrorCode.TARGET_FOLDER_CANNOT_HAVE_SAME_PATH_WITH_SOURCE_FOLDER -> finished(false, "Target folder cannot have same path with source folder")
|
||||
else -> finished(false, "Failed to move downloads: $errorCode")
|
||||
}
|
||||
Logger.log("Failed to move downloads: $errorCode")
|
||||
super.onFailed(errorCode)
|
||||
}
|
||||
|
||||
override fun onCompleted(result: Result) {
|
||||
finished(true, "Successfully moved downloads")
|
||||
super.onCompleted(result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
snackString("Error: ${e.message}")
|
||||
finished(false, "Failed to move downloads: ${e.message}")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fun queryDownload(downloadedType: DownloadedType): Boolean {
|
||||
return downloadsList.contains(downloadedType)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.util.TypedValue
|
||||
@@ -14,7 +13,6 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.widget.ImageView
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
@@ -56,9 +54,7 @@ import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.LauncherWrapper
|
||||
import ani.dantotsu.util.StoragePermissions
|
||||
import com.flaviofaria.kenburnsview.RandomTransitionGenerator
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
@@ -36,16 +36,8 @@ object Download {
|
||||
}
|
||||
|
||||
private fun getDownloadDir(context: Context): File {
|
||||
val direct: File
|
||||
if (PrefManager.getVal(PrefName.SdDl)) {
|
||||
val arrayOfFiles = ContextCompat.getExternalFilesDirs(context, null)
|
||||
val parentDirectory = arrayOfFiles[1].toString()
|
||||
direct = File(parentDirectory)
|
||||
if (!direct.exists()) direct.mkdirs()
|
||||
} else {
|
||||
direct = File("storage/emulated/0/${Environment.DIRECTORY_DOWNLOADS}/Dantotsu/")
|
||||
if (!direct.exists()) direct.mkdirs()
|
||||
}
|
||||
val direct = File("storage/emulated/0/${Environment.DIRECTORY_DOWNLOADS}/Dantotsu/")
|
||||
if (!direct.exists()) direct.mkdirs()
|
||||
return direct
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Build.BRAND
|
||||
import android.os.Build.DEVICE
|
||||
@@ -79,7 +80,9 @@ import ani.dantotsu.startMainActivity
|
||||
import ani.dantotsu.statusBarHeight
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
import ani.dantotsu.toast
|
||||
import ani.dantotsu.util.LauncherWrapper
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.accessAlertDialog
|
||||
import ani.dantotsu.util.StoragePermissions.Companion.downloadsPermission
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
@@ -89,7 +92,9 @@ import eltos.simpledialogfragment.color.SimpleColorDialog
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import io.noties.markwon.Markwon
|
||||
import io.noties.markwon.SoftBreakAddsNewLinePlugin
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@@ -102,6 +107,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
override fun handleOnBackPressed() = startMainActivity(this@SettingsActivity)
|
||||
}
|
||||
lateinit var binding: ActivitySettingsBinding
|
||||
lateinit var launcher: LauncherWrapper
|
||||
private lateinit var bindingAccounts: ActivitySettingsAccountsBinding
|
||||
private lateinit var bindingTheme: ActivitySettingsThemeBinding
|
||||
private lateinit var bindingExtensions: ActivitySettingsExtensionsBinding
|
||||
@@ -113,6 +119,7 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
private val extensionInstaller = Injekt.get<BasePreferences>().extensionInstaller()
|
||||
private var cursedCounter = 0
|
||||
|
||||
@kotlin.OptIn(DelicateCoroutinesApi::class)
|
||||
@OptIn(UnstableApi::class)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -164,6 +171,8 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
}
|
||||
}
|
||||
}
|
||||
val contract = ActivityResultContracts.OpenDocumentTree()
|
||||
launcher = LauncherWrapper(this, contract)
|
||||
|
||||
binding.settingsVersion.text = getString(R.string.version_current, BuildConfig.VERSION_NAME)
|
||||
binding.settingsVersion.setOnLongClickListener {
|
||||
@@ -699,20 +708,6 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
restartApp(binding.root)
|
||||
}
|
||||
|
||||
settingsDownloadInSd.isChecked = PrefManager.getVal(PrefName.SdDl)
|
||||
settingsDownloadInSd.setOnCheckedChangeListener { _, isChecked ->
|
||||
if (isChecked) {
|
||||
val arrayOfFiles = ContextCompat.getExternalFilesDirs(this@SettingsActivity, null)
|
||||
if (arrayOfFiles.size > 1 && arrayOfFiles[1] != null) {
|
||||
PrefManager.setVal(PrefName.SdDl, true)
|
||||
} else {
|
||||
settingsDownloadInSd.isChecked = false
|
||||
PrefManager.setVal(PrefName.SdDl, true)
|
||||
snackString(getString(R.string.noSdFound))
|
||||
}
|
||||
} else PrefManager.setVal(PrefName.SdDl, true)
|
||||
}
|
||||
|
||||
settingsContinueMedia.isChecked = PrefManager.getVal(PrefName.ContinueMedia)
|
||||
settingsContinueMedia.setOnCheckedChangeListener { _, isChecked ->
|
||||
PrefManager.setVal(PrefName.ContinueMedia, isChecked)
|
||||
@@ -732,6 +727,44 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||
PrefManager.setVal(PrefName.AdultOnly, isChecked)
|
||||
restartApp(binding.root)
|
||||
}
|
||||
|
||||
settingsDownloadLocation.setOnClickListener {
|
||||
val dialog = AlertDialog.Builder(this@SettingsActivity, R.style.MyPopup)
|
||||
.setTitle(R.string.change_download_location)
|
||||
.setMessage(R.string.download_location_msg)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ ->
|
||||
val oldUri = PrefManager.getVal<String>(PrefName.DownloadsDir)
|
||||
launcher.registerForCallback { success ->
|
||||
if (success) {
|
||||
toast(getString(R.string.please_wait))
|
||||
val newUri = PrefManager.getVal<String>(PrefName.DownloadsDir)
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
Injekt.get<DownloadsManager>().moveDownloadsDir(
|
||||
this@SettingsActivity,
|
||||
Uri.parse(oldUri), Uri.parse(newUri)
|
||||
) { finished, message ->
|
||||
if (finished) {
|
||||
toast(getString(R.string.success))
|
||||
} else {
|
||||
toast(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toast(getString(R.string.error))
|
||||
}
|
||||
}
|
||||
launcher.launch()
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.cancel) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
var previousStart: View = when (PrefManager.getVal<Int>(PrefName.DefaultStartUpTab)) {
|
||||
0 -> uiSettingsAnime
|
||||
1 -> uiSettingsHome
|
||||
|
||||
@@ -13,7 +13,6 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
|
||||
OfflineView(Pref(Location.General, Int::class, 0)),
|
||||
DownloadManager(Pref(Location.General, Int::class, 0)),
|
||||
NSFWExtension(Pref(Location.General, Boolean::class, true)),
|
||||
SdDl(Pref(Location.General, Boolean::class, false)),
|
||||
ContinueMedia(Pref(Location.General, Boolean::class, true)),
|
||||
SearchSources(Pref(Location.General, Boolean::class, true)),
|
||||
RecentlyListOnly(Pref(Location.General, Boolean::class, false)),
|
||||
|
||||
@@ -62,8 +62,11 @@ class StoragePermissions {
|
||||
}
|
||||
|
||||
fun AppCompatActivity.accessAlertDialog(launcher: LauncherWrapper,
|
||||
complete: (Boolean) -> Unit) {
|
||||
if (PrefManager.getVal<String>(PrefName.DownloadsDir).isNotEmpty()) {
|
||||
force: Boolean = false,
|
||||
complete: (Boolean) -> Unit
|
||||
) {
|
||||
if ((PrefManager.getVal<String>(PrefName.DownloadsDir).isNotEmpty() || hasDirAccess(this)) && !force) {
|
||||
complete(true)
|
||||
return
|
||||
}
|
||||
val builder = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
|
||||
@@ -191,27 +191,6 @@
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<!--TODO: Add support for SD card-->
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/settingsDownloadInSd"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="false"
|
||||
android:drawableStart="@drawable/ic_round_sd_card_24"
|
||||
android:drawablePadding="16dp"
|
||||
android:elegantTextHeight="true"
|
||||
android:enabled="false"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:minHeight="64dp"
|
||||
android:text="@string/downloadInSd"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
android:visibility="gone"
|
||||
app:cornerRadius="0dp"
|
||||
app:drawableTint="?attr/colorPrimary"
|
||||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -317,5 +296,29 @@
|
||||
app:drawableTint="?attr/colorPrimary"
|
||||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/settingsDownloadLocation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginStart="-31dp"
|
||||
android:layout_marginEnd="-31dp"
|
||||
android:background="@drawable/ui_bg"
|
||||
android:backgroundTint="?attr/colorSecondary"
|
||||
android:backgroundTintMode="src_atop"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:paddingStart="31dp"
|
||||
android:paddingEnd="31dp"
|
||||
android:text="@string/change_download_location"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/ic_round_source_24"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
</ani.dantotsu.others.Xpandable>
|
||||
</merge>
|
||||
@@ -747,7 +747,9 @@
|
||||
<string name="follows_you">Follows you</string>
|
||||
<string name="mutual">Mutual</string>
|
||||
<string name="success">Success</string>
|
||||
|
||||
<string name="error">Some error occurred</string>
|
||||
<string name="error_msg">Error: %1$s</string>
|
||||
<string name="please_wait">Please wait</string>
|
||||
<string name="upcoming">Upcoming</string>
|
||||
<string name="no_shows_to_display">No shows to display</string>
|
||||
<string name="extension_name">Extension Name</string>
|
||||
@@ -868,4 +870,6 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
||||
<string name="dir_error">Your path could not be set</string>
|
||||
<string name="dir_access">Downloads access</string>
|
||||
<string name="dir_access_msg">Please choose a directory to save your downloads</string>
|
||||
<string name="change_download_location">Change Download Location</string>
|
||||
<string name="download_location_msg">Are you sure you want to change the download location?\nOld downloads may no longer be accessible.</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user