feat: Display file description on all file events
This commit is contained in:
parent
a5dc6db4e8
commit
f68a9de6bf
7 changed files with 213 additions and 142 deletions
|
|
@ -4,17 +4,16 @@ import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:flutter_linkify/flutter_linkify.dart';
|
|
||||||
import 'package:just_audio/just_audio.dart';
|
import 'package:just_audio/just_audio.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:opus_caf_converter_dart/opus_caf_converter_dart.dart';
|
import 'package:opus_caf_converter_dart/opus_caf_converter_dart.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/config/app_config.dart';
|
|
||||||
import 'package:fluffychat/config/themes.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/error_reporter.dart';
|
||||||
|
import 'package:fluffychat/utils/file_description.dart';
|
||||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||||
import 'package:fluffychat/utils/url_launcher.dart';
|
|
||||||
import '../../../utils/matrix_sdk_extensions/event_extension.dart';
|
import '../../../utils/matrix_sdk_extensions/event_extension.dart';
|
||||||
|
|
||||||
class AudioPlayerWidget extends StatefulWidget {
|
class AudioPlayerWidget extends StatefulWidget {
|
||||||
|
|
@ -240,17 +239,11 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
|
||||||
final statusText = this.statusText ??= _durationString ?? '00:00';
|
final statusText = this.statusText ??= _durationString ?? '00:00';
|
||||||
final audioPlayer = this.audioPlayer;
|
final audioPlayer = this.audioPlayer;
|
||||||
|
|
||||||
final body = widget.event.content.tryGet<String>('body') ??
|
final fileDescription = widget.event.fileDescription;
|
||||||
widget.event.content.tryGet<String>('filename');
|
|
||||||
final displayBody = body != null &&
|
|
||||||
body.isNotEmpty &&
|
|
||||||
widget.event.content['org.matrix.msc1767.audio'] == null;
|
|
||||||
|
|
||||||
final wavePosition =
|
final wavePosition =
|
||||||
(currentPosition / maxPosition) * AudioPlayerWidget.wavesCount;
|
(currentPosition / maxPosition) * AudioPlayerWidget.wavesCount;
|
||||||
|
|
||||||
final fontSize = 12 * AppConfig.fontSizeFactor;
|
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(12.0),
|
padding: const EdgeInsets.all(12.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
@ -380,22 +373,12 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (displayBody) ...[
|
if (fileDescription != null) ...[
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Linkify(
|
HtmlMessage(
|
||||||
text: body,
|
html: fileDescription,
|
||||||
style: TextStyle(
|
textColor: widget.color,
|
||||||
color: widget.color,
|
room: widget.event.room,
|
||||||
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(),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/config/app_config.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/pages/image_viewer/image_viewer.dart';
|
||||||
|
import 'package:fluffychat/utils/file_description.dart';
|
||||||
import 'package:fluffychat/widgets/mxc_image.dart';
|
import 'package:fluffychat/widgets/mxc_image.dart';
|
||||||
import '../../../widgets/blur_hash.dart';
|
import '../../../widgets/blur_hash.dart';
|
||||||
|
|
||||||
|
|
@ -13,6 +15,7 @@ class ImageBubble extends StatelessWidget {
|
||||||
final BoxFit fit;
|
final BoxFit fit;
|
||||||
final bool maxSize;
|
final bool maxSize;
|
||||||
final Color? backgroundColor;
|
final Color? backgroundColor;
|
||||||
|
final Color? textColor;
|
||||||
final bool thumbnailOnly;
|
final bool thumbnailOnly;
|
||||||
final bool animated;
|
final bool animated;
|
||||||
final double width;
|
final double width;
|
||||||
|
|
@ -34,6 +37,7 @@ class ImageBubble extends StatelessWidget {
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.borderRadius,
|
this.borderRadius,
|
||||||
this.timeline,
|
this.timeline,
|
||||||
|
this.textColor,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -76,35 +80,54 @@ class ImageBubble extends StatelessWidget {
|
||||||
|
|
||||||
final borderRadius =
|
final borderRadius =
|
||||||
this.borderRadius ?? BorderRadius.circular(AppConfig.borderRadius);
|
this.borderRadius ?? BorderRadius.circular(AppConfig.borderRadius);
|
||||||
return Material(
|
|
||||||
color: Colors.transparent,
|
final fileDescription = event.fileDescription;
|
||||||
clipBehavior: Clip.hardEdge,
|
final textColor = this.textColor;
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: borderRadius,
|
return Column(
|
||||||
side: BorderSide(
|
mainAxisSize: MainAxisSize.min,
|
||||||
color: event.messageType == MessageTypes.Sticker
|
spacing: 8,
|
||||||
? Colors.transparent
|
children: [
|
||||||
: theme.dividerColor,
|
Material(
|
||||||
),
|
color: Colors.transparent,
|
||||||
),
|
clipBehavior: Clip.hardEdge,
|
||||||
child: InkWell(
|
shape: RoundedRectangleBorder(
|
||||||
onTap: () => _onTap(context),
|
borderRadius: borderRadius,
|
||||||
borderRadius: borderRadius,
|
side: BorderSide(
|
||||||
child: Hero(
|
color: event.messageType == MessageTypes.Sticker
|
||||||
tag: event.eventId,
|
? Colors.transparent
|
||||||
child: MxcImage(
|
: theme.dividerColor,
|
||||||
event: event,
|
),
|
||||||
width: width,
|
),
|
||||||
height: height,
|
child: InkWell(
|
||||||
fit: fit,
|
onTap: () => _onTap(context),
|
||||||
animated: animated,
|
borderRadius: borderRadius,
|
||||||
isThumbnail: thumbnailOnly,
|
child: Hero(
|
||||||
placeholder: event.messageType == MessageTypes.Sticker
|
tag: event.eventId,
|
||||||
? null
|
child: MxcImage(
|
||||||
: _buildPlaceholder,
|
event: event,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit,
|
||||||
|
animated: animated,
|
||||||
|
isThumbnail: thumbnailOnly,
|
||||||
|
placeholder: event.messageType == MessageTypes.Sticker
|
||||||
|
? null
|
||||||
|
: _buildPlaceholder,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
if (fileDescription != null && textColor != null)
|
||||||
|
SizedBox(
|
||||||
|
width: width,
|
||||||
|
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/config/themes.dart';
|
||||||
import 'package:fluffychat/pages/chat/events/room_creation_state_event.dart';
|
import 'package:fluffychat/pages/chat/events/room_creation_state_event.dart';
|
||||||
import 'package:fluffychat/utils/date_time_extension.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/utils/string_color.dart';
|
||||||
import 'package:fluffychat/widgets/avatar.dart';
|
import 'package:fluffychat/widgets/avatar.dart';
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
|
|
@ -130,6 +131,7 @@ class Message extends StatelessWidget {
|
||||||
MessageTypes.Image,
|
MessageTypes.Image,
|
||||||
MessageTypes.Sticker,
|
MessageTypes.Sticker,
|
||||||
}.contains(event.messageType) &&
|
}.contains(event.messageType) &&
|
||||||
|
event.fileDescription == null &&
|
||||||
!event.redacted) ||
|
!event.redacted) ||
|
||||||
(event.messageType == MessageTypes.Text &&
|
(event.messageType == MessageTypes.Text &&
|
||||||
event.relationshipType == null &&
|
event.relationshipType == null &&
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ class MessageContent extends StatelessWidget {
|
||||||
fit: fit,
|
fit: fit,
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
timeline: timeline,
|
timeline: timeline,
|
||||||
|
textColor: textColor,
|
||||||
);
|
);
|
||||||
case CuteEventContent.eventType:
|
case CuteEventContent.eventType:
|
||||||
return CuteContent(event);
|
return CuteContent(event);
|
||||||
|
|
@ -159,7 +160,7 @@ class MessageContent extends StatelessWidget {
|
||||||
}
|
}
|
||||||
return MessageDownloadContent(event, textColor);
|
return MessageDownloadContent(event, textColor);
|
||||||
case MessageTypes.Video:
|
case MessageTypes.Video:
|
||||||
return EventVideoPlayer(event);
|
return EventVideoPlayer(event, textColor: textColor);
|
||||||
case MessageTypes.File:
|
case MessageTypes.File:
|
||||||
return MessageDownloadContent(event, textColor);
|
return MessageDownloadContent(event, textColor);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:matrix/matrix.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';
|
import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart';
|
||||||
|
|
||||||
class MessageDownloadContent extends StatelessWidget {
|
class MessageDownloadContent extends StatelessWidget {
|
||||||
|
|
@ -21,59 +23,73 @@ class MessageDownloadContent extends StatelessWidget {
|
||||||
?.toUpperCase() ??
|
?.toUpperCase() ??
|
||||||
'UNKNOWN');
|
'UNKNOWN');
|
||||||
final sizeString = event.sizeString;
|
final sizeString = event.sizeString;
|
||||||
return InkWell(
|
final fileDescription = event.fileDescription;
|
||||||
onTap: () => event.saveFile(context),
|
return Column(
|
||||||
child: Column(
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
spacing: 8,
|
||||||
mainAxisSize: MainAxisSize.min,
|
children: [
|
||||||
children: <Widget>[
|
InkWell(
|
||||||
Padding(
|
onTap: () => event.saveFile(context),
|
||||||
padding: const EdgeInsets.all(16.0),
|
child: Column(
|
||||||
child: Row(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
Icon(
|
children: <Widget>[
|
||||||
Icons.file_download_outlined,
|
Padding(
|
||||||
color: textColor,
|
padding: const EdgeInsets.all(16.0),
|
||||||
),
|
child: Row(
|
||||||
const SizedBox(width: 16),
|
children: [
|
||||||
Flexible(
|
Icon(
|
||||||
child: Text(
|
Icons.file_download_outlined,
|
||||||
filename,
|
|
||||||
maxLines: 1,
|
|
||||||
style: TextStyle(
|
|
||||||
color: textColor,
|
color: textColor,
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
const SizedBox(width: 16),
|
||||||
),
|
Flexible(
|
||||||
),
|
child: Text(
|
||||||
],
|
filename,
|
||||||
),
|
maxLines: 1,
|
||||||
),
|
style: TextStyle(
|
||||||
const Divider(height: 1),
|
color: textColor,
|
||||||
Padding(
|
fontWeight: FontWeight.bold,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
|
),
|
||||||
child: Row(
|
overflow: TextOverflow.ellipsis,
|
||||||
children: [
|
),
|
||||||
Text(
|
|
||||||
filetype,
|
|
||||||
style: TextStyle(
|
|
||||||
color: textColor.withAlpha(150),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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:video_player/video_player.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/config/app_config.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/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/localized_exception_extension.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart';
|
||||||
import 'package:fluffychat/utils/platform_infos.dart';
|
import 'package:fluffychat/utils/platform_infos.dart';
|
||||||
|
|
@ -20,7 +22,8 @@ import '../../../utils/error_reporter.dart';
|
||||||
|
|
||||||
class EventVideoPlayer extends StatefulWidget {
|
class EventVideoPlayer extends StatefulWidget {
|
||||||
final Event event;
|
final Event event;
|
||||||
const EventVideoPlayer(this.event, {super.key});
|
final Color? textColor;
|
||||||
|
const EventVideoPlayer(this.event, {this.textColor, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
EventVideoPlayerState createState() => EventVideoPlayerState();
|
EventVideoPlayerState createState() => EventVideoPlayerState();
|
||||||
|
|
@ -102,51 +105,75 @@ class EventVideoPlayerState extends State<EventVideoPlayer> {
|
||||||
final blurHash = (widget.event.infoMap as Map<String, dynamic>)
|
final blurHash = (widget.event.infoMap as Map<String, dynamic>)
|
||||||
.tryGet<String>('xyz.amorgan.blurhash') ??
|
.tryGet<String>('xyz.amorgan.blurhash') ??
|
||||||
fallbackBlurHash;
|
fallbackBlurHash;
|
||||||
|
final fileDescription = widget.event.fileDescription;
|
||||||
|
final textColor = widget.textColor;
|
||||||
|
|
||||||
|
const width = 300.0;
|
||||||
|
|
||||||
final chewieManager = _chewieManager;
|
final chewieManager = _chewieManager;
|
||||||
return Material(
|
return Column(
|
||||||
color: Colors.black,
|
mainAxisSize: MainAxisSize.min,
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
spacing: 8,
|
||||||
child: SizedBox(
|
children: [
|
||||||
height: 300,
|
Material(
|
||||||
child: chewieManager != null
|
color: Colors.black,
|
||||||
? Center(child: Chewie(controller: chewieManager))
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||||
: Stack(
|
child: SizedBox(
|
||||||
children: [
|
height: width,
|
||||||
if (hasThumbnail)
|
child: chewieManager != null
|
||||||
Center(
|
? Center(child: Chewie(controller: chewieManager))
|
||||||
child: ImageBubble(
|
: Stack(
|
||||||
widget.event,
|
children: [
|
||||||
tapToView: false,
|
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,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
else
|
|
||||||
BlurHash(blurhash: blurHash, width: 300, height: 300),
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
if (fileDescription != null && textColor != null)
|
||||||
|
SizedBox(
|
||||||
|
width: width,
|
||||||
|
child: HtmlMessage(
|
||||||
|
html: fileDescription,
|
||||||
|
textColor: textColor,
|
||||||
|
room: widget.event.room,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
lib/utils/file_description.dart
Normal file
19
lib/utils/file_description.dart
Normal file
|
|
@ -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…
Add table
Add a link
Reference in a new issue