Add fragment transfer estimate

This commit is contained in:
Janez T
2026-03-05 09:38:39 +01:00
parent 55a85659d3
commit 76b093685e
4 changed files with 77 additions and 2 deletions

View File

@@ -13,6 +13,8 @@ class ImageSession {
final int width;
final int height;
final List<ImagePacket?> fragments; // indexed by fragment.index
DateTime? firstFragmentAt;
DateTime? lastFragmentAt;
ImageSession({
required this.sessionId,
@@ -25,6 +27,21 @@ class ImageSession {
int get receivedCount => fragments.where((f) => f != null).length;
bool get isComplete => receivedCount == total;
Duration? estimateRemaining() {
if (isComplete) return Duration.zero;
if (firstFragmentAt == null || lastFragmentAt == null) return null;
if (receivedCount < 2) return null;
final elapsedMs = lastFragmentAt!
.difference(firstFragmentAt!)
.inMilliseconds;
if (elapsedMs <= 0) return null;
final avgMsPerFragment = elapsedMs / (receivedCount - 1);
final remaining = total - receivedCount;
if (remaining <= 0) return Duration.zero;
return Duration(milliseconds: (avgMsPerFragment * remaining).round());
}
/// Reassemble the complete image bytes, or null if any fragment is missing.
Uint8List? get imageBytes => reassembleImage(fragments);
}
@@ -62,6 +79,8 @@ class ImageProvider with ChangeNotifier {
bool isComplete(String sessionId) =>
_sessions[sessionId]?.isComplete ?? false;
bool hasOutgoing(String sessionId) => _outgoing.containsKey(sessionId);
Duration? estimateRemainingTransferTime(String sessionId) =>
_sessions[sessionId]?.estimateRemaining();
List<int> missingFragmentIndices(String sessionId) {
final session = _sessions[sessionId];
@@ -94,7 +113,13 @@ class ImageProvider with ChangeNotifier {
final session = _sessions[fragment.sessionId]!;
if (fragment.index < session.total) {
final wasMissing = session.fragments[fragment.index] == null;
session.fragments[fragment.index] = fragment;
if (wasMissing) {
final now = DateTime.now();
session.firstFragmentAt ??= now;
session.lastFragmentAt = now;
}
}
final justComplete = session.isComplete;

View File

@@ -13,6 +13,8 @@ class VoiceSession {
final VoicePacketMode mode;
final int total;
final List<VoicePacket?> packets; // indexed by packet.index
DateTime? firstPacketAt;
DateTime? lastPacketAt;
VoiceSession({
required this.sessionId,
@@ -23,6 +25,19 @@ class VoiceSession {
int get receivedCount => packets.where((p) => p != null).length;
bool get isComplete => receivedCount == total;
Duration? estimateRemaining() {
if (isComplete) return Duration.zero;
if (firstPacketAt == null || lastPacketAt == null) return null;
if (receivedCount < 2) return null;
final elapsedMs = lastPacketAt!.difference(firstPacketAt!).inMilliseconds;
if (elapsedMs <= 0) return null;
final avgMsPerPacket = elapsedMs / (receivedCount - 1);
final remaining = total - receivedCount;
if (remaining <= 0) return Duration.zero;
return Duration(milliseconds: (avgMsPerPacket * remaining).round());
}
/// Total estimated audio duration in seconds (sum of all received packets).
double get estimatedDurationSeconds {
var ms = 0;
@@ -93,6 +108,8 @@ class VoiceProvider with ChangeNotifier {
bool hasOutgoingSession(String sessionId) =>
_outgoingSessions.containsKey(sessionId);
Duration? estimateRemainingTransferTime(String sessionId) =>
_sessions[sessionId]?.estimateRemaining();
List<int> missingPacketIndices(String sessionId) {
final session = _sessions[sessionId];
@@ -120,7 +137,13 @@ class VoiceProvider with ChangeNotifier {
final session = _sessions[packet.sessionId]!;
if (packet.index < session.total) {
final wasMissing = session.packets[packet.index] == null;
session.packets[packet.index] = packet;
if (wasMissing) {
final now = DateTime.now();
session.firstPacketAt ??= now;
session.lastPacketAt = now;
}
}
final justComplete = session.isComplete;