feat: changing the downloads dir

This commit is contained in:
rebelonion
2024-04-04 02:21:43 -05:00
parent 79113cb04a
commit 33ed647832
8 changed files with 133 additions and 53 deletions

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)),

View File

@@ -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)

View File

@@ -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>

View File

@@ -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>