You've already forked immich
mirror of
https://github.com/immich-app/immich.git
synced 2025-07-17 15:47:54 +02:00
fix(mobile): check and request permissions when saving files to prevent hard crash
This commit is contained in:
@ -141,7 +141,7 @@ class DownloadStateNotifier extends StateNotifier<DownloadState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void downloadAsset(Asset asset, BuildContext context) async {
|
void downloadAsset(Asset asset, BuildContext context) async {
|
||||||
await _downloadService.download(asset);
|
await _downloadService.download(asset, context: context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancelDownload(String id) async {
|
void cancelDownload(String id) async {
|
||||||
|
@ -13,6 +13,9 @@ import 'package:immich_mobile/repositories/file_media.repository.dart';
|
|||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
import 'package:immich_mobile/utils/download.dart';
|
import 'package:immich_mobile/utils/download.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart' as ph;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
final downloadServiceProvider = Provider(
|
final downloadServiceProvider = Provider(
|
||||||
(ref) => DownloadService(
|
(ref) => DownloadService(
|
||||||
@ -158,7 +161,11 @@ class DownloadService {
|
|||||||
return await FileDownloader().cancelTaskWithId(id);
|
return await FileDownloader().cancelTaskWithId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> download(Asset asset) async {
|
Future<void> download(Asset asset, {BuildContext? context}) async {
|
||||||
|
if (!await _handlePermission(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (asset.isImage && asset.livePhotoVideoId != null && Platform.isIOS) {
|
if (asset.isImage && asset.livePhotoVideoId != null && Platform.isIOS) {
|
||||||
await _downloadRepository.download(
|
await _downloadRepository.download(
|
||||||
_buildDownloadTask(
|
_buildDownloadTask(
|
||||||
@ -196,6 +203,53 @@ class DownloadService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> _handlePermission(BuildContext? context) async {
|
||||||
|
final permission = await ph.Permission.photos.status;
|
||||||
|
if (permission.isDenied || permission.isPermanentlyDenied) {
|
||||||
|
if (context == null) return false;
|
||||||
|
|
||||||
|
final bool? shouldRequest = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('permission_onboarding_request').tr(),
|
||||||
|
content: const Text('permission_onboarding_permission_denied').tr(),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context, false),
|
||||||
|
child: const Text('cancel').tr(),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context, true),
|
||||||
|
child: Text(
|
||||||
|
permission.isPermanentlyDenied
|
||||||
|
? 'permission_onboarding_go_to_settings'
|
||||||
|
: 'permission_onboarding_grant_permission',
|
||||||
|
).tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (shouldRequest == true) {
|
||||||
|
if (permission.isPermanentlyDenied) {
|
||||||
|
await ph.openAppSettings();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final result = await ph.Permission.photos.request();
|
||||||
|
if (!result.isGranted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
DownloadTask _buildDownloadTask(
|
DownloadTask _buildDownloadTask(
|
||||||
String id,
|
String id,
|
||||||
String filename, {
|
String filename, {
|
||||||
|
Reference in New Issue
Block a user