Remove old and slow simplePath from SAF, also autoformatted

This commit is contained in:
Nicholas Wallace
2026-07-20 18:59:19 -07:00
parent b3c3950c55
commit dc6184f41d
6 changed files with 247 additions and 205 deletions
@@ -11,53 +11,66 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo
import java.io.File import java.io.File
enum class LockOrientationSetting { enum class LockOrientationSetting {
NONE, PORTRAIT, LANDSCAPE NONE,
PORTRAIT,
LANDSCAPE
} }
enum class HapticFeedbackSetting { enum class HapticFeedbackSetting {
OFF, LIGHT, MEDIUM, HEAVY OFF,
LIGHT,
MEDIUM,
HEAVY
} }
enum class ShakeSensitivitySetting { enum class ShakeSensitivitySetting {
VERY_LOW, LOW, MEDIUM, HIGH, VERY_HIGH VERY_LOW,
LOW,
MEDIUM,
HIGH,
VERY_HIGH
} }
enum class DownloadUsingCellularSetting { enum class DownloadUsingCellularSetting {
ASK, ALWAYS, NEVER ASK,
ALWAYS,
NEVER
} }
enum class StreamingUsingCellularSetting { enum class StreamingUsingCellularSetting {
ASK, ALWAYS, NEVER ASK,
ALWAYS,
NEVER
} }
enum class AndroidAutoBrowseSeriesSequenceOrderSetting { enum class AndroidAutoBrowseSeriesSequenceOrderSetting {
ASC, DESC ASC,
DESC
} }
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
data class ServerConnectionConfig( data class ServerConnectionConfig(
var id:String, var id: String,
var index:Int, var index: Int,
var name:String, var name: String,
var address:String, var address: String,
// version added after 0.9.81-beta // version added after 0.9.81-beta
var version:String?, var version: String?,
var userId:String, var userId: String,
var username:String, var username: String,
var token:String, var token: String,
var customHeaders:Map<String, String>? var customHeaders: Map<String, String>?
) )
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
data class LocalFile( data class LocalFile(
var id:String, var id: String,
var filename:String?, var filename: String?,
var contentUrl:String, var contentUrl: String,
var basePath:String, var basePath: String,
var absolutePath:String, var absolutePath: String,
var simplePath:String, var mimeType: String?,
var mimeType:String?, var size: Long
var size:Long
) { ) {
@JsonIgnore @JsonIgnore
fun exists(ctx: Context): Boolean { fun exists(ctx: Context): Boolean {
@@ -73,17 +86,17 @@ data class LocalFile(
} }
@JsonIgnore @JsonIgnore
fun isAudioFile():Boolean { fun isAudioFile(): Boolean {
if (mimeType == "application/octet-stream") return true if (mimeType == "application/octet-stream") return true
if (mimeType == "video/mp4") return true if (mimeType == "video/mp4") return true
return mimeType?.startsWith("audio") == true return mimeType?.startsWith("audio") == true
} }
@JsonIgnore @JsonIgnore
fun isEBookFile():Boolean { fun isEBookFile(): Boolean {
return getEBookFormat() != null return getEBookFormat() != null
} }
@JsonIgnore @JsonIgnore
fun getEBookFormat():String? { fun getEBookFormat(): String? {
if (mimeType == "application/epub+zip") return "epub" if (mimeType == "application/epub+zip") return "epub"
if (mimeType == "application/pdf") return "pdf" if (mimeType == "application/pdf") return "pdf"
if (mimeType == "application/x-mobipocket-ebook") return "mobi" if (mimeType == "application/x-mobipocket-ebook") return "mobi"
@@ -96,118 +109,124 @@ data class LocalFile(
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
data class LocalFolder( data class LocalFolder(
var id:String, var id: String,
var name:String, var name: String,
var contentUrl:String, var contentUrl: String,
var basePath:String, var basePath: String,
var absolutePath:String, var absolutePath: String,
var simplePath:String, var storageType: String,
var storageType:String, var mediaType: String
var mediaType:String
) )
@JsonTypeInfo(use= JsonTypeInfo.Id.DEDUCTION) @JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
@JsonSubTypes( @JsonSubTypes(JsonSubTypes.Type(LibraryItem::class), JsonSubTypes.Type(LocalLibraryItem::class))
JsonSubTypes.Type(LibraryItem::class), open class LibraryItemWrapper(var id: String) {
JsonSubTypes.Type(LocalLibraryItem::class)
)
open class LibraryItemWrapper(var id:String) {
@JsonIgnore @JsonIgnore
open fun getMediaDescription(progress:MediaProgressWrapper?, ctx: Context): MediaDescriptionCompat { return MediaDescriptionCompat.Builder().build() } open fun getMediaDescription(
progress: MediaProgressWrapper?,
ctx: Context
): MediaDescriptionCompat {
return MediaDescriptionCompat.Builder().build()
}
} }
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
data class DeviceInfo( data class DeviceInfo(
var deviceId:String, var deviceId: String,
var manufacturer:String, var manufacturer: String,
var model:String, var model: String,
var sdkVersion:Int, var sdkVersion: Int,
var clientVersion: String var clientVersion: String
) )
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
data class PlayItemRequestPayload( data class PlayItemRequestPayload(
var mediaPlayer:String, var mediaPlayer: String,
var forceDirectPlay:Boolean, var forceDirectPlay: Boolean,
var forceTranscode:Boolean, var forceTranscode: Boolean,
var deviceInfo:DeviceInfo var deviceInfo: DeviceInfo
) )
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
data class DeviceSettings( data class DeviceSettings(
var disableAutoRewind:Boolean, var disableAutoRewind: Boolean,
var enableAltView:Boolean, var enableAltView: Boolean,
var allowSeekingOnMediaControls:Boolean, var allowSeekingOnMediaControls: Boolean,
var jumpBackwardsTime:Int, var jumpBackwardsTime: Int,
var jumpForwardTime:Int, var jumpForwardTime: Int,
var enableMp3IndexSeeking:Boolean, var enableMp3IndexSeeking: Boolean,
var disableShakeToResetSleepTimer:Boolean, var disableShakeToResetSleepTimer: Boolean,
var shakeSensitivity: ShakeSensitivitySetting, var shakeSensitivity: ShakeSensitivitySetting,
var lockOrientation: LockOrientationSetting, var lockOrientation: LockOrientationSetting,
var hapticFeedback: HapticFeedbackSetting, var hapticFeedback: HapticFeedbackSetting,
var autoSleepTimer: Boolean, var autoSleepTimer: Boolean,
var autoSleepTimerStartTime: String, var autoSleepTimerStartTime: String,
var autoSleepTimerEndTime: String, var autoSleepTimerEndTime: String,
var autoSleepTimerAutoRewind: Boolean, var autoSleepTimerAutoRewind: Boolean,
var autoSleepTimerAutoRewindTime: Long, //Time in milliseconds var autoSleepTimerAutoRewindTime: Long, // Time in milliseconds
var sleepTimerLength: Long, // Time in milliseconds var sleepTimerLength: Long, // Time in milliseconds
var disableSleepTimerFadeOut: Boolean, var disableSleepTimerFadeOut: Boolean,
var disableSleepTimerResetFeedback: Boolean, var disableSleepTimerResetFeedback: Boolean,
var enableSleepTimerAlmostDoneChime: Boolean, var enableSleepTimerAlmostDoneChime: Boolean,
var languageCode: String, var languageCode: String,
var downloadUsingCellular: DownloadUsingCellularSetting, var downloadUsingCellular: DownloadUsingCellularSetting,
var streamingUsingCellular: StreamingUsingCellularSetting, var streamingUsingCellular: StreamingUsingCellularSetting,
var androidAutoBrowseLimitForGrouping: Int, var androidAutoBrowseLimitForGrouping: Int,
var androidAutoBrowseSeriesSequenceOrder: AndroidAutoBrowseSeriesSequenceOrderSetting var androidAutoBrowseSeriesSequenceOrder: AndroidAutoBrowseSeriesSequenceOrderSetting
) { ) {
companion object { companion object {
// Static method to get default device settings // Static method to get default device settings
fun default():DeviceSettings { fun default(): DeviceSettings {
return DeviceSettings( return DeviceSettings(
disableAutoRewind = false, disableAutoRewind = false,
enableAltView = true, enableAltView = true,
allowSeekingOnMediaControls = false, allowSeekingOnMediaControls = false,
jumpBackwardsTime = 10, jumpBackwardsTime = 10,
jumpForwardTime = 10, jumpForwardTime = 10,
enableMp3IndexSeeking = false, enableMp3IndexSeeking = false,
disableShakeToResetSleepTimer = false, disableShakeToResetSleepTimer = false,
shakeSensitivity = ShakeSensitivitySetting.MEDIUM, shakeSensitivity = ShakeSensitivitySetting.MEDIUM,
lockOrientation = LockOrientationSetting.NONE, lockOrientation = LockOrientationSetting.NONE,
hapticFeedback = HapticFeedbackSetting.LIGHT, hapticFeedback = HapticFeedbackSetting.LIGHT,
autoSleepTimer = false, autoSleepTimer = false,
autoSleepTimerStartTime = "22:00", autoSleepTimerStartTime = "22:00",
autoSleepTimerEndTime = "06:00", autoSleepTimerEndTime = "06:00",
sleepTimerLength = 900000L, // 15 minutes sleepTimerLength = 900000L, // 15 minutes
autoSleepTimerAutoRewind = false, autoSleepTimerAutoRewind = false,
autoSleepTimerAutoRewindTime = 300000L, // 5 minutes autoSleepTimerAutoRewindTime = 300000L, // 5 minutes
disableSleepTimerFadeOut = false, disableSleepTimerFadeOut = false,
disableSleepTimerResetFeedback = false, disableSleepTimerResetFeedback = false,
enableSleepTimerAlmostDoneChime = false, enableSleepTimerAlmostDoneChime = false,
languageCode = "en-us", languageCode = "en-us",
downloadUsingCellular = DownloadUsingCellularSetting.ALWAYS, downloadUsingCellular = DownloadUsingCellularSetting.ALWAYS,
streamingUsingCellular = StreamingUsingCellularSetting.ALWAYS, streamingUsingCellular = StreamingUsingCellularSetting.ALWAYS,
androidAutoBrowseLimitForGrouping = 100, androidAutoBrowseLimitForGrouping = 100,
androidAutoBrowseSeriesSequenceOrder = AndroidAutoBrowseSeriesSequenceOrderSetting.ASC androidAutoBrowseSeriesSequenceOrder = AndroidAutoBrowseSeriesSequenceOrderSetting.ASC
) )
} }
} }
@get:JsonIgnore @get:JsonIgnore
val jumpBackwardsTimeMs get() = jumpBackwardsTime * 1000L val jumpBackwardsTimeMs
get() = jumpBackwardsTime * 1000L
@get:JsonIgnore @get:JsonIgnore
val jumpForwardTimeMs get() = jumpForwardTime * 1000L val jumpForwardTimeMs
get() = jumpForwardTime * 1000L
@get:JsonIgnore @get:JsonIgnore
val autoSleepTimerStartHour get() = autoSleepTimerStartTime.split(":")[0].toInt() val autoSleepTimerStartHour
get() = autoSleepTimerStartTime.split(":")[0].toInt()
@get:JsonIgnore @get:JsonIgnore
val autoSleepTimerStartMinute get() = autoSleepTimerStartTime.split(":")[1].toInt() val autoSleepTimerStartMinute
get() = autoSleepTimerStartTime.split(":")[1].toInt()
@get:JsonIgnore @get:JsonIgnore
val autoSleepTimerEndHour get() = autoSleepTimerEndTime.split(":")[0].toInt() val autoSleepTimerEndHour
get() = autoSleepTimerEndTime.split(":")[0].toInt()
@get:JsonIgnore @get:JsonIgnore
val autoSleepTimerEndMinute get() = autoSleepTimerEndTime.split(":")[1].toInt() val autoSleepTimerEndMinute
get() = autoSleepTimerEndTime.split(":")[1].toInt()
@JsonIgnore @JsonIgnore
fun getShakeThresholdGravity() : Float { // Used in ShakeDetector fun getShakeThresholdGravity(): Float { // Used in ShakeDetector
return if (shakeSensitivity == ShakeSensitivitySetting.VERY_HIGH) 1.1f return if (shakeSensitivity == ShakeSensitivitySetting.VERY_HIGH) 1.1f
else if (shakeSensitivity == ShakeSensitivitySetting.HIGH) 1.3f else if (shakeSensitivity == ShakeSensitivitySetting.HIGH) 1.3f
else if (shakeSensitivity == ShakeSensitivitySetting.MEDIUM) 1.5f else if (shakeSensitivity == ShakeSensitivitySetting.MEDIUM) 1.5f
@@ -221,10 +240,10 @@ data class DeviceSettings(
} }
data class DeviceData( data class DeviceData(
var serverConnectionConfigs:MutableList<ServerConnectionConfig>, var serverConnectionConfigs: MutableList<ServerConnectionConfig>,
var lastServerConnectionConfigId:String?, var lastServerConnectionConfigId: String?,
var deviceSettings: DeviceSettings?, var deviceSettings: DeviceSettings?,
var lastPlaybackSession: PlaybackSession? var lastPlaybackSession: PlaybackSession?
) { ) {
@JsonIgnore @JsonIgnore
fun getLastServerConnectionConfig(): ServerConnectionConfig? { fun getLastServerConnectionConfig(): ServerConnectionConfig? {
@@ -100,7 +100,7 @@ class LocalLibraryItem(
@JsonIgnore @JsonIgnore
private fun trackExists(ctx: Context, contentUrl: String?, path: String): Boolean { private fun trackExists(ctx: Context, contentUrl: String?, path: String): Boolean {
return LocalFile("", null, contentUrl ?: "", "", path, "", null, 0).exists(ctx) return LocalFile("", null, contentUrl ?: "", "", path, null, 0).exists(ctx)
} }
@JsonIgnore @JsonIgnore
@@ -14,7 +14,6 @@ data class LocalMediaItem(
var mediaType: String, var mediaType: String,
var folderId: String, var folderId: String,
var contentUrl: String, var contentUrl: String,
var simplePath: String,
var basePath: String, var basePath: String,
var absolutePath: String, var absolutePath: String,
var audioTracks: MutableList<AudioTrack>, var audioTracks: MutableList<AudioTrack>,
@@ -35,7 +35,6 @@ class FolderScanner(private val ctx: Context) {
Uri.fromFile(file).toString(), Uri.fromFile(file).toString(),
file.getBasePath(ctx), file.getBasePath(ctx),
file.absolutePath, file.absolutePath,
file.getSimplePath(ctx),
file.mimeType, file.mimeType,
file.length() file.length()
) )
@@ -61,7 +60,6 @@ class FolderScanner(private val ctx: Context) {
contentUrl, contentUrl,
part.localFolderName, part.localFolderName,
part.finalDestinationPath, part.finalDestinationPath,
part.finalDestinationPath,
mimeTypeFor(part), mimeTypeFor(part),
size size
) )
@@ -81,7 +79,6 @@ class FolderScanner(private val ctx: Context) {
document.uri.toString(), document.uri.toString(),
document.getBasePath(ctx), document.getBasePath(ctx),
document.getAbsolutePath(ctx), document.getAbsolutePath(ctx),
document.getSimplePath(ctx),
document.mimeType, document.mimeType,
document.length() document.length()
) )
@@ -23,40 +23,49 @@ import java.io.File
class AbsFileSystem : Plugin() { class AbsFileSystem : Plugin() {
private val TAG = "AbsFileSystem" private val TAG = "AbsFileSystem"
private val tag = "AbsFileSystem" private val tag = "AbsFileSystem"
private var jacksonMapper = jacksonObjectMapper().enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature()) private var jacksonMapper =
jacksonObjectMapper()
.enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature())
lateinit var mainActivity: MainActivity lateinit var mainActivity: MainActivity
override fun load() { override fun load() {
mainActivity = (activity as MainActivity) mainActivity = (activity as MainActivity)
mainActivity.storage.storageAccessCallback = object : StorageAccessCallback { mainActivity.storage.storageAccessCallback =
override fun onRootPathNotSelected( object : StorageAccessCallback {
requestCode: Int, override fun onRootPathNotSelected(
rootPath: String, requestCode: Int,
uri: Uri, rootPath: String,
selectedStorageType: StorageType, uri: Uri,
expectedStorageType: StorageType selectedStorageType: StorageType,
) { expectedStorageType: StorageType
Log.d(TAG, "STORAGE ACCESS CALLBACK") ) {
} Log.d(TAG, "STORAGE ACCESS CALLBACK")
}
override fun onCanceledByUser(requestCode: Int) { override fun onCanceledByUser(requestCode: Int) {
Log.d(TAG, "STORAGE ACCESS CALLBACK") Log.d(TAG, "STORAGE ACCESS CALLBACK")
} }
override fun onExpectedStorageNotSelected(requestCode: Int, selectedFolder: DocumentFile, selectedStorageType: StorageType, expectedBasePath: String, expectedStorageType: StorageType) { override fun onExpectedStorageNotSelected(
Log.d(TAG, "STORAGE ACCESS CALLBACK") requestCode: Int,
} selectedFolder: DocumentFile,
selectedStorageType: StorageType,
expectedBasePath: String,
expectedStorageType: StorageType
) {
Log.d(TAG, "STORAGE ACCESS CALLBACK")
}
override fun onStoragePermissionDenied(requestCode: Int) { override fun onStoragePermissionDenied(requestCode: Int) {
Log.d(TAG, "STORAGE ACCESS CALLBACK") Log.d(TAG, "STORAGE ACCESS CALLBACK")
} }
override fun onRootPathPermissionGranted(requestCode: Int, root: DocumentFile) { override fun onRootPathPermissionGranted(requestCode: Int, root: DocumentFile) {
Log.d(TAG, "STORAGE ACCESS CALLBACK") Log.d(TAG, "STORAGE ACCESS CALLBACK")
} }
} }
} }
@PluginMethod @PluginMethod
@@ -65,60 +74,77 @@ class AbsFileSystem : Plugin() {
val REQUEST_CODE_SELECT_FOLDER = 6 val REQUEST_CODE_SELECT_FOLDER = 6
val REQUEST_CODE_SDCARD_ACCESS = 7 val REQUEST_CODE_SDCARD_ACCESS = 7
mainActivity.storage.folderPickerCallback = object : FolderPickerCallback { mainActivity.storage.folderPickerCallback =
override fun onFolderSelected(requestCode: Int, folder: DocumentFile) { object : FolderPickerCallback {
Log.d(TAG, "ON FOLDER SELECTED ${folder.uri} ${folder.name}") override fun onFolderSelected(requestCode: Int, folder: DocumentFile) {
val absolutePath = folder.getAbsolutePath(activity) Log.d(TAG, "ON FOLDER SELECTED ${folder.uri} ${folder.name}")
val storageType = folder.getStorageType(activity) val absolutePath = folder.getAbsolutePath(activity)
val simplePath = folder.getSimplePath(activity) val storageType = folder.getStorageType(activity)
val basePath = folder.getBasePath(activity) val basePath = folder.getBasePath(activity)
val folderId = android.util.Base64.encodeToString(folder.id.toByteArray(), android.util.Base64.DEFAULT) val folderId =
android.util.Base64.encodeToString(
folder.id.toByteArray(),
android.util.Base64.DEFAULT
)
val localFolder = LocalFolder(folderId, folder.name ?: "", folder.uri.toString(),basePath,absolutePath, simplePath, storageType.toString(), mediaType) val localFolder =
LocalFolder(
folderId,
folder.name ?: "",
folder.uri.toString(),
basePath,
absolutePath,
storageType.toString(),
mediaType
)
DeviceManager.dbManager.saveLocalFolder(localFolder) DeviceManager.dbManager.saveLocalFolder(localFolder)
call.resolve(JSObject(jacksonMapper.writeValueAsString(localFolder))) call.resolve(JSObject(jacksonMapper.writeValueAsString(localFolder)))
} }
override fun onStorageAccessDenied( override fun onStorageAccessDenied(
requestCode: Int, requestCode: Int,
folder: DocumentFile?, folder: DocumentFile?,
storageType: StorageType, storageType: StorageType,
storageId: String storageId: String
) { ) {
Log.e(tag, "Storage Access Denied ${folder?.getAbsolutePath(mainActivity)}") Log.e(tag, "Storage Access Denied ${folder?.getAbsolutePath(mainActivity)}")
val jsobj = JSObject() val jsobj = JSObject()
if (requestCode == REQUEST_CODE_SELECT_FOLDER) { if (requestCode == REQUEST_CODE_SELECT_FOLDER) {
val builder: AlertDialog.Builder = AlertDialog.Builder(mainActivity) val builder: AlertDialog.Builder = AlertDialog.Builder(mainActivity)
builder.setMessage( builder.setMessage(
"You have no write access to this storage, thus selecting this folder is useless." + "You have no write access to this storage, thus selecting this folder is useless." +
"\nWould you like to grant access to this folder?") "\nWould you like to grant access to this folder?"
builder.setNegativeButton("Dont Allow") { _, _ -> )
run { builder.setNegativeButton("Dont Allow") { _, _ ->
jsobj.put("error", "User Canceled, Access Denied") run {
call.resolve(jsobj) jsobj.put("error", "User Canceled, Access Denied")
call.resolve(jsobj)
}
}
builder.setPositiveButton("Allow.") { _, _ ->
mainActivity.storageHelper.requestStorageAccess(
REQUEST_CODE_SDCARD_ACCESS,
initialPath = FileFullPath(mainActivity, storageId, "")
)
}
builder.show()
} else {
Log.d(TAG, "STORAGE ACCESS DENIED $requestCode")
jsobj.put("error", "Access Denied")
call.resolve(jsobj)
}
}
override fun onStoragePermissionDenied(requestCode: Int) {
Log.d(TAG, "STORAGE PERMISSION DENIED $requestCode")
val jsobj = JSObject()
jsobj.put("error", "Permission Denied")
call.resolve(jsobj)
}
} }
}
builder.setPositiveButton("Allow.") { _, _ -> mainActivity.storageHelper.requestStorageAccess(REQUEST_CODE_SDCARD_ACCESS, initialPath = FileFullPath(mainActivity, storageId, "")) }
builder.show()
} else {
Log.d(TAG, "STORAGE ACCESS DENIED $requestCode")
jsobj.put("error", "Access Denied")
call.resolve(jsobj)
}
}
override fun onStoragePermissionDenied(requestCode: Int) {
Log.d(TAG, "STORAGE PERMISSION DENIED $requestCode")
val jsobj = JSObject()
jsobj.put("error", "Permission Denied")
call.resolve(jsobj)
}
}
mainActivity.storage.openFolderPicker(REQUEST_CODE_SELECT_FOLDER) mainActivity.storage.openFolderPicker(REQUEST_CODE_SELECT_FOLDER)
} }
@@ -152,7 +178,7 @@ class AbsFileSystem : Plugin() {
val folderUrl = call.data.getString("folderUrl", "").toString() val folderUrl = call.data.getString("folderUrl", "").toString()
Log.d(TAG, "Check Folder Permissions for $folderUrl") Log.d(TAG, "Check Folder Permissions for $folderUrl")
val hasAccess = SimpleStorage.hasStorageAccess(context,folderUrl,true) val hasAccess = SimpleStorage.hasStorageAccess(context, folderUrl, true)
val jsobj = JSObject() val jsobj = JSObject()
jsobj.put("value", hasAccess) jsobj.put("value", hasAccess)
@@ -196,26 +222,29 @@ class AbsFileSystem : Plugin() {
if (localLibraryItem?.folderId?.startsWith("internal-") == true) { if (localLibraryItem?.folderId?.startsWith("internal-") == true) {
Log.d(tag, "Deleting internal library item at absolutePath $absolutePath") Log.d(tag, "Deleting internal library item at absolutePath $absolutePath")
val file = File(absolutePath) val file = File(absolutePath)
success = if (file.exists()) { success =
file.deleteRecursively() if (file.exists()) {
} else { file.deleteRecursively()
true } else {
} true
}
} else { } else {
var subfolderPathToDelete = "" var subfolderPathToDelete = ""
localLibraryItem?.folderId?.let { folderId -> localLibraryItem?.folderId?.let { folderId ->
val folder = DeviceManager.dbManager.getLocalFolder(folderId) val folder = DeviceManager.dbManager.getLocalFolder(folderId)
folder?.absolutePath?.let { folderPath -> folder?.absolutePath?.let { folderPath ->
val splitAbsolutePath = absolutePath.split("/") val splitAbsolutePath = absolutePath.split("/")
val fullSubDir = splitAbsolutePath.subList(0, splitAbsolutePath.size - 1).joinToString("/") val fullSubDir =
splitAbsolutePath.subList(0, splitAbsolutePath.size - 1).joinToString("/")
if (fullSubDir != folderPath) { if (fullSubDir != folderPath) {
val subdirHasAnItem = DeviceManager.dbManager.getLocalLibraryItems().any { _localLibraryItem -> val subdirHasAnItem =
if (_localLibraryItem.id == localLibraryItemId) { DeviceManager.dbManager.getLocalLibraryItems().any { _localLibraryItem ->
false if (_localLibraryItem.id == localLibraryItemId) {
} else { false
_localLibraryItem.absolutePath.startsWith(fullSubDir) } else {
} _localLibraryItem.absolutePath.startsWith(fullSubDir)
} }
}
subfolderPathToDelete = if (subdirHasAnItem) "" else fullSubDir subfolderPathToDelete = if (subdirHasAnItem) "" else fullSubDir
} }
} }
-2
View File
@@ -119,7 +119,6 @@ class AbsDatabaseWeb extends WebPlugin {
name: 'Audiobooks', name: 'Audiobooks',
contentUrl: 'test', contentUrl: 'test',
absolutePath: '/audiobooks', absolutePath: '/audiobooks',
simplePath: 'audiobooks',
storageType: 'primary', storageType: 'primary',
mediaType: 'book' mediaType: 'book'
} }
@@ -196,7 +195,6 @@ class AbsDatabaseWeb extends WebPlugin {
filename: 'lf1.mp3', filename: 'lf1.mp3',
contentUrl: 'test', contentUrl: 'test',
absolutePath: 'test', absolutePath: 'test',
simplePath: 'test',
mimeType: 'audio/mpeg', mimeType: 'audio/mpeg',
size: 39048290 size: 39048290
} }