mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Add voice image packet retry
This commit is contained in:
@@ -446,13 +446,15 @@ class _MessagesTabState extends State<MessagesTab> {
|
||||
|
||||
setState(() => _isSendingImage = true);
|
||||
try {
|
||||
// Compress to grayscale AVIF using user-selected size and compression.
|
||||
// Compress AVIF using user-selected size, compression and color mode.
|
||||
final maxSize = await ImagePreferences.getMaxSize();
|
||||
final compression = await ImagePreferences.getCompression();
|
||||
final grayscale = await ImagePreferences.getGrayscale();
|
||||
final result = await ImageCodecService.compress(
|
||||
rawBytes,
|
||||
maxDimension: maxSize,
|
||||
compression: compression,
|
||||
grayscale: grayscale,
|
||||
);
|
||||
if (result == null) {
|
||||
ToastLogger.error(context, 'Image compression failed');
|
||||
@@ -467,10 +469,21 @@ class _MessagesTabState extends State<MessagesTab> {
|
||||
).join();
|
||||
|
||||
// Fragment.
|
||||
var imageDataBytesPerFragment = ImagePacket.maxDataBytes;
|
||||
if (_destinationType ==
|
||||
MessageDestinationPreferences.destinationTypeContact &&
|
||||
_selectedRecipient != null &&
|
||||
_selectedRecipient!.outPathLen >= 0) {
|
||||
imageDataBytesPerFragment = safeImageDataBytesForPath(
|
||||
_selectedRecipient!.outPathLen,
|
||||
);
|
||||
}
|
||||
|
||||
final fragments = fragmentImage(
|
||||
sessionId: sessionId,
|
||||
format: ImageFormat.avif,
|
||||
bytes: compressed,
|
||||
maxDataBytes: imageDataBytesPerFragment,
|
||||
);
|
||||
|
||||
if (fragments.isEmpty) {
|
||||
@@ -548,7 +561,8 @@ class _MessagesTabState extends State<MessagesTab> {
|
||||
|
||||
debugPrint(
|
||||
'📷 [Image] Sent IE1 for session $sessionId: '
|
||||
'${fragments.length} fragments, ${compressed.length}B',
|
||||
'${fragments.length} fragments, ${compressed.length}B, '
|
||||
'chunk=${imageDataBytesPerFragment}B',
|
||||
);
|
||||
} catch (e, st) {
|
||||
debugPrint('❌ [Image] _pickAndSendImage: $e\n$st');
|
||||
|
||||
@@ -50,6 +50,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
int _voiceBitrate = VoiceBitratePreferences.defaultBitrate;
|
||||
int _imageMaxSize = ImagePreferences.defaultMaxSize;
|
||||
int _imageCompression = ImagePreferences.defaultQuality;
|
||||
bool _imageGrayscale = ImagePreferences.defaultGrayscale;
|
||||
final LocationTrackingService _locationService = LocationTrackingService();
|
||||
|
||||
@override
|
||||
@@ -119,10 +120,12 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
Future<void> _loadImagePreferences() async {
|
||||
final size = await ImagePreferences.getMaxSize();
|
||||
final compression = await ImagePreferences.getCompression();
|
||||
final grayscale = await ImagePreferences.getGrayscale();
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_imageMaxSize = size;
|
||||
_imageCompression = compression;
|
||||
_imageGrayscale = grayscale;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -695,6 +698,18 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
onChangeEnd: (v) => _saveImageCompression(v.round()),
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
secondary: const Icon(Icons.invert_colors),
|
||||
title: const Text('Grayscale'),
|
||||
subtitle: const Text(
|
||||
'Converts image to grayscale for smaller file size',
|
||||
),
|
||||
value: _imageGrayscale,
|
||||
onChanged: (value) async {
|
||||
await ImagePreferences.setGrayscale(value);
|
||||
setState(() => _imageGrayscale = value);
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
|
||||
// Templates Section
|
||||
|
||||
Reference in New Issue
Block a user