obsolete files: give error hint on viewer, allow deleting from media store
This commit is contained in:
parent
34b6ef0428
commit
f6434f0b5f
3 changed files with 48 additions and 14 deletions
|
@ -186,7 +186,7 @@ class MediaStoreImageProvider : ImageProvider() {
|
||||||
override suspend fun delete(context: Context, uri: Uri, path: String?) {
|
override suspend fun delete(context: Context, uri: Uri, path: String?) {
|
||||||
path ?: throw Exception("failed to delete file because path is null")
|
path ?: throw Exception("failed to delete file because path is null")
|
||||||
|
|
||||||
if (requireAccessPermission(context, path)) {
|
if (File(path).exists() && requireAccessPermission(context, path)) {
|
||||||
// if the file is on SD card, calling the content resolver `delete()` removes the entry from the Media Store
|
// if the file is on SD card, calling the content resolver `delete()` removes the entry from the Media Store
|
||||||
// but it doesn't delete the file, even if the app has the permission
|
// but it doesn't delete the file, even if the app has the permission
|
||||||
val df = getDocumentFile(context, path, uri)
|
val df = getDocumentFile(context, path, uri)
|
||||||
|
|
|
@ -129,7 +129,10 @@ class _EntryPageViewState extends State<EntryPageView> {
|
||||||
} else if (entry.canDecode) {
|
} else if (entry.canDecode) {
|
||||||
child = _buildRasterView();
|
child = _buildRasterView();
|
||||||
}
|
}
|
||||||
child ??= ErrorView(onTap: () => onTap?.call(null));
|
child ??= ErrorView(
|
||||||
|
entry: entry,
|
||||||
|
onTap: () => onTap?.call(null),
|
||||||
|
);
|
||||||
|
|
||||||
return widget.heroTag != null
|
return widget.heroTag != null
|
||||||
? Hero(
|
? Hero(
|
||||||
|
@ -146,7 +149,10 @@ class _EntryPageViewState extends State<EntryPageView> {
|
||||||
child: RasterImageView(
|
child: RasterImageView(
|
||||||
entry: entry,
|
entry: entry,
|
||||||
viewStateNotifier: _viewStateNotifier,
|
viewStateNotifier: _viewStateNotifier,
|
||||||
errorBuilder: (context, error, stackTrace) => ErrorView(onTap: () => onTap?.call(null)),
|
errorBuilder: (context, error, stackTrace) => ErrorView(
|
||||||
|
entry: entry,
|
||||||
|
onTap: () => onTap?.call(null),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,54 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/collection/empty.dart';
|
import 'package:aves/widgets/collection/empty.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ErrorView extends StatelessWidget {
|
class ErrorView extends StatefulWidget {
|
||||||
|
final AvesEntry entry;
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
|
||||||
const ErrorView({@required this.onTap});
|
const ErrorView({
|
||||||
|
@required this.entry,
|
||||||
|
@required this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ErrorViewState createState() => _ErrorViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ErrorViewState extends State<ErrorView> {
|
||||||
|
Future<bool> _exists;
|
||||||
|
|
||||||
|
AvesEntry get entry => widget.entry;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_exists = entry.path != null ? File(entry.path).exists() : SynchronousFuture(true);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => onTap?.call(),
|
onTap: () => widget.onTap?.call(),
|
||||||
// use a `Container` with a dummy color to make it expand
|
// use container to expand constraints, so that the user can tap anywhere
|
||||||
// so that we can also detect taps around the title `Text`
|
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.transparent,
|
// opaque to cover potential lower quality layer below
|
||||||
child: EmptyContent(
|
color: Colors.black,
|
||||||
|
child: FutureBuilder<bool>(
|
||||||
|
future: _exists,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox();
|
||||||
|
final exists = snapshot.data;
|
||||||
|
return EmptyContent(
|
||||||
icon: AIcons.error,
|
icon: AIcons.error,
|
||||||
text: 'Oops!',
|
text: exists ? 'Oops!' : 'The file no longer exists.',
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
),
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue