Solian/lib/widgets/posts/content/attachment.dart

167 lines
4.2 KiB
Dart
Raw Normal View History

2024-04-13 11:47:31 +00:00
import 'package:flutter/material.dart';
2024-04-17 12:57:25 +00:00
import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart';
2024-04-13 11:47:31 +00:00
import 'package:solian/models/post.dart';
import 'package:solian/utils/service_url.dart';
import 'package:flutter_carousel_widget/flutter_carousel_widget.dart';
import 'package:solian/widgets/posts/attachment_screen.dart';
2024-04-15 15:08:32 +00:00
import 'package:uuid/uuid.dart';
2024-04-13 11:47:31 +00:00
class AttachmentItem extends StatefulWidget {
2024-04-15 15:08:32 +00:00
final int type;
final String url;
final String? tag;
2024-04-13 17:45:27 +00:00
final String? badge;
2024-04-13 11:47:31 +00:00
2024-04-15 15:08:32 +00:00
const AttachmentItem({
super.key,
required this.type,
required this.url,
this.tag,
this.badge,
});
2024-04-13 11:47:31 +00:00
@override
State<AttachmentItem> createState() => _AttachmentItemState();
}
class _AttachmentItemState extends State<AttachmentItem> {
2024-04-15 15:08:32 +00:00
String getTag() => 'attachment-${widget.tag ?? const Uuid().v4()}';
2024-04-13 11:47:31 +00:00
2024-04-17 12:57:25 +00:00
late final _videoPlayer = Player(
configuration: PlayerConfiguration(
2024-05-01 16:49:38 +00:00
title: 'Attachment #${getTag()}',
2024-04-17 12:57:25 +00:00
logLevel: MPVLogLevel.error,
),
);
late final _videoController = VideoController(_videoPlayer);
2024-04-13 11:47:31 +00:00
2024-05-01 09:37:34 +00:00
@override
void initState() {
super.initState();
if (widget.type != 1) {
_videoPlayer.open(
Media(widget.url),
play: false,
);
}
}
2024-04-13 11:47:31 +00:00
@override
Widget build(BuildContext context) {
2024-04-15 15:08:32 +00:00
const borderRadius = Radius.circular(8);
final tag = getTag();
2024-04-13 11:47:31 +00:00
Widget content;
2024-04-15 15:08:32 +00:00
if (widget.type == 1) {
2024-04-13 11:47:31 +00:00
content = GestureDetector(
child: ClipRRect(
borderRadius: const BorderRadius.all(borderRadius),
child: Hero(
2024-04-15 15:08:32 +00:00
tag: tag,
2024-04-13 17:45:27 +00:00
child: Stack(
children: [
Image.network(
2024-04-15 15:08:32 +00:00
widget.url,
2024-05-01 09:37:34 +00:00
key: Key(getTag()),
2024-04-13 17:45:27 +00:00
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
widget.badge == null
? Container()
: Positioned(
right: 12,
bottom: 8,
2024-04-30 12:31:54 +00:00
child: Material(
2024-05-01 09:37:34 +00:00
color: Colors.transparent,
2024-04-30 12:31:54 +00:00
child: Chip(label: Text(widget.badge!)),
),
2024-04-13 17:45:27 +00:00
)
],
2024-04-13 11:47:31 +00:00
),
),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) {
return AttachmentScreen(
2024-04-15 15:08:32 +00:00
tag: tag,
url: widget.url,
2024-04-13 11:47:31 +00:00
);
}),
);
},
);
} else {
2024-04-17 12:57:25 +00:00
content = ClipRRect(
borderRadius: const BorderRadius.all(borderRadius),
child: Video(
controller: _videoController,
key: Key(getTag()),
),
2024-04-13 11:47:31 +00:00
);
}
return Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(borderRadius),
border: Border.all(
color: Theme.of(context).dividerColor,
width: 0.9,
),
),
child: content,
);
}
@override
void dispose() {
2024-04-17 12:57:25 +00:00
_videoPlayer.dispose();
2024-04-13 11:47:31 +00:00
super.dispose();
}
}
class AttachmentList extends StatelessWidget {
final List<Attachment> items;
2024-04-17 15:00:53 +00:00
final String provider;
2024-04-13 11:47:31 +00:00
2024-05-01 09:37:34 +00:00
const AttachmentList(
{super.key, required this.items, required this.provider});
2024-04-13 11:47:31 +00:00
2024-05-01 09:37:34 +00:00
Uri getFileUri(String fileId) =>
getRequestUri(provider, '/api/attachments/o/$fileId');
2024-04-15 15:08:32 +00:00
2024-04-13 11:47:31 +00:00
@override
Widget build(BuildContext context) {
2024-04-13 17:45:27 +00:00
var renderProgress = 0;
2024-04-13 11:47:31 +00:00
return FlutterCarousel(
options: CarouselOptions(
aspectRatio: 16 / 9,
2024-04-13 17:45:27 +00:00
viewportFraction: 1,
showIndicator: false,
2024-04-13 11:47:31 +00:00
),
items: items.map((item) {
2024-04-13 17:45:27 +00:00
renderProgress++;
final badge = '$renderProgress/${items.length}';
2024-04-13 11:47:31 +00:00
return Builder(
builder: (BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
2024-04-13 17:45:27 +00:00
child: AttachmentItem(
2024-04-15 15:08:32 +00:00
type: item.type,
tag: item.fileId,
url: getFileUri(item.fileId).toString(),
badge: items.length <= 1 ? null : badge,
),
2024-04-13 11:47:31 +00:00
);
},
);
}).toList(),
);
}
}