various edge case fixes
This commit is contained in:
parent
d8fca48ef8
commit
a074ff5dd6
8 changed files with 51 additions and 16 deletions
|
@ -33,7 +33,10 @@ import io.flutter.plugin.common.MethodCall
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||||
import io.flutter.util.PathUtils
|
import io.flutter.util.PathUtils
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.beyka.tiffbitmapfactory.TiffBitmapFactory
|
import org.beyka.tiffbitmapfactory.TiffBitmapFactory
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
|
@ -84,7 +87,7 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||||
}
|
}
|
||||||
}.mapValues { it.value?.path }.toMutableMap()
|
}.mapValues { it.value?.path }.toMutableMap()
|
||||||
dirs["externalCacheDirs"] = context.externalCacheDirs.joinToString { it.path }
|
dirs["externalCacheDirs"] = context.externalCacheDirs.joinToString { it.path }
|
||||||
dirs["externalFilesDirs"] = context.getExternalFilesDirs(null).joinToString { it.path }
|
dirs["externalFilesDirs"] = context.getExternalFilesDirs(null).joinToString { it?.path ?: "null" }
|
||||||
|
|
||||||
// used by flutter plugin `path_provider`
|
// used by flutter plugin `path_provider`
|
||||||
dirs.putAll(
|
dirs.putAll(
|
||||||
|
|
|
@ -13,6 +13,7 @@ import deckers.thibault.aves.PendingStorageAccessResultHandler
|
||||||
import deckers.thibault.aves.utils.LogUtils
|
import deckers.thibault.aves.utils.LogUtils
|
||||||
import deckers.thibault.aves.utils.MimeTypes
|
import deckers.thibault.aves.utils.MimeTypes
|
||||||
import deckers.thibault.aves.utils.PermissionManager
|
import deckers.thibault.aves.utils.PermissionManager
|
||||||
|
import deckers.thibault.aves.utils.StorageUtils
|
||||||
import io.flutter.plugin.common.EventChannel
|
import io.flutter.plugin.common.EventChannel
|
||||||
import io.flutter.plugin.common.EventChannel.EventSink
|
import io.flutter.plugin.common.EventChannel.EventSink
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
@ -80,6 +81,11 @@ class StorageAccessStreamHandler(private val activity: Activity, arguments: Any?
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uris.any { !StorageUtils.isMediaStoreContentUri(it) }) {
|
||||||
|
error("requestMediaFileAccess-nonmediastore", "request is only valid for Media Store content URIs, uris=$uris", null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||||
error("requestMediaFileAccess-unsupported", "media file bulk access is not allowed before Android R", null)
|
error("requestMediaFileAccess-unsupported", "media file bulk access is not allowed before Android R", null)
|
||||||
return
|
return
|
||||||
|
@ -148,12 +154,17 @@ class StorageAccessStreamHandler(private val activity: Activity, arguments: Any?
|
||||||
|
|
||||||
fun onGranted(uri: Uri) {
|
fun onGranted(uri: Uri) {
|
||||||
ioScope.launch {
|
ioScope.launch {
|
||||||
activity.contentResolver.openInputStream(uri)?.use { input ->
|
try {
|
||||||
val buffer = ByteArray(BUFFER_SIZE)
|
activity.contentResolver.openInputStream(uri)?.use { input ->
|
||||||
var len: Int
|
val buffer = ByteArray(BUFFER_SIZE)
|
||||||
while (input.read(buffer).also { len = it } != -1) {
|
var len: Int
|
||||||
success(buffer.copyOf(len))
|
while (input.read(buffer).also { len = it } != -1) {
|
||||||
|
success(buffer.copyOf(len))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(LOG_TAG, "failed to open input stream for uri=$uri", e)
|
||||||
|
} finally {
|
||||||
endOfStream()
|
endOfStream()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,13 +36,14 @@ object StorageUtils {
|
||||||
const val TRASH_PATH_PLACEHOLDER = "#trash"
|
const val TRASH_PATH_PLACEHOLDER = "#trash"
|
||||||
|
|
||||||
private fun isAppFile(context: Context, path: String): Boolean {
|
private fun isAppFile(context: Context, path: String): Boolean {
|
||||||
return context.getExternalFilesDirs(null).any { filesDir -> path.startsWith(filesDir.path) }
|
val filesDirs = context.getExternalFilesDirs(null).filterNotNull()
|
||||||
|
return filesDirs.any { path.startsWith(it.path) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun appExternalFilesDirFor(context: Context, path: String): File? {
|
private fun appExternalFilesDirFor(context: Context, path: String): File? {
|
||||||
val filesDirs = context.getExternalFilesDirs(null)
|
val filesDirs = context.getExternalFilesDirs(null).filterNotNull()
|
||||||
val volumePath = getVolumePath(context, path)
|
val volumePath = getVolumePath(context, path)
|
||||||
return volumePath?.let { filesDirs.firstOrNull { it.startsWith(volumePath) } } ?: filesDirs.first()
|
return volumePath?.let { filesDirs.firstOrNull { it.startsWith(volumePath) } } ?: filesDirs.firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun trashDirFor(context: Context, path: String): File? {
|
fun trashDirFor(context: Context, path: String): File? {
|
||||||
|
|
|
@ -154,5 +154,9 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
|
||||||
_isValidNotifier.value = name.isNotEmpty;
|
_isValidNotifier.value = name.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _submit(BuildContext context) => Navigator.pop(context, Tuple2<AvesEntry?, String>(_coverEntry, _nameController.text));
|
void _submit(BuildContext context) {
|
||||||
|
if (_isValidNotifier.value) {
|
||||||
|
Navigator.pop(context, Tuple2<AvesEntry?, String>(_coverEntry, _nameController.text));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,5 +87,9 @@ class _RenameEntryDialogState extends State<RenameEntryDialog> {
|
||||||
_isValidNotifier.value = newName.isNotEmpty && !exists;
|
_isValidNotifier.value = newName.isNotEmpty && !exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _submit(BuildContext context) => Navigator.pop(context, _nameController.text);
|
void _submit(BuildContext context) {
|
||||||
|
if (_isValidNotifier.value) {
|
||||||
|
Navigator.pop(context, _nameController.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,5 +157,9 @@ class _CreateAlbumDialogState extends State<CreateAlbumDialog> {
|
||||||
_isValidNotifier.value = newName.isNotEmpty && !exists;
|
_isValidNotifier.value = newName.isNotEmpty && !exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _submit(BuildContext context) => Navigator.pop(context, _buildAlbumPath(_nameController.text));
|
void _submit(BuildContext context) {
|
||||||
|
if (_isValidNotifier.value) {
|
||||||
|
Navigator.pop(context, _buildAlbumPath(_nameController.text));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,8 +84,12 @@ class _RenameAlbumDialogState extends State<RenameAlbumDialog> {
|
||||||
final path = _buildAlbumPath(newName);
|
final path = _buildAlbumPath(newName);
|
||||||
final exists = newName.isNotEmpty && await FileSystemEntity.type(path) != FileSystemEntityType.notFound;
|
final exists = newName.isNotEmpty && await FileSystemEntity.type(path) != FileSystemEntityType.notFound;
|
||||||
_existsNotifier.value = exists && newName != initialValue;
|
_existsNotifier.value = exists && newName != initialValue;
|
||||||
_isValidNotifier.value = newName.isNotEmpty && !exists;
|
_isValidNotifier.value = newName.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _submit(BuildContext context) => Navigator.pop(context, _nameController.text);
|
void _submit(BuildContext context) {
|
||||||
|
if (_isValidNotifier.value) {
|
||||||
|
Navigator.pop(context, _nameController.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,5 +62,9 @@ class _ViewerThumbnailPreviewState extends State<ViewerThumbnailPreview> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onScrollerIndexChange() => _debouncer(() => ViewEntryNotification(index: _entryIndexNotifier.value).dispatch(context));
|
void _onScrollerIndexChange() => _debouncer(() {
|
||||||
|
if (mounted) {
|
||||||
|
ViewEntryNotification(index: _entryIndexNotifier.value).dispatch(context);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue