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(
|
|
|
|
title: "Attachment #${getTag()}",
|
|
|
|
logLevel: MPVLogLevel.error,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
late final _videoController = VideoController(_videoPlayer);
|
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-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,
|
|
|
|
child: Chip(label: Text(widget.badge!)),
|
|
|
|
)
|
|
|
|
],
|
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
|
|
|
_videoPlayer.open(
|
|
|
|
Media(widget.url),
|
|
|
|
play: false,
|
2024-04-13 11:47:31 +00:00
|
|
|
);
|
|
|
|
|
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-04-17 15:00:53 +00:00
|
|
|
const AttachmentList({super.key, required this.items, required this.provider});
|
2024-04-13 11:47:31 +00:00
|
|
|
|
2024-04-17 15:00:53 +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,
|
2024-04-14 15:39:18 +00:00
|
|
|
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(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|