Add icons and info text for delivery data on posts/comments

Implements Feature #66
This commit is contained in:
Hank Grabowski 2024-06-28 10:57:35 -04:00
parent 5b8320d8c4
commit 526c8c4d83
5 changed files with 78 additions and 4 deletions

View file

@ -41,6 +41,8 @@
old. ([Feature #58](https://gitlab.com/mysocialportal/relatica/-/issues/58))
* Autocomplete now lists hashtags and accounts that are used in a post or post above the rest of the
results. ([Feature #28](https://gitlab.com/mysocialportal/relatica/-/issues/28))
* Show delivery data for logged in user's posts and comments (not
reshares) ([Feature #66](https://gitlab.com/mysocialportal/relatica/-/issues/66))
## Version 0.10.1 (beta)

View file

@ -142,9 +142,44 @@ class StatusHeaderControl extends StatelessWidget {
),
),
TimelineNetworkInfoControl(info: entry.networkInfo),
if (entry.deliveryData.hasDeliveryData) ...[
const HorizontalPadding(),
buildDeliveryIndicator(context),
],
],
),
],
);
}
Widget buildDeliveryIndicator(BuildContext context) {
final data = entry.deliveryData;
const fullyDeliveredIcon = '\uf1d8'; //fa-paper-plane
const inDeliveryIcon = '\uf1d9'; //fa-paper-plane-o
final percentRemaining =
data.leftForDelivery.toDouble() / data.total.toDouble();
final iconText =
percentRemaining > 0.1 ? inDeliveryIcon : fullyDeliveredIcon;
return GestureDetector(
onTap: () async {
final text = """
Federated Messages Deliveries to Remote Servers
Total: ${data.total}
Completed: ${data.done}
Failed: ${data.failed}
Remaining: ${data.leftForDelivery}
""";
showConfirmDialog(context, text);
},
child: Tooltip(
message:
'Deliveries to remote servers: ${entry.deliveryData.done}/${entry.deliveryData.total}',
child: Text(
iconText,
style: const TextStyle(fontFamily: 'ForkAwesome'),
),
),
);
}
}

View file

@ -0,0 +1,17 @@
class DeliveryData {
static const empty = DeliveryData(total: 0, done: 0, failed: 0);
final int total;
final int done;
final int failed;
const DeliveryData({
required this.total,
required this.done,
required this.failed,
});
bool get hasDeliveryData => total > 0;
int get leftForDelivery => total - done - failed;
}

View file

@ -1,5 +1,6 @@
import '../globals.dart';
import 'connection.dart';
import 'delivery_data.dart';
import 'engagement_summary.dart';
import 'link_data.dart';
import 'link_preview_data.dart';
@ -59,6 +60,8 @@ class TimelineEntry {
final EngagementSummary engagementSummary;
final DeliveryData deliveryData;
TimelineEntry(
{this.id = '',
this.parentId = '',
@ -84,7 +87,8 @@ class TimelineEntry {
this.mediaAttachments = const [],
this.engagementSummary = const EngagementSummary(),
this.networkInfo = TimelineNetworkInfo.empty,
this.linkPreviewData})
this.linkPreviewData,
this.deliveryData = DeliveryData.empty})
: visibility = visibility ?? Visibility.public();
TimelineEntry.randomBuilt()
@ -114,7 +118,8 @@ class TimelineEntry {
mediaAttachments = [],
networkInfo = TimelineNetworkInfo.empty,
engagementSummary = const EngagementSummary(),
linkPreviewData = LinkPreviewData(link: 'fake link');
linkPreviewData = LinkPreviewData(link: 'fake link'),
deliveryData = DeliveryData.empty;
TimelineEntry copy({
int? creationTimestamp,
@ -145,6 +150,7 @@ class TimelineEntry {
EngagementSummary? engagementSummary,
TimelineNetworkInfo? networkInfo,
LinkPreviewData? linkPreviewData,
DeliveryData? deliveryData,
}) {
return TimelineEntry(
creationTimestamp: creationTimestamp ?? this.creationTimestamp,
@ -173,6 +179,7 @@ class TimelineEntry {
engagementSummary: engagementSummary ?? this.engagementSummary,
networkInfo: networkInfo ?? this.networkInfo,
linkPreviewData: linkPreviewData ?? this.linkPreviewData,
deliveryData: deliveryData ?? this.deliveryData,
);
}
@ -213,7 +220,8 @@ class TimelineEntry {
dislikes == other.dislikes &&
mediaAttachments == other.mediaAttachments &&
networkInfo == other.networkInfo &&
engagementSummary == other.engagementSummary;
engagementSummary == other.engagementSummary &&
deliveryData == other.deliveryData;
@override
int get hashCode =>
@ -240,5 +248,6 @@ class TimelineEntry {
dislikes.hashCode ^
mediaAttachments.hashCode ^
networkInfo.hashCode ^
engagementSummary.hashCode;
engagementSummary.hashCode ^
deliveryData.hashCode;
}

View file

@ -1,6 +1,7 @@
import 'package:logging/logging.dart';
import '../../globals.dart';
import '../../models/delivery_data.dart';
import '../../models/engagement_summary.dart';
import '../../models/link_data.dart';
import '../../models/location_data.dart';
@ -152,6 +153,15 @@ extension TimelineEntryMastodonExtensions on TimelineEntry {
final connection = ConnectionMastodonExtensions.fromJson(json['account']);
connectionManager?.upsertConnection(connection);
final ddj = json['friendica']?['delivery_data'];
final deliveryData = ddj == null
? DeliveryData.empty
: DeliveryData(
total: ddj['delivery_queue_count'] ?? 0,
done: ddj['delivery_queue_done'] ?? 0,
failed: ddj['delivery_queue_failed'] ?? 0,
);
return TimelineEntry(
creationTimestamp: timestamp,
modificationTimestamp: modificationTimestamp,
@ -176,6 +186,7 @@ extension TimelineEntryMastodonExtensions on TimelineEntry {
engagementSummary: engagementSummary,
networkInfo: networkInfo,
linkPreviewData: linkPreviewData,
deliveryData: deliveryData,
);
}
}