Solian/lib/widgets/attachments/attachment_list_fullscreen.dart

198 lines
6.9 KiB
Dart
Raw Normal View History

import 'dart:math' as math;
import 'package:dismissible_page/dismissible_page.dart';
2024-05-20 16:02:39 +00:00
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:get/get.dart';
2024-05-20 16:02:39 +00:00
import 'package:solian/models/attachment.dart';
import 'package:solian/widgets/account/account_avatar.dart';
2024-05-22 15:18:01 +00:00
import 'package:solian/widgets/attachments/attachment_item.dart';
2024-05-20 16:02:39 +00:00
2024-05-25 16:11:00 +00:00
class AttachmentListFullScreen extends StatefulWidget {
final String parentId;
2024-05-20 16:02:39 +00:00
final Attachment attachment;
2024-05-25 16:11:00 +00:00
const AttachmentListFullScreen(
{super.key, required this.parentId, required this.attachment});
2024-05-20 16:02:39 +00:00
@override
2024-05-25 16:11:00 +00:00
State<AttachmentListFullScreen> createState() =>
_AttachmentListFullScreenState();
2024-05-20 16:02:39 +00:00
}
2024-05-25 16:11:00 +00:00
class _AttachmentListFullScreenState extends State<AttachmentListFullScreen> {
bool _showDetails = true;
Color get _unFocusColor =>
Theme.of(context).colorScheme.onSurface.withOpacity(0.75);
String _formatBytes(int bytes, {int decimals = 2}) {
if (bytes == 0) return '0 Bytes';
const k = 1024;
final dm = decimals < 0 ? 0 : decimals;
final sizes = [
'Bytes',
'KiB',
'MiB',
'GiB',
'TiB',
'PiB',
'EiB',
'ZiB',
'YiB'
];
final i = (math.log(bytes) / math.log(k)).floor().toInt();
return '${(bytes / math.pow(k, i)).toStringAsFixed(dm)} ${sizes[i]}';
}
2024-05-20 16:02:39 +00:00
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return DismissiblePage(
key: Key('attachment-dismissible${widget.attachment.id}'),
direction: DismissiblePageDismissDirection.vertical,
onDismissed: () => Navigator.pop(context),
dismissThresholds: const {
DismissiblePageDismissDirection.vertical: 0.0,
},
2024-07-27 11:20:53 +00:00
onDragStart: () {
setState(() => _showDetails = false);
},
onDragEnd: () {
setState(() => _showDetails = true);
},
2024-05-20 16:02:39 +00:00
child: GestureDetector(
child: Stack(
fit: StackFit.loose,
children: [
SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: InteractiveViewer(
boundaryMargin: EdgeInsets.zero,
minScale: 1,
maxScale: 16,
2024-07-27 11:20:53 +00:00
panEnabled: true,
scaleEnabled: true,
child: AttachmentItem(
parentId: widget.parentId,
showHideButton: false,
item: widget.attachment,
fit: BoxFit.contain,
),
),
2024-05-20 16:02:39 +00:00
),
Align(
alignment: Alignment.bottomCenter,
2024-07-27 06:16:49 +00:00
child: IgnorePointer(
child: Container(
height: 300,
decoration: BoxDecoration(
2024-07-27 06:16:49 +00:00
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Theme.of(context).colorScheme.surface,
Theme.of(context).colorScheme.surface.withOpacity(0),
],
2024-07-27 06:16:49 +00:00
),
),
),
),
)
.animate(target: _showDetails ? 1 : 0)
.fadeIn(curve: Curves.fastEaseInToSlowEaseOut),
Positioned(
2024-07-27 11:20:53 +00:00
bottom: math.max(MediaQuery.of(context).padding.bottom, 16),
left: 16,
right: 16,
2024-07-27 06:16:49 +00:00
child: IgnorePointer(
child: Material(
color: Colors.transparent,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.attachment.account != null)
Row(
children: [
AccountAvatar(
content: widget.attachment.account!.avatar,
radius: 19,
),
const SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'attachmentUploadBy'.tr,
style: Theme.of(context).textTheme.bodySmall,
),
Text(
widget.attachment.account!.nick,
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
],
),
const SizedBox(height: 4),
Text(
widget.attachment.alt,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 2),
Wrap(
spacing: 6,
children: [
2024-07-27 06:16:49 +00:00
if (widget.attachment.metadata?['width'] != null &&
widget.attachment.metadata?['height'] != null)
Text(
'${widget.attachment.metadata?['width']}x${widget.attachment.metadata?['height']}',
style: TextStyle(
fontSize: 12,
color: _unFocusColor,
),
2024-07-27 06:16:49 +00:00
),
if (widget.attachment.metadata?['ratio'] != null)
Text(
'${(widget.attachment.metadata?['ratio'] as double).toPrecision(2)}',
style: TextStyle(
fontSize: 12,
color: _unFocusColor,
),
),
Text(
2024-07-27 06:16:49 +00:00
_formatBytes(widget.attachment.size),
style: TextStyle(
fontSize: 12,
color: _unFocusColor,
),
2024-07-27 06:16:49 +00:00
)
],
),
],
),
),
),
)
.animate(target: _showDetails ? 1 : 0)
.fadeIn(curve: Curves.fastEaseInToSlowEaseOut),
],
2024-05-20 16:02:39 +00:00
),
onTap: () {
setState(() => _showDetails = !_showDetails);
2024-05-20 16:02:39 +00:00
},
),
);
}
}