various edge case fixes

This commit is contained in:
Thibault Deckers 2022-03-17 11:17:44 +09:00
parent d8fca48ef8
commit a074ff5dd6
8 changed files with 51 additions and 16 deletions

View file

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

View file

@ -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 {
try {
activity.contentResolver.openInputStream(uri)?.use { input -> activity.contentResolver.openInputStream(uri)?.use { input ->
val buffer = ByteArray(BUFFER_SIZE) val buffer = ByteArray(BUFFER_SIZE)
var len: Int var len: Int
while (input.read(buffer).also { len = it } != -1) { while (input.read(buffer).also { len = it } != -1) {
success(buffer.copyOf(len)) success(buffer.copyOf(len))
} }
}
} catch (e: Exception) {
Log.e(LOG_TAG, "failed to open input stream for uri=$uri", e)
} finally {
endOfStream() endOfStream()
} }
} }

View file

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

View 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));
}
}
} }

View file

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

View file

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

View file

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

View file

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