Initial commit
This commit is contained in:
163
lib/pages/chat/events/video_player.dart
Normal file
163
lib/pages/chat/events/video_player.dart
Normal file
@@ -0,0 +1,163 @@
|
||||
// SPDX-FileCopyrightText: 2019-Present Christian Kußowski
|
||||
// SPDX-FileCopyrightText: 2019-Present Contributors to FluffyChat
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:tatchat/config/app_config.dart';
|
||||
import 'package:tatchat/config/setting_keys.dart';
|
||||
import 'package:tatchat/utils/file_description.dart';
|
||||
import 'package:tatchat/utils/matrix_sdk_extensions/event_extension.dart';
|
||||
import 'package:tatchat/utils/platform_infos.dart';
|
||||
import 'package:tatchat/utils/url_launcher.dart';
|
||||
import 'package:tatchat/widgets/blur_hash.dart';
|
||||
import 'package:tatchat/widgets/mxc_image.dart';
|
||||
import 'package:flutter_linkify/flutter_linkify.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import '../../image_viewer/image_viewer.dart';
|
||||
|
||||
class EventVideoPlayer extends StatelessWidget {
|
||||
final Event event;
|
||||
final Timeline? timeline;
|
||||
final Color? textColor;
|
||||
final Color? linkColor;
|
||||
|
||||
const EventVideoPlayer(
|
||||
this.event, {
|
||||
this.timeline,
|
||||
this.textColor,
|
||||
this.linkColor,
|
||||
super.key,
|
||||
});
|
||||
|
||||
static const String fallbackBlurHash = 'L5H2EC=PM+yV0g-mq.wG9c010J}I';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final supportsVideoPlayer = PlatformInfos.supportsVideoPlayer;
|
||||
|
||||
final blurHash =
|
||||
(event.infoMap as Map<String, dynamic>).tryGet<String>(
|
||||
'xyz.amorgan.blurhash',
|
||||
) ??
|
||||
fallbackBlurHash;
|
||||
final fileDescription = event.fileDescription;
|
||||
const maxDimension = 300.0;
|
||||
final infoMap = event.content.tryGetMap<String, Object?>('info');
|
||||
final videoWidth = infoMap?.tryGet<int>('w') ?? maxDimension;
|
||||
final videoHeight = infoMap?.tryGet<int>('h') ?? maxDimension;
|
||||
|
||||
final modifier = max(videoWidth, videoHeight) / maxDimension;
|
||||
final width = videoWidth / modifier;
|
||||
final height = videoHeight / modifier;
|
||||
|
||||
final durationInt = infoMap?.tryGet<int>('duration');
|
||||
final duration = durationInt == null
|
||||
? null
|
||||
: Duration(milliseconds: durationInt);
|
||||
|
||||
return Column(
|
||||
mainAxisSize: .min,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Material(
|
||||
color: Colors.black,
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||
child: InkWell(
|
||||
onTap: () => supportsVideoPlayer
|
||||
? showDialog(
|
||||
context: context,
|
||||
builder: (_) => ImageViewer(
|
||||
event,
|
||||
timeline: timeline,
|
||||
outerContext: context,
|
||||
),
|
||||
)
|
||||
: event.saveFile(context),
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||
child: SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
child: Hero(
|
||||
tag: event.eventId,
|
||||
child: Stack(
|
||||
children: [
|
||||
if (event.hasThumbnail &&
|
||||
AppSettings.showThumbnailsInTimeline.value)
|
||||
MxcImage(
|
||||
event: event,
|
||||
cacheKey: event.transactionId ?? event.eventId,
|
||||
cacheName: event.room.id,
|
||||
isThumbnail: true,
|
||||
width: width,
|
||||
height: height,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (context) => BlurHash(
|
||||
blurhash: blurHash,
|
||||
width: width,
|
||||
height: height,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
)
|
||||
else
|
||||
BlurHash(
|
||||
blurhash: blurHash,
|
||||
width: width,
|
||||
height: height,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Center(
|
||||
child: CircleAvatar(
|
||||
child: supportsVideoPlayer
|
||||
? const Icon(Icons.play_arrow_outlined)
|
||||
: const Icon(Icons.file_download_outlined),
|
||||
),
|
||||
),
|
||||
if (duration != null)
|
||||
Positioned(
|
||||
bottom: 8,
|
||||
left: 16,
|
||||
child: Text(
|
||||
'${duration.inMinutes.toString().padLeft(2, '0')}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
backgroundColor: Colors.black.withAlpha(32),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (fileDescription != null && textColor != null && linkColor != null)
|
||||
SizedBox(
|
||||
width: width,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Linkify(
|
||||
text: fileDescription,
|
||||
textScaleFactor: MediaQuery.textScalerOf(context).scale(1),
|
||||
style: TextStyle(
|
||||
color: textColor,
|
||||
fontSize: AppConfig.messageFontSize,
|
||||
),
|
||||
options: const LinkifyOptions(humanize: false),
|
||||
linkStyle: TextStyle(
|
||||
color: linkColor,
|
||||
fontSize: AppConfig.messageFontSize,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: linkColor,
|
||||
),
|
||||
onOpen: (url) => UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user