Skip to content

Commit

Permalink
content: Implement inline video preview
Browse files Browse the repository at this point in the history
Fixes: #356
  • Loading branch information
rajveermalviya authored and gnprice committed May 10, 2024
1 parent 9806c5a commit d5ece54
Show file tree
Hide file tree
Showing 6 changed files with 494 additions and 20 deletions.
4 changes: 4 additions & 0 deletions assets/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,10 @@
"httpStatus": {"type": "int", "example": "500"}
}
},
"errorVideoPlayerFailed": "Unable to play the video",
"@errorVideoPlayerFailed": {
"description": "Error message when a video fails to play."
},
"serverUrlValidationErrorEmpty": "Please enter a URL.",
"@serverUrlValidationErrorEmpty": {
"description": "Error message when URL is empty"
Expand Down
44 changes: 36 additions & 8 deletions lib/widgets/content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,7 @@ class BlockContentList extends StatelessWidget {
);
return MessageImage(node: node);
} else if (node is InlineVideoNode) {
return Text.rich(
TextSpan(children: [
const TextSpan(text: "(unimplemented:", style: errorStyle),
TextSpan(text: node.debugHtmlText, style: errorCodeStyle),
const TextSpan(text: ")", style: errorStyle),
]),
style: errorStyle);
return MessageInlineVideo(node: node);
} else if (node is EmbedVideoNode) {
return MessageEmbedVideo(node: node);
} else if (node is UnimplementedBlockContentNode) {
Expand Down Expand Up @@ -387,7 +381,10 @@ class MessageImage extends StatelessWidget {
return MessageMediaContainer(
onTap: resolvedSrc == null ? null : () { // TODO(log)
Navigator.of(context).push(getLightboxRoute(
context: context, message: message, src: resolvedSrc));
context: context,
message: message,
src: resolvedSrc,
mediaType: MediaType.image));
},
child: resolvedSrc == null ? null : LightboxHero(
message: message,
Expand All @@ -398,6 +395,37 @@ class MessageImage extends StatelessWidget {
}
}

class MessageInlineVideo extends StatelessWidget {
const MessageInlineVideo({super.key, required this.node});

final InlineVideoNode node;

@override
Widget build(BuildContext context) {
final message = InheritedMessage.of(context);
final store = PerAccountStoreWidget.of(context);
final resolvedSrc = store.tryResolveUrl(node.srcUrl);

return MessageMediaContainer(
onTap: resolvedSrc == null ? null : () { // TODO(log)
Navigator.of(context).push(getLightboxRoute(
context: context,
message: message,
src: resolvedSrc,
mediaType: MediaType.video));
},
child: Container(
color: Colors.black,
alignment: Alignment.center,
// To avoid potentially confusing UX, do not show play icon as
// we also disable onTap above.
child: resolvedSrc == null ? null : const Icon( // TODO(log)
Icons.play_arrow_rounded,
color: Colors.white,
size: 32)));
}
}

class MessageEmbedVideo extends StatelessWidget {
const MessageEmbedVideo({super.key, required this.node});

Expand Down
5 changes: 4 additions & 1 deletion lib/widgets/dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@ Future<void> showErrorDialog({
required BuildContext context,
required String title,
String? message,
bool barrierDismissible = true,
VoidCallback? onContinue,
}) {
final zulipLocalizations = ZulipLocalizations.of(context);
return showDialog(
context: context,
barrierDismissible: barrierDismissible,
builder: (BuildContext context) => AlertDialog(
title: Text(title),
content: message != null ? SingleChildScrollView(child: Text(message)) : null,
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
onPressed: onContinue ?? () => Navigator.pop(context),
child: _dialogActionText(zulipLocalizations.errorDialogContinue)),
]));
}
Expand Down
Loading

0 comments on commit d5ece54

Please sign in to comment.