improve download handling
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<!-- Needed for uploading media files on devices with Android 13 and later. -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
|
||||
|
||||
+29
@@ -45,6 +45,7 @@ import 'package:weblibre/presentation/hooks/menu_controller.dart';
|
||||
import 'package:weblibre/presentation/widgets/failure_widget.dart';
|
||||
import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart';
|
||||
import 'package:weblibre/presentation/widgets/url_icon.dart';
|
||||
import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
|
||||
|
||||
class Section extends MultiSliver {
|
||||
static final _datePattern = DateFormat.MMMd().addPattern('Hm');
|
||||
@@ -499,6 +500,34 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
onTap: (item) async {
|
||||
if (selectedItems.value.isNotEmpty) {
|
||||
toggleSelected(item);
|
||||
} else if (isDownloadsMode) {
|
||||
final filePath = item.title;
|
||||
final file = filePath.mapNotNull(File.new);
|
||||
|
||||
if (file == null ||
|
||||
await file.exists() != true) {
|
||||
if (context.mounted) {
|
||||
ui_helper.showErrorMessage(
|
||||
context,
|
||||
'Downloaded file not found',
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final opened = await GeckoDownloadsService()
|
||||
.openDownloadedFile(
|
||||
fileName: p.basename(file.path),
|
||||
directoryPath: file.parent.path,
|
||||
contentType: item.previewImageUrl,
|
||||
);
|
||||
|
||||
if (!opened && context.mounted) {
|
||||
ui_helper.showErrorMessage(
|
||||
context,
|
||||
'Could not open downloaded file',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
|
||||
+2
-2
@@ -441,7 +441,7 @@ final class UnifiedPreferenceSettingsRepositoryProvider
|
||||
}
|
||||
|
||||
String _$unifiedPreferenceSettingsRepositoryHash() =>
|
||||
r'c544b5815ec676ddb6cde1ffeb8c9ef4a7dc4469';
|
||||
r'f2153c826e2cba308cf3e8bdfe371e0b6b3e7dbd';
|
||||
|
||||
final class UnifiedPreferenceSettingsRepositoryFamily extends $Family
|
||||
with
|
||||
@@ -554,7 +554,7 @@ final class PreferenceSettingsGroupRepositoryProvider
|
||||
}
|
||||
|
||||
String _$preferenceSettingsGroupRepositoryHash() =>
|
||||
r'c8335b39c4c9fa95c4d415231b103a2feff97d26';
|
||||
r'ae2b8553b895945d2a5c44a8ed24b8bbb00bb985';
|
||||
|
||||
final class PreferenceSettingsGroupRepositoryFamily extends $Family
|
||||
with
|
||||
|
||||
@@ -18,9 +18,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:weblibre/core/providers/router.dart';
|
||||
import 'package:weblibre/domain/services/app_initialization.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers.dart';
|
||||
import 'package:weblibre/features/sync/domain/entities/sync_repository_state.dart';
|
||||
import 'package:weblibre/features/sync/domain/repositories/sync.dart';
|
||||
import 'package:weblibre/features/web_search/domain/controllers/sandbox_capture_controller.dart';
|
||||
@@ -99,7 +102,9 @@ class MainApp extends HookConsumerWidget {
|
||||
disableAnimations: disableAnimations,
|
||||
child: _SyncEventListener(
|
||||
child: _SandboxCaptureErrorListener(
|
||||
child: child ?? const SizedBox.shrink(),
|
||||
child: _DownloadStoppedListener(
|
||||
child: child ?? const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -142,6 +147,65 @@ class MainApp extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _DownloadStoppedListener extends HookConsumerWidget {
|
||||
final Widget child;
|
||||
|
||||
const _DownloadStoppedListener({required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final downloadStoppedEvents = ref.watch(
|
||||
eventServiceProvider.select((service) => service.downloadStoppedEvents),
|
||||
);
|
||||
|
||||
useOnStreamChange(
|
||||
downloadStoppedEvents,
|
||||
onData: (download) {
|
||||
switch (download.status) {
|
||||
case DownloadStatus.completed:
|
||||
ui_helper.showInfoMessage(
|
||||
context,
|
||||
'Download completed',
|
||||
duration: const Duration(seconds: 6),
|
||||
action: SnackBarAction(
|
||||
label: 'Open',
|
||||
onPressed: () async {
|
||||
final opened = await GeckoDownloadsService()
|
||||
.openDownloadedFile(
|
||||
fileName: download.fileName ?? '',
|
||||
directoryPath: download.directoryPath ?? '',
|
||||
contentType: download.contentType,
|
||||
);
|
||||
|
||||
if (!opened && context.mounted) {
|
||||
ui_helper.showErrorMessage(
|
||||
context,
|
||||
'Could not open downloaded file',
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
case DownloadStatus.failed:
|
||||
ui_helper.showErrorMessage(
|
||||
context,
|
||||
'Download failed: ${download.fileName ?? download.url}',
|
||||
persist: true,
|
||||
);
|
||||
case DownloadStatus.initiated:
|
||||
case DownloadStatus.downloading:
|
||||
case DownloadStatus.paused:
|
||||
case DownloadStatus.cancelled:
|
||||
case null:
|
||||
break;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
MediaQueryData applyAppMediaQueryOverrides({
|
||||
required MediaQueryData mediaQuery,
|
||||
required double uiScaleFactor,
|
||||
|
||||
Reference in New Issue
Block a user