Add voice image packet retry

This commit is contained in:
Janez T
2026-03-01 19:25:19 +01:00
parent 0e7ba5572d
commit a0c4cdeede
10 changed files with 388 additions and 44 deletions

View File

@@ -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');

View File

@@ -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