Implement mediaplayer and content viewer
This commit is contained in:
parent
dcf3e312cf
commit
bd36e3039e
|
@ -8,8 +8,10 @@ import 'matrix.dart';
|
||||||
class Avatar extends StatelessWidget {
|
class Avatar extends StatelessWidget {
|
||||||
final MxContent mxContent;
|
final MxContent mxContent;
|
||||||
final double size;
|
final double size;
|
||||||
|
final Function onTap;
|
||||||
|
|
||||||
const Avatar(this.mxContent, {this.size = 40, Key key}) : super(key: key);
|
const Avatar(this.mxContent, {this.size = 40, this.onTap, Key key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -19,21 +21,24 @@ class Avatar extends StatelessWidget {
|
||||||
height: size * MediaQuery.of(context).devicePixelRatio,
|
height: size * MediaQuery.of(context).devicePixelRatio,
|
||||||
method: ThumbnailMethod.scale,
|
method: ThumbnailMethod.scale,
|
||||||
);
|
);
|
||||||
return CircleAvatar(
|
return InkWell(
|
||||||
radius: size / 2,
|
onTap: onTap,
|
||||||
backgroundImage: mxContent.mxc?.isNotEmpty ?? false
|
child: CircleAvatar(
|
||||||
? kIsWeb
|
radius: size / 2,
|
||||||
? NetworkImage(
|
backgroundImage: mxContent.mxc?.isNotEmpty ?? false
|
||||||
src,
|
? kIsWeb
|
||||||
)
|
? NetworkImage(
|
||||||
: CachedNetworkImageProvider(
|
src,
|
||||||
src,
|
)
|
||||||
)
|
: CachedNetworkImageProvider(
|
||||||
: null,
|
src,
|
||||||
backgroundColor: Theme.of(context).secondaryHeaderColor,
|
)
|
||||||
child: mxContent.mxc.isEmpty
|
: null,
|
||||||
? Text("@", style: TextStyle(color: Colors.blueGrey))
|
backgroundColor: Theme.of(context).secondaryHeaderColor,
|
||||||
: null,
|
child: mxContent.mxc.isEmpty
|
||||||
|
? Text("@", style: TextStyle(color: Colors.blueGrey))
|
||||||
|
: null,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:fluffychat/utils/app_route.dart';
|
||||||
|
import 'package:fluffychat/views/content_web_view.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -29,27 +31,35 @@ class ContentBanner extends StatelessWidget {
|
||||||
height: bannerSize,
|
height: bannerSize,
|
||||||
method: ThumbnailMethod.scale,
|
method: ThumbnailMethod.scale,
|
||||||
);
|
);
|
||||||
return Container(
|
return InkWell(
|
||||||
height: 200,
|
onTap: () => Navigator.of(context).push(
|
||||||
color: Theme.of(context).secondaryHeaderColor,
|
AppRoute.defaultRoute(
|
||||||
child: !loading
|
context,
|
||||||
? mxContent.mxc?.isNotEmpty ?? false
|
ContentWebView(mxContent),
|
||||||
? kIsWeb
|
),
|
||||||
? Image.network(
|
),
|
||||||
src,
|
child: Container(
|
||||||
height: 200,
|
height: 200,
|
||||||
fit: BoxFit.cover,
|
color: Theme.of(context).secondaryHeaderColor,
|
||||||
)
|
child: !loading
|
||||||
: CachedNetworkImage(
|
? mxContent.mxc?.isNotEmpty ?? false
|
||||||
imageUrl: src,
|
? kIsWeb
|
||||||
height: 200,
|
? Image.network(
|
||||||
fit: BoxFit.cover,
|
src,
|
||||||
placeholder: (c, s) =>
|
height: 200,
|
||||||
Center(child: CircularProgressIndicator()),
|
fit: BoxFit.cover,
|
||||||
errorWidget: (c, s, o) => Icon(Icons.error, size: 200),
|
)
|
||||||
)
|
: CachedNetworkImage(
|
||||||
: Icon(defaultIcon, size: 200)
|
imageUrl: src,
|
||||||
: Icon(defaultIcon, size: 200),
|
height: 200,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
placeholder: (c, s) =>
|
||||||
|
Center(child: CircularProgressIndicator()),
|
||||||
|
errorWidget: (c, s, o) => Icon(Icons.error, size: 200),
|
||||||
|
)
|
||||||
|
: Icon(defaultIcon, size: 200)
|
||||||
|
: Icon(defaultIcon, size: 200),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ import 'package:bubble/bubble.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/dialogs/redact_message_dialog.dart';
|
import 'package:fluffychat/components/dialogs/redact_message_dialog.dart';
|
||||||
import 'package:fluffychat/components/message_content.dart';
|
import 'package:fluffychat/components/message_content.dart';
|
||||||
|
import 'package:fluffychat/utils/app_route.dart';
|
||||||
import 'package:fluffychat/utils/date_time_extension.dart';
|
import 'package:fluffychat/utils/date_time_extension.dart';
|
||||||
|
import 'package:fluffychat/views/content_web_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
@ -26,8 +28,10 @@ class Message extends StatelessWidget {
|
||||||
final bool ownMessage = event.senderId == client.userID;
|
final bool ownMessage = event.senderId == client.userID;
|
||||||
Alignment alignment = ownMessage ? Alignment.topRight : Alignment.topLeft;
|
Alignment alignment = ownMessage ? Alignment.topRight : Alignment.topLeft;
|
||||||
Color color = Theme.of(context).secondaryHeaderColor;
|
Color color = Theme.of(context).secondaryHeaderColor;
|
||||||
final bool sameSender =
|
final bool sameSender = nextEvent != null &&
|
||||||
nextEvent != null ? nextEvent.sender.id == event.sender.id : false;
|
[EventTypes.Message, EventTypes.Sticker].contains(nextEvent.type)
|
||||||
|
? nextEvent.sender.id == event.sender.id
|
||||||
|
: false;
|
||||||
BubbleNip nip = sameSender
|
BubbleNip nip = sameSender
|
||||||
? BubbleNip.no
|
? BubbleNip.no
|
||||||
: ownMessage ? BubbleNip.rightBottom : BubbleNip.leftBottom;
|
: ownMessage ? BubbleNip.rightBottom : BubbleNip.leftBottom;
|
||||||
|
@ -151,8 +155,17 @@ class Message extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
final Widget avatarOrSizedBox =
|
final Widget avatarOrSizedBox = sameSender
|
||||||
sameSender ? SizedBox(width: 40) : Avatar(event.sender.avatarUrl);
|
? SizedBox(width: 40)
|
||||||
|
: Avatar(
|
||||||
|
event.sender.avatarUrl,
|
||||||
|
onTap: () => Navigator.of(context).push(
|
||||||
|
AppRoute.defaultRoute(
|
||||||
|
context,
|
||||||
|
ContentWebView(event.sender.avatarUrl),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
if (ownMessage) {
|
if (ownMessage) {
|
||||||
rowChildren.add(avatarOrSizedBox);
|
rowChildren.add(avatarOrSizedBox);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import 'package:bubble/bubble.dart';
|
import 'package:bubble/bubble.dart';
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:fluffychat/utils/app_route.dart';
|
||||||
|
import 'package:fluffychat/views/content_web_view.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:link_text/link_text.dart';
|
import 'package:link_text/link_text.dart';
|
||||||
|
@ -58,9 +60,11 @@ class MessageContent extends StatelessWidget {
|
||||||
radius: Radius.circular(10),
|
radius: Radius.circular(10),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => launch(
|
onTap: () => Navigator.of(context).push(
|
||||||
MxContent(event.content["url"])
|
AppRoute.defaultRoute(
|
||||||
.getDownloadLink(Matrix.of(context).client),
|
context,
|
||||||
|
ContentWebView(MxContent(event.content["url"])),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: kIsWeb
|
child: kIsWeb
|
||||||
? Image.network(
|
? Image.network(
|
||||||
|
@ -74,8 +78,78 @@ class MessageContent extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
case MessageTypes.Audio:
|
case MessageTypes.Audio:
|
||||||
case MessageTypes.File:
|
if (textOnly) {
|
||||||
|
return Text(
|
||||||
|
"${event.sender.calcDisplayname()} sent an audio message",
|
||||||
|
maxLines: maxLines,
|
||||||
|
style: TextStyle(
|
||||||
|
color: textColor,
|
||||||
|
decoration:
|
||||||
|
event.redacted ? TextDecoration.lineThrough : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Container(
|
||||||
|
width: 200,
|
||||||
|
child: RaisedButton(
|
||||||
|
color: Colors.blueGrey,
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(Icons.play_arrow, color: Colors.white),
|
||||||
|
Text(
|
||||||
|
"Play ${event.body}",
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
softWrap: false,
|
||||||
|
maxLines: 1,
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onPressed: () => Navigator.of(context).push(
|
||||||
|
AppRoute.defaultRoute(
|
||||||
|
context,
|
||||||
|
ContentWebView(MxContent(event.content["url"])),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
case MessageTypes.Video:
|
case MessageTypes.Video:
|
||||||
|
if (textOnly) {
|
||||||
|
return Text(
|
||||||
|
"${event.sender.calcDisplayname()} sent a video message",
|
||||||
|
maxLines: maxLines,
|
||||||
|
style: TextStyle(
|
||||||
|
color: textColor,
|
||||||
|
decoration:
|
||||||
|
event.redacted ? TextDecoration.lineThrough : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Container(
|
||||||
|
width: 200,
|
||||||
|
child: RaisedButton(
|
||||||
|
color: Colors.blueGrey,
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(Icons.play_arrow, color: Colors.white),
|
||||||
|
Text(
|
||||||
|
"Play ${event.body}",
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
softWrap: false,
|
||||||
|
maxLines: 1,
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onPressed: () => Navigator.of(context).push(
|
||||||
|
AppRoute.defaultRoute(
|
||||||
|
context,
|
||||||
|
ContentWebView(MxContent(event.content["url"])),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
case MessageTypes.File:
|
||||||
if (textOnly) {
|
if (textOnly) {
|
||||||
return Text(
|
return Text(
|
||||||
"${event.sender.calcDisplayname()} sent a file",
|
"${event.sender.calcDisplayname()} sent a file",
|
||||||
|
@ -96,6 +170,7 @@ class MessageContent extends StatelessWidget {
|
||||||
overflow: TextOverflow.fade,
|
overflow: TextOverflow.fade,
|
||||||
softWrap: false,
|
softWrap: false,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
onPressed: () => launch(
|
onPressed: () => launch(
|
||||||
MxContent(event.content["url"])
|
MxContent(event.content["url"])
|
||||||
|
|
35
lib/views/content_web_view.dart
Normal file
35
lib/views/content_web_view.dart
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
import 'package:webview_flutter/webview_flutter.dart';
|
||||||
|
|
||||||
|
class ContentWebView extends StatelessWidget {
|
||||||
|
final MxContent content;
|
||||||
|
|
||||||
|
const ContentWebView(this.content);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final String url = content.getDownloadLink(Matrix.of(context).client);
|
||||||
|
print(url);
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(
|
||||||
|
"Content viewer",
|
||||||
|
),
|
||||||
|
actions: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.file_download,
|
||||||
|
),
|
||||||
|
onPressed: () => launch(url),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: WebView(
|
||||||
|
initialUrl: url,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue