diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 44b900c..19d7118 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -489,7 +489,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = 64;
+ CURRENT_PROJECT_VERSION = 65;
DEVELOPMENT_TEAM = JND55328G8;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -511,7 +511,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 64;
+ CURRENT_PROJECT_VERSION = 65;
DEVELOPMENT_TEAM = JND55328G8;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
@@ -530,7 +530,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 64;
+ CURRENT_PROJECT_VERSION = 65;
DEVELOPMENT_TEAM = JND55328G8;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
@@ -547,7 +547,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 64;
+ CURRENT_PROJECT_VERSION = 65;
DEVELOPMENT_TEAM = JND55328G8;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
@@ -679,7 +679,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = 64;
+ CURRENT_PROJECT_VERSION = 65;
DEVELOPMENT_TEAM = JND55328G8;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -702,7 +702,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = 64;
+ CURRENT_PROJECT_VERSION = 65;
DEVELOPMENT_TEAM = JND55328G8;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 6a0c4f3..a049987 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -43,7 +43,7 @@
CFBundleSignature
????
CFBundleVersion
- 64
+ 65
LSRequiresIPhoneOS
NSBluetoothAlwaysUsageDescription
diff --git a/ios/fastlane/report.xml b/ios/fastlane/report.xml
index 46eea60..e157e94 100644
--- a/ios/fastlane/report.xml
+++ b/ios/fastlane/report.xml
@@ -5,19 +5,22 @@
-
+
-
+
-
+
-
+
+
+
+
diff --git a/lib/screens/messages_tab.dart b/lib/screens/messages_tab.dart
index e3bc2bf..70ff2d6 100644
--- a/lib/screens/messages_tab.dart
+++ b/lib/screens/messages_tab.dart
@@ -457,6 +457,7 @@ class _MessagesTabState extends State {
grayscale: grayscale,
);
if (result == null) {
+ if (!mounted) return;
ToastLogger.error(context, 'Image compression failed');
return;
}
@@ -487,6 +488,7 @@ class _MessagesTabState extends State {
);
if (fragments.isEmpty) {
+ if (!mounted) return;
ToastLogger.error(context, 'Image fragmentation failed');
return;
}
@@ -494,6 +496,7 @@ class _MessagesTabState extends State {
// Build envelope.
final deviceKey = connectionProvider.deviceInfo.publicKey;
if (deviceKey == null || deviceKey.length < 6) {
+ if (!mounted) return;
ToastLogger.error(context, 'Device key unavailable');
return;
}
@@ -513,6 +516,8 @@ class _MessagesTabState extends State {
timestampSec: DateTime.now().millisecondsSinceEpoch ~/ 1000,
);
+ if (!mounted) return;
+
// Cache for deferred serving.
final imageProvider = context.read();
imageProvider.cacheOutgoingSession(sessionId, fragments, envelope);
@@ -555,6 +560,7 @@ class _MessagesTabState extends State {
);
if (!sent) {
messagesProvider.markMessageFailed(msgId);
+ if (!mounted) return;
ToastLogger.error(context, 'Failed to announce image');
}
}
@@ -566,6 +572,7 @@ class _MessagesTabState extends State {
);
} catch (e, st) {
debugPrint('❌ [Image] _pickAndSendImage: $e\n$st');
+ if (!mounted) return;
ToastLogger.error(context, 'Image send failed');
} finally {
if (mounted) setState(() => _isSendingImage = false);
diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart
index 49edb75..f0261dc 100644
--- a/lib/screens/settings_screen.dart
+++ b/lib/screens/settings_screen.dart
@@ -1206,24 +1206,26 @@ class _SettingsScreenState extends State {
builder: (context) => AlertDialog(
title: const Text('Max image size'),
content: SingleChildScrollView(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: ImagePreferences.supportedSizes
- .map(
- (size) => RadioListTile(
- value: size,
- groupValue: _imageMaxSize,
- title: Text('${size}×$size px'),
- subtitle: size == ImagePreferences.defaultMaxSize
- ? const Text('Default')
- : null,
- onChanged: (value) {
- if (value != null) _saveImageMaxSize(value);
- Navigator.pop(context);
- },
- ),
- )
- .toList(),
+ child: RadioGroup(
+ groupValue: _imageMaxSize,
+ onChanged: (value) {
+ if (value != null) _saveImageMaxSize(value);
+ Navigator.pop(context);
+ },
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: ImagePreferences.supportedSizes
+ .map(
+ (size) => RadioListTile(
+ value: size,
+ title: Text('$size×$size px'),
+ subtitle: size == ImagePreferences.defaultMaxSize
+ ? const Text('Default')
+ : null,
+ ),
+ )
+ .toList(),
+ ),
),
),
actions: [