| .. | .. |
|---|
| 2 | 2 | import 'dart:convert'; |
|---|
| 3 | 3 | import 'dart:io'; |
|---|
| 4 | 4 | |
|---|
| 5 | +import 'package:flutter/services.dart'; |
|---|
| 5 | 6 | import 'package:path_provider/path_provider.dart'; |
|---|
| 6 | 7 | |
|---|
| 7 | 8 | import '../models/message.dart'; |
|---|
| .. | .. |
|---|
| 14 | 15 | static Timer? _debounceTimer; |
|---|
| 15 | 16 | static final Map<String, List<Message>> _pendingSaves = {}; |
|---|
| 16 | 17 | |
|---|
| 18 | + static const _backupChannel = |
|---|
| 19 | + MethodChannel('com.mnsoft.pailot/backup'); |
|---|
| 20 | + |
|---|
| 17 | 21 | /// Initialize the base directory for message storage. |
|---|
| 22 | + /// On iOS, the directory is excluded from iCloud / iTunes backup so that |
|---|
| 23 | + /// large base64 image attachments do not bloat the user's cloud storage. |
|---|
| 24 | + /// Messages can be re-fetched from the server if needed. |
|---|
| 18 | 25 | static Future<Directory> _getBaseDir() async { |
|---|
| 19 | 26 | if (_baseDir != null) return _baseDir!; |
|---|
| 20 | 27 | final appDir = await getApplicationDocumentsDirectory(); |
|---|
| 21 | 28 | _baseDir = Directory('${appDir.path}/messages'); |
|---|
| 22 | | - if (!await _baseDir!.exists()) { |
|---|
| 29 | + final created = !await _baseDir!.exists(); |
|---|
| 30 | + if (created) { |
|---|
| 23 | 31 | await _baseDir!.create(recursive: true); |
|---|
| 24 | 32 | } |
|---|
| 33 | + // Exclude from iCloud / iTunes backup (best-effort, iOS only). |
|---|
| 34 | + if (Platform.isIOS) { |
|---|
| 35 | + try { |
|---|
| 36 | + await _backupChannel.invokeMethod<void>( |
|---|
| 37 | + 'excludeFromBackup', |
|---|
| 38 | + _baseDir!.path, |
|---|
| 39 | + ); |
|---|
| 40 | + } catch (_) { |
|---|
| 41 | + // Non-fatal: if the channel call fails, backup exclusion is skipped. |
|---|
| 42 | + } |
|---|
| 43 | + } |
|---|
| 25 | 44 | return _baseDir!; |
|---|
| 26 | 45 | } |
|---|
| 27 | 46 | |
|---|