Sync update: 2026-05-18 21:13:35

This commit is contained in:
Hamza-Ayed
2026-05-18 21:13:35 +03:00
parent 340a22fffa
commit 1eec712c58

View File

@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:get/get.dart';
@@ -152,11 +153,13 @@ class MessageBubble extends StatelessWidget {
Widget _buildAckIcon(int ack) {
switch (ack) {
case 1: // Pending/Queued
return const Icon(Icons.access_time, size: 13, color: AppTheme.textSecondary);
return const Icon(Icons.access_time,
size: 13, color: AppTheme.textSecondary);
case 2: // Sent (single grey tick)
return const Icon(Icons.done, size: 15, color: AppTheme.textSecondary);
case 3: // Delivered (double grey tick)
return const Icon(Icons.done_all, size: 15, color: AppTheme.textSecondary);
return const Icon(Icons.done_all,
size: 15, color: AppTheme.textSecondary);
case 4: // Read (double blue tick)
return const Icon(Icons.done_all, size: 15, color: Colors.blue);
case 5: // Played audio/video (double blue with wave icon)
@@ -250,7 +253,8 @@ class _InteractiveMediaWidgetState extends State<InteractiveMediaWidget> {
await _player.pause();
} else {
final bytes = base64Decode(base64Data);
final safeId = widget.message.id.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '');
final safeId =
widget.message.id.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '');
final tempDir = Directory.systemTemp;
final tempFile = File('${tempDir.path}/voice_$safeId.mp3');
@@ -293,7 +297,8 @@ class _InteractiveMediaWidgetState extends State<InteractiveMediaWidget> {
child: const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(strokeWidth: 2, color: AppTheme.primary),
child: CircularProgressIndicator(
strokeWidth: 2, color: AppTheme.primary),
),
);
}
@@ -318,12 +323,16 @@ class _InteractiveMediaWidgetState extends State<InteractiveMediaWidget> {
children: [
Text(
_getLabel(),
style: const TextStyle(color: AppTheme.textPrimary, fontWeight: FontWeight.w500, fontSize: 13),
style: const TextStyle(
color: AppTheme.textPrimary,
fontWeight: FontWeight.w500,
fontSize: 13),
),
const SizedBox(height: 2),
const Text(
'Tap to download',
style: TextStyle(color: AppTheme.textSecondary, fontSize: 10),
style:
TextStyle(color: AppTheme.textSecondary, fontSize: 10),
),
],
),
@@ -397,7 +406,9 @@ class _InteractiveMediaWidgetState extends State<InteractiveMediaWidget> {
children: [
IconButton(
icon: Icon(
_isPlaying ? Icons.pause_circle_filled : Icons.play_circle_filled,
_isPlaying
? Icons.pause_circle_filled
: Icons.play_circle_filled,
color: AppTheme.primary,
size: 36,
),
@@ -413,8 +424,10 @@ class _InteractiveMediaWidgetState extends State<InteractiveMediaWidget> {
SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 2.5,
thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 5),
overlayShape: const RoundSliderOverlayShape(overlayRadius: 10),
thumbShape:
const RoundSliderThumbShape(enabledThumbRadius: 5),
overlayShape:
const RoundSliderOverlayShape(overlayRadius: 10),
activeTrackColor: AppTheme.primary,
inactiveTrackColor: AppTheme.surfaceLight,
thumbColor: AppTheme.primary,
@@ -423,7 +436,8 @@ class _InteractiveMediaWidgetState extends State<InteractiveMediaWidget> {
child: Slider(
value: _audioProgress.clamp(0.0, 1.0),
onChanged: (v) async {
final targetMs = (v * _audioDurationSeconds * 1000).toInt();
final targetMs =
(v * _audioDurationSeconds * 1000).toInt();
await _player.seek(Duration(milliseconds: targetMs));
},
),
@@ -457,11 +471,13 @@ class _InteractiveMediaWidgetState extends State<InteractiveMediaWidget> {
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.check_circle_outline, color: AppTheme.primary, size: 32),
const Icon(Icons.check_circle_outline,
color: AppTheme.primary, size: 32),
const SizedBox(width: 12),
Text(
_getLabel(),
style: const TextStyle(color: AppTheme.textPrimary, fontWeight: FontWeight.w500),
style: const TextStyle(
color: AppTheme.textPrimary, fontWeight: FontWeight.w500),
),
],
),
@@ -470,21 +486,31 @@ class _InteractiveMediaWidgetState extends State<InteractiveMediaWidget> {
IconData _getIcon() {
switch (widget.message.type) {
case "image": return Icons.photo_outlined;
case "video": return Icons.videocam_outlined;
case "audio": return Icons.audiotrack_outlined;
case "sticker": return Icons.emoji_emotions_outlined;
default: return Icons.insert_drive_file_outlined;
case "image":
return Icons.photo_outlined;
case "video":
return Icons.videocam_outlined;
case "audio":
return Icons.audiotrack_outlined;
case "sticker":
return Icons.emoji_emotions_outlined;
default:
return Icons.insert_drive_file_outlined;
}
}
String _getLabel() {
switch (widget.message.type) {
case "image": return "Image Attachment";
case "video": return "Video Attachment";
case "audio": return "Audio / Voice Note";
case "sticker": return "Sticker Attachment";
default: return "File Attachment";
case "image":
return "Image Attachment";
case "video":
return "Video Attachment";
case "audio":
return "Audio / Voice Note";
case "sticker":
return "Sticker Attachment";
default:
return "File Attachment";
}
}
}