diff --git a/lib/pages/profile.dart b/lib/pages/profile.dart index 345c05b..f970e2d 100644 --- a/lib/pages/profile.dart +++ b/lib/pages/profile.dart @@ -58,6 +58,7 @@ class ProfilePage extends StatelessWidget { TextSpan( style: TextStyle(color: LAYER_5), children: textToSpans( + context, profile.about ?? "", [], profile.pubKey, diff --git a/lib/pages/stream.dart b/lib/pages/stream.dart index 856e029..8bc6fab 100644 --- a/lib/pages/stream.dart +++ b/lib/pages/stream.dart @@ -145,6 +145,7 @@ class _StreamPage extends State with RouteAware { url: stream.info.stream!, placeholder: stream.info.image, aspectRatio: 16 / 9, + isLive: true, ) : (stream.info.image?.isNotEmpty ?? false) ? ProxyImg(url: stream.info.image) diff --git a/lib/widgets/chat_message.dart b/lib/widgets/chat_message.dart index 4c987f7..56c8e90 100644 --- a/lib/widgets/chat_message.dart +++ b/lib/widgets/chat_message.dart @@ -46,7 +46,7 @@ class ChatMessageWidget extends StatelessWidget { spacing: 2, crossAxisAlignment: CrossAxisAlignment.start, children: [ - _chatText(profile), + _chatText(context, profile), /*RxFilter( Key(msg.id), filters: [ @@ -63,7 +63,7 @@ class ChatMessageWidget extends StatelessWidget { }); } - Widget _chatText(Metadata profile) { + Widget _chatText(BuildContext context, Metadata profile) { return RichText( text: TextSpan( children: [ @@ -92,7 +92,13 @@ class ChatMessageWidget extends StatelessWidget { ), ), TextSpan(text: " "), - ...textToSpans(msg.content, msg.tags, msg.pubKey), + ...textToSpans( + context, + msg.content, + msg.tags, + msg.pubKey, + embedMedia: false, + ), ], ), ); diff --git a/lib/widgets/nostr_text.dart b/lib/widgets/nostr_text.dart index 513251c..28ac660 100644 --- a/lib/widgets/nostr_text.dart +++ b/lib/widgets/nostr_text.dart @@ -17,12 +17,14 @@ class NoteText extends StatelessWidget { final Nip01Event event; final bool? embedMedia; final bool? showEmbeds; + final bool? previewMedia; const NoteText({ super.key, required this.event, this.embedMedia, this.showEmbeds, + this.previewMedia, }); @override @@ -34,11 +36,13 @@ class NoteText extends StatelessWidget { return RichText( text: TextSpan( children: textToSpans( + context, event.content, event.tags, event.pubKey, showEmbeds: showEmbeds, embedMedia: embedMedia, + previewMedia: previewMedia, ), ), ); @@ -49,11 +53,13 @@ class NoteText extends StatelessWidget { /// and mentions into multiple spans for rendering /// /// https://github.com/leo-lox/camelus/blob/f58455a0ac07fcc780bdc69b8f4544fd5ea4a46d/lib/presentation_layer/components/note_card/note_card_build_split_content.dart#L262 List textToSpans( + BuildContext context, String content, List> tags, String pubkey, { bool? showEmbeds, bool? embedMedia, + bool? previewMedia, }) { List spans = []; RegExp exp = RegExp( @@ -76,7 +82,14 @@ List textToSpans( } else if (matched.startsWith('#')) { spans.add(_buildHashtagSpan(matched)); } else if (matched.startsWith('http')) { - spans.add(_buildUrlSpan(matched, embedMedia ?? false)); + spans.add( + _buildUrlSpan( + context, + matched, + embedMedia ?? false, + previewMedia ?? true, + ), + ); } else if (matched.startsWith(":") && matched.endsWith(":") && tags.any( @@ -134,22 +147,29 @@ InlineSpan _buildHashtagSpan(String word) { return TextSpan(text: word, style: TextStyle(color: PRIMARY_1)); } -InlineSpan _buildUrlSpan(String url, bool embedMedia) { - if (embedMedia && - (url.endsWith(".jpg") || - url.endsWith(".gif") || - url.endsWith(".jpeg") || - url.endsWith(".webp") || - url.endsWith(".png") || - url.endsWith(".bmp"))) { +InlineSpan _buildUrlSpan( + BuildContext context, + String url, + bool embedMedia, + bool previewMedia, +) { + final isImage = + url.endsWith(".jpg") || + url.endsWith(".gif") || + url.endsWith(".jpeg") || + url.endsWith(".webp") || + url.endsWith(".png") || + url.endsWith(".bmp"); + final isVideo = + url.endsWith(".mp4") || + url.endsWith(".mov") || + url.endsWith(".webm") || + url.endsWith(".mkv") || + url.endsWith(".m3u8"); + if (embedMedia && isImage) { return WidgetSpan(child: ProxyImg(url: url)); } - if (embedMedia && - (url.endsWith(".mp4") || - url.endsWith(".mov") || - url.endsWith(".webm") || - url.endsWith(".mkv") || - url.endsWith(".m3u8"))) { + if (embedMedia && isVideo) { return WidgetSpan( child: AspectRatio( aspectRatio: 16 / 9, @@ -163,7 +183,32 @@ InlineSpan _buildUrlSpan(String url, bool embedMedia) { recognizer: TapGestureRecognizer() ..onTap = () { - launchUrl(Uri.parse(url)); + if (previewMedia) { + showModalBottomSheet( + context: context, + builder: (context) { + return Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: LAYER_1, + borderRadius: DEFAULT_BR, + ), + child: + isImage + ? ProxyImg(url: url) + : AspectRatio( + aspectRatio: 16 / 9, + child: VideoPlayerWidget( + url: url, + autoPlay: false, + ), + ), + ); + }, + ); + } else { + launchUrl(Uri.parse(url)); + } }, ); } diff --git a/lib/widgets/note_embed.dart b/lib/widgets/note_embed.dart index 12756b6..fc43cea 100644 --- a/lib/widgets/note_embed.dart +++ b/lib/widgets/note_embed.dart @@ -45,6 +45,7 @@ class NoteEmbedWidget extends StatelessWidget { }, color: LAYER_3, child: Row( + mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.link, size: 16), ProfileLoaderWidget(author, (context, state) { diff --git a/lib/widgets/stream_info.dart b/lib/widgets/stream_info.dart index ab85cc3..057cf18 100644 --- a/lib/widgets/stream_info.dart +++ b/lib/widgets/stream_info.dart @@ -79,6 +79,7 @@ class StreamInfoWidget extends StatelessWidget { Text.rich( TextSpan( children: textToSpans( + context, stream.info.summary!, [], stream.info.host, diff --git a/lib/widgets/video_player.dart b/lib/widgets/video_player.dart index f040299..73dd646 100644 --- a/lib/widgets/video_player.dart +++ b/lib/widgets/video_player.dart @@ -9,6 +9,7 @@ class VideoPlayerWidget extends StatefulWidget { final String? placeholder; final double? aspectRatio; final bool? autoPlay; + final bool? isLive; const VideoPlayerWidget({ super.key, @@ -16,6 +17,7 @@ class VideoPlayerWidget extends StatefulWidget { this.placeholder, this.aspectRatio, this.autoPlay, + this.isLive, }); @override @@ -38,6 +40,7 @@ class _VideoPlayerWidget extends State { videoPlayerController: _controller, autoPlay: widget.autoPlay ?? true, aspectRatio: widget.aspectRatio, + isLive: widget.isLive ?? false, autoInitialize: true, placeholder: (widget.placeholder?.isNotEmpty ?? false)