From 2344ed887d01254367df329c668ec41648571178 Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Tue, 19 May 2026 19:45:39 -0400 Subject: [PATCH] Add file card --- lib/helpers/extensions/size_to_string.dart | 22 ++++++++++++++++ lib/widgets/file_card.dart | 29 ++++++++++++++++++++++ lib/widgets/renderers/event.dart | 12 +++++++-- 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 lib/helpers/extensions/size_to_string.dart create mode 100644 lib/widgets/file_card.dart diff --git a/lib/helpers/extensions/size_to_string.dart b/lib/helpers/extensions/size_to_string.dart new file mode 100644 index 0000000..654df9a --- /dev/null +++ b/lib/helpers/extensions/size_to_string.dart @@ -0,0 +1,22 @@ +import "package:fast_immutable_collections/fast_immutable_collections.dart"; + +extension SizeToString on int { + String get sizeAsString { + const IListConst suffixes = IListConst([ + "B", + "KB", + "MB", + "GB", + "TB", + "PB", + ]); + + var i = 0; + var size = toDouble(); + while (size > 1024 && i < suffixes.length - 1) { + size /= 1024; + i++; + } + return "${size.toStringAsFixed(2)} ${suffixes[i]}"; + } +} diff --git a/lib/widgets/file_card.dart b/lib/widgets/file_card.dart new file mode 100644 index 0000000..7e3bb6f --- /dev/null +++ b/lib/widgets/file_card.dart @@ -0,0 +1,29 @@ +import "package:flutter/material.dart"; +import "package:nexus/helpers/extensions/size_to_string.dart"; +import "package:nexus/models/info/file.dart"; + +class FileCard extends StatelessWidget { + final Uri uri; + final FileInfo? info; + final String? filename; + const FileCard(this.uri, this.info, {this.filename, super.key}); + + @override + Widget build(BuildContext context) => SizedBox( + width: 320, + child: Card( + color: Theme.of(context).colorScheme.surfaceContainer, + child: ListTile( + leading: Icon(Icons.file_copy), + title: Text( + filename ?? "file", + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + subtitle: info?.size == null ? null : Text(info!.size!.sizeAsString), + // TODO: Downloading files + trailing: IconButton(onPressed: null, icon: Icon(Icons.download)), + ), + ), + ); +} diff --git a/lib/widgets/renderers/event.dart b/lib/widgets/renderers/event.dart index b2272f3..85b9e92 100644 --- a/lib/widgets/renderers/event.dart +++ b/lib/widgets/renderers/event.dart @@ -26,6 +26,7 @@ import "package:nexus/widgets/loading.dart"; import "package:nexus/widgets/players/video.dart"; import "package:nexus/widgets/players/audio.dart"; import "package:nexus/widgets/renderers/membership.dart"; +import "package:nexus/widgets/file_card.dart"; import "package:timeago/timeago.dart"; import "package:flutter_linkify/flutter_linkify.dart"; @@ -238,8 +239,15 @@ class EventRenderer extends ConsumerWidget { :final info, ) => AudioPlayer(url, info), - // FileMessageContent(:final info) => - // FileRenderer(url, info), + FileMessageContent( + :final info, + :final filename, + ) => + FileCard( + url, + info, + filename: filename, + ), ImageMessageContent(:final info) => ExpandableImage( url.toString(), child: ClipRRect(