feat: Display file description on all file events

pull/1552/head
Krille 7 months ago
parent a5dc6db4e8
commit f68a9de6bf
No known key found for this signature in database
GPG Key ID: E067ECD60F1A0652

@ -4,17 +4,16 @@ import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:just_audio/just_audio.dart';
import 'package:matrix/matrix.dart';
import 'package:opus_caf_converter_dart/opus_caf_converter_dart.dart';
import 'package:path_provider/path_provider.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat/events/html_message.dart';
import 'package:fluffychat/utils/error_reporter.dart';
import 'package:fluffychat/utils/file_description.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:fluffychat/utils/url_launcher.dart';
import '../../../utils/matrix_sdk_extensions/event_extension.dart';
class AudioPlayerWidget extends StatefulWidget {
@ -240,17 +239,11 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
final statusText = this.statusText ??= _durationString ?? '00:00';
final audioPlayer = this.audioPlayer;
final body = widget.event.content.tryGet<String>('body') ??
widget.event.content.tryGet<String>('filename');
final displayBody = body != null &&
body.isNotEmpty &&
widget.event.content['org.matrix.msc1767.audio'] == null;
final fileDescription = widget.event.fileDescription;
final wavePosition =
(currentPosition / maxPosition) * AudioPlayerWidget.wavesCount;
final fontSize = 12 * AppConfig.fontSizeFactor;
return Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
@ -380,22 +373,12 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
],
),
),
if (displayBody) ...[
if (fileDescription != null) ...[
const SizedBox(height: 8),
Linkify(
text: body,
style: TextStyle(
color: widget.color,
fontSize: fontSize,
),
options: const LinkifyOptions(humanize: false),
linkStyle: TextStyle(
color: widget.color.withAlpha(150),
fontSize: fontSize,
decoration: TextDecoration.underline,
decorationColor: widget.color.withAlpha(150),
),
onOpen: (url) => UrlLauncher(context, url.url).launchUrl(),
HtmlMessage(
html: fileDescription,
textColor: widget.color,
room: widget.event.room,
),
],
],

@ -3,7 +3,9 @@ import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pages/chat/events/html_message.dart';
import 'package:fluffychat/pages/image_viewer/image_viewer.dart';
import 'package:fluffychat/utils/file_description.dart';
import 'package:fluffychat/widgets/mxc_image.dart';
import '../../../widgets/blur_hash.dart';
@ -13,6 +15,7 @@ class ImageBubble extends StatelessWidget {
final BoxFit fit;
final bool maxSize;
final Color? backgroundColor;
final Color? textColor;
final bool thumbnailOnly;
final bool animated;
final double width;
@ -34,6 +37,7 @@ class ImageBubble extends StatelessWidget {
this.onTap,
this.borderRadius,
this.timeline,
this.textColor,
super.key,
});
@ -76,35 +80,54 @@ class ImageBubble extends StatelessWidget {
final borderRadius =
this.borderRadius ?? BorderRadius.circular(AppConfig.borderRadius);
return Material(
color: Colors.transparent,
clipBehavior: Clip.hardEdge,
shape: RoundedRectangleBorder(
borderRadius: borderRadius,
side: BorderSide(
color: event.messageType == MessageTypes.Sticker
? Colors.transparent
: theme.dividerColor,
final fileDescription = event.fileDescription;
final textColor = this.textColor;
return Column(
mainAxisSize: MainAxisSize.min,
spacing: 8,
children: [
Material(
color: Colors.transparent,
clipBehavior: Clip.hardEdge,
shape: RoundedRectangleBorder(
borderRadius: borderRadius,
side: BorderSide(
color: event.messageType == MessageTypes.Sticker
? Colors.transparent
: theme.dividerColor,
),
),
child: InkWell(
onTap: () => _onTap(context),
borderRadius: borderRadius,
child: Hero(
tag: event.eventId,
child: MxcImage(
event: event,
width: width,
height: height,
fit: fit,
animated: animated,
isThumbnail: thumbnailOnly,
placeholder: event.messageType == MessageTypes.Sticker
? null
: _buildPlaceholder,
),
),
),
),
),
child: InkWell(
onTap: () => _onTap(context),
borderRadius: borderRadius,
child: Hero(
tag: event.eventId,
child: MxcImage(
event: event,
if (fileDescription != null && textColor != null)
SizedBox(
width: width,
height: height,
fit: fit,
animated: animated,
isThumbnail: thumbnailOnly,
placeholder: event.messageType == MessageTypes.Sticker
? null
: _buildPlaceholder,
child: HtmlMessage(
html: fileDescription,
textColor: textColor,
room: event.room,
),
),
),
),
],
);
}
}

@ -8,6 +8,7 @@ import 'package:swipe_to_action/swipe_to_action.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat/events/room_creation_state_event.dart';
import 'package:fluffychat/utils/date_time_extension.dart';
import 'package:fluffychat/utils/file_description.dart';
import 'package:fluffychat/utils/string_color.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/matrix.dart';
@ -130,6 +131,7 @@ class Message extends StatelessWidget {
MessageTypes.Image,
MessageTypes.Sticker,
}.contains(event.messageType) &&
event.fileDescription == null &&
!event.redacted) ||
(event.messageType == MessageTypes.Text &&
event.relationshipType == null &&

@ -140,6 +140,7 @@ class MessageContent extends StatelessWidget {
fit: fit,
borderRadius: borderRadius,
timeline: timeline,
textColor: textColor,
);
case CuteEventContent.eventType:
return CuteContent(event);
@ -159,7 +160,7 @@ class MessageContent extends StatelessWidget {
}
return MessageDownloadContent(event, textColor);
case MessageTypes.Video:
return EventVideoPlayer(event);
return EventVideoPlayer(event, textColor: textColor);
case MessageTypes.File:
return MessageDownloadContent(event, textColor);

@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/pages/chat/events/html_message.dart';
import 'package:fluffychat/utils/file_description.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart';
class MessageDownloadContent extends StatelessWidget {
@ -21,59 +23,73 @@ class MessageDownloadContent extends StatelessWidget {
?.toUpperCase() ??
'UNKNOWN');
final sizeString = event.sizeString;
return InkWell(
onTap: () => event.saveFile(context),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Icon(
Icons.file_download_outlined,
color: textColor,
),
const SizedBox(width: 16),
Flexible(
child: Text(
filename,
maxLines: 1,
style: TextStyle(
final fileDescription = event.fileDescription;
return Column(
mainAxisSize: MainAxisSize.min,
spacing: 8,
children: [
InkWell(
onTap: () => event.saveFile(context),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Icon(
Icons.file_download_outlined,
color: textColor,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
),
const Divider(height: 1),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
child: Row(
children: [
Text(
filetype,
style: TextStyle(
color: textColor.withAlpha(150),
),
const SizedBox(width: 16),
Flexible(
child: Text(
filename,
maxLines: 1,
style: TextStyle(
color: textColor,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
),
),
],
),
const Spacer(),
if (sizeString != null)
Text(
sizeString,
style: TextStyle(
color: textColor.withAlpha(150),
),
const Divider(height: 1),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
child: Row(
children: [
Text(
filetype,
style: TextStyle(
color: textColor.withAlpha(150),
),
),
),
],
),
const Spacer(),
if (sizeString != null)
Text(
sizeString,
style: TextStyle(
color: textColor.withAlpha(150),
),
),
],
),
),
],
),
),
if (fileDescription != null)
HtmlMessage(
html: fileDescription,
textColor: textColor,
room: event.room,
),
],
),
],
);
}
}

@ -11,7 +11,9 @@ import 'package:universal_html/html.dart' as html;
import 'package:video_player/video_player.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pages/chat/events/html_message.dart';
import 'package:fluffychat/pages/chat/events/image_bubble.dart';
import 'package:fluffychat/utils/file_description.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart';
import 'package:fluffychat/utils/platform_infos.dart';
@ -20,7 +22,8 @@ import '../../../utils/error_reporter.dart';
class EventVideoPlayer extends StatefulWidget {
final Event event;
const EventVideoPlayer(this.event, {super.key});
final Color? textColor;
const EventVideoPlayer(this.event, {this.textColor, super.key});
@override
EventVideoPlayerState createState() => EventVideoPlayerState();
@ -102,51 +105,75 @@ class EventVideoPlayerState extends State<EventVideoPlayer> {
final blurHash = (widget.event.infoMap as Map<String, dynamic>)
.tryGet<String>('xyz.amorgan.blurhash') ??
fallbackBlurHash;
final fileDescription = widget.event.fileDescription;
final textColor = widget.textColor;
const width = 300.0;
final chewieManager = _chewieManager;
return Material(
color: Colors.black,
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
child: SizedBox(
height: 300,
child: chewieManager != null
? Center(child: Chewie(controller: chewieManager))
: Stack(
children: [
if (hasThumbnail)
Center(
child: ImageBubble(
widget.event,
tapToView: false,
),
)
else
BlurHash(blurhash: blurHash, width: 300, height: 300),
Center(
child: IconButton(
style: IconButton.styleFrom(
backgroundColor: theme.colorScheme.surface,
return Column(
mainAxisSize: MainAxisSize.min,
spacing: 8,
children: [
Material(
color: Colors.black,
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
child: SizedBox(
height: width,
child: chewieManager != null
? Center(child: Chewie(controller: chewieManager))
: Stack(
children: [
if (hasThumbnail)
Center(
child: ImageBubble(
widget.event,
tapToView: false,
textColor: widget.textColor,
),
)
else
BlurHash(
blurhash: blurHash,
width: width,
height: width,
),
Center(
child: IconButton(
style: IconButton.styleFrom(
backgroundColor: theme.colorScheme.surface,
),
icon: _isDownloading
? const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator.adaptive(
strokeWidth: 2,
),
)
: const Icon(Icons.play_circle_outlined),
tooltip: _isDownloading
? L10n.of(context).loadingPleaseWait
: L10n.of(context).videoWithSize(
widget.event.sizeString ?? '?MB',
),
onPressed: _isDownloading ? null : _downloadAction,
),
),
icon: _isDownloading
? const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator.adaptive(
strokeWidth: 2,
),
)
: const Icon(Icons.play_circle_outlined),
tooltip: _isDownloading
? L10n.of(context).loadingPleaseWait
: L10n.of(context).videoWithSize(
widget.event.sizeString ?? '?MB',
),
onPressed: _isDownloading ? null : _downloadAction,
),
],
),
],
),
),
),
),
if (fileDescription != null && textColor != null)
SizedBox(
width: width,
child: HtmlMessage(
html: fileDescription,
textColor: textColor,
room: widget.event.room,
),
),
],
);
}
}

@ -0,0 +1,19 @@
import 'package:matrix/matrix.dart';
extension FileDescriptionExtension on Event {
String? get fileDescription {
if (!{
MessageTypes.File,
MessageTypes.Image,
}.contains(messageType)) {
return null;
}
final formattedBody = content.tryGet<String>('formatted_body');
if (formattedBody != null) return formattedBody;
final filename = content.tryGet<String>('filename');
final body = content.tryGet<String>('body');
if (filename != body && body != null) return body;
return null;
}
}
Loading…
Cancel
Save