diff --git a/lib/data/api/api_client.dart b/lib/data/api/api_client.dart index 1419f92..e88b917 100644 --- a/lib/data/api/api_client.dart +++ b/lib/data/api/api_client.dart @@ -44,6 +44,16 @@ class _ErrorInterceptor extends Interceptor { )); return; } + if (err.type == DioExceptionType.receiveTimeout || + err.type == DioExceptionType.sendTimeout) { + handler.reject(DioException( + requestOptions: err.requestOptions, + error: const AppException('Request timed out. The server is taking too long to respond.'), + type: err.type, + response: err.response, + )); + return; + } handler.next(err); } } diff --git a/lib/data/api/quick_capture_api.dart b/lib/data/api/quick_capture_api.dart index 19ca190..485b28c 100644 --- a/lib/data/api/quick_capture_api.dart +++ b/lib/data/api/quick_capture_api.dart @@ -40,6 +40,7 @@ class QuickCaptureApi { final response = await _dio.post( '/api/quick-capture', data: {'text': text}, + options: Options(receiveTimeout: const Duration(seconds: 120)), ); return CaptureResult.fromJson(response.data as Map); } on DioException catch (e) { diff --git a/lib/providers/update_provider.dart b/lib/providers/update_provider.dart index 73dbdcc..b5aac9c 100644 --- a/lib/providers/update_provider.dart +++ b/lib/providers/update_provider.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:open_file/open_file.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; enum UpdateStatus { idle, checking, available, downloading, upToDate, error } @@ -102,6 +103,22 @@ class UpdateNotifier extends Notifier { Future downloadAndInstall() async { if (state.downloadUrl == null) return; + + // Android 8+ requires explicit per-app "Install unknown apps" approval + // beyond the manifest declaration. Check and redirect to Settings if needed. + final installPermission = await Permission.requestInstallPackages.status; + if (!installPermission.isGranted) { + final result = await Permission.requestInstallPackages.request(); + if (!result.isGranted) { + state = state.copyWith( + status: UpdateStatus.error, + errorMessage: + 'Grant "Install unknown apps" permission for Fabled in Settings, then try again.', + ); + return; + } + } + state = state.copyWith(status: UpdateStatus.downloading, downloadProgress: 0); try { diff --git a/pubspec.yaml b/pubspec.yaml index 299298d..3830495 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,6 +22,7 @@ dependencies: markdown: ^7.2.2 package_info_plus: ^9.0.0 open_file: ^3.3.2 + permission_handler: ^11.3.1 flutter_inappwebview: ^6.1.5 flutter_markdown_plus: ^1.0.7 google_fonts: ^8.0.2