💄 Redesigned attachment zoom view
This commit is contained in:
parent
54c098c274
commit
115cb4adc1
@ -1,5 +1,4 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math' show max;
|
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dismissible_page/dismissible_page.dart';
|
import 'package:dismissible_page/dismissible_page.dart';
|
||||||
@ -48,11 +47,14 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
bool _showOverlay = true;
|
bool _showOverlay = true;
|
||||||
bool _dismissable = true;
|
bool _dismissable = true;
|
||||||
|
|
||||||
|
int _page = 0;
|
||||||
|
|
||||||
void _updatePage() {
|
void _updatePage() {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (_isCompletedDownload) {
|
if (_isCompletedDownload) {
|
||||||
setState(() => _isCompletedDownload = false);
|
setState(() => _isCompletedDownload = false);
|
||||||
}
|
}
|
||||||
|
_page = _pageController.page?.round() ?? 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,31 +224,11 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
BoxDecoration(color: Colors.transparent),
|
BoxDecoration(color: Colors.transparent),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
Positioned(
|
|
||||||
top: max(MediaQuery.of(context).padding.top, 8),
|
|
||||||
left: 14,
|
|
||||||
child: IgnorePointer(
|
|
||||||
ignoring: !_showOverlay,
|
|
||||||
child: IconButton(
|
|
||||||
constraints: const BoxConstraints(),
|
|
||||||
icon: const Icon(Icons.close),
|
|
||||||
style: ButtonStyle(
|
|
||||||
backgroundColor: MaterialStateProperty.all(
|
|
||||||
Theme.of(context).colorScheme.surface.withOpacity(0.5),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
).opacity(_showOverlay ? 1 : 0, animate: true).animate(
|
|
||||||
const Duration(milliseconds: 300), Curves.easeInOut),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
child: IgnorePointer(
|
child: IgnorePointer(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 300,
|
height: 200,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
begin: Alignment.bottomCenter,
|
begin: Alignment.bottomCenter,
|
||||||
@ -269,153 +251,130 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
child: Material(
|
child: Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: Builder(builder: (context) {
|
child: Builder(builder: (context) {
|
||||||
final ud = context.read<UserDirectoryProvider>();
|
return Row(
|
||||||
final item = widget.data.elementAt(
|
|
||||||
widget.data.length > 1
|
|
||||||
? _pageController.page?.round() ?? 0
|
|
||||||
: 0,
|
|
||||||
);
|
|
||||||
final account = ud.getFromCache(item.accountId);
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
if (item.accountId > 0)
|
IconButton(
|
||||||
Row(
|
iconSize: 18,
|
||||||
children: [
|
constraints: const BoxConstraints(),
|
||||||
IgnorePointer(
|
icon: const Icon(Icons.close),
|
||||||
child: AccountImage(
|
style: ButtonStyle(
|
||||||
content: account?.avatar,
|
backgroundColor: MaterialStateProperty.all(
|
||||||
radius: 19,
|
Theme.of(context)
|
||||||
),
|
.colorScheme
|
||||||
),
|
.surface
|
||||||
const Gap(8),
|
.withOpacity(0.5),
|
||||||
Expanded(
|
|
||||||
child: IgnorePointer(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'attachmentUploadBy'.tr(),
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodySmall,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
account?.nick ?? 'unknown'.tr(),
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyMedium,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (widget.data.length > 1)
|
|
||||||
IgnorePointer(
|
|
||||||
child: Text(
|
|
||||||
'${(_pageController.page?.round() ?? 0) + 1}/${widget.data.length}',
|
|
||||||
style: GoogleFonts.robotoMono(fontSize: 13),
|
|
||||||
).padding(right: 8),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
borderRadius:
|
|
||||||
const BorderRadius.all(Radius.circular(16)),
|
|
||||||
onTap: _isDownloading
|
|
||||||
? null
|
|
||||||
: () => _saveToAlbum(widget.data.length > 1
|
|
||||||
? _pageController.page?.round() ?? 0
|
|
||||||
: 0),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.all(6),
|
|
||||||
child: !_isDownloading
|
|
||||||
? !_isCompletedDownload
|
|
||||||
? const Icon(Symbols.save_alt)
|
|
||||||
: const Icon(Symbols.download_done)
|
|
||||||
: SizedBox(
|
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
value: _progressOfDownload,
|
|
||||||
strokeWidth: 3,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Gap(4),
|
|
||||||
IgnorePointer(
|
|
||||||
child: Text(
|
|
||||||
item.alt,
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const Gap(2),
|
IconButton(
|
||||||
IgnorePointer(
|
iconSize: 20,
|
||||||
child: Wrap(
|
constraints: const BoxConstraints(),
|
||||||
spacing: 6,
|
padding: EdgeInsets.zero,
|
||||||
children: [
|
visualDensity: VisualDensity.compact,
|
||||||
if (item.metadata['exif'] == null)
|
icon: const Icon(Symbols.hide).padding(all: 6),
|
||||||
Text(
|
onPressed: () {
|
||||||
'#${item.rid}',
|
setState(() => _showOverlay = false);
|
||||||
style: metaTextStyle,
|
}),
|
||||||
),
|
Expanded(
|
||||||
if (item.metadata['exif']?['Model'] != null)
|
child: IgnorePointer(
|
||||||
Text(
|
child: Builder(builder: (context) {
|
||||||
'attachmentShotOn'.tr(args: [
|
final item = widget.data.elementAt(_page);
|
||||||
item.metadata['exif']?['Model'],
|
final doShowCameraInfo =
|
||||||
]),
|
item.metadata['exif']?['Model'] != null;
|
||||||
style: metaTextStyle,
|
final exif = item.metadata['exif'];
|
||||||
).padding(right: 2),
|
return Column(
|
||||||
if (item.metadata['exif']?['Megapixels'] !=
|
children: [
|
||||||
null &&
|
if (widget.data.length > 1)
|
||||||
item.metadata['exif']?['Model'] != null)
|
Text(
|
||||||
Text(
|
'${_page + 1}/${widget.data.length}',
|
||||||
'${item.metadata['exif']?['Megapixels']}MP',
|
style:
|
||||||
style: metaTextStyle,
|
GoogleFonts.robotoMono(fontSize: 13),
|
||||||
)
|
).padding(right: 8),
|
||||||
else
|
if (doShowCameraInfo)
|
||||||
Text(
|
Text(
|
||||||
item.size.formatBytes(),
|
'attachmentShotOn'
|
||||||
style: metaTextStyle,
|
.tr(args: [exif?['Model']]),
|
||||||
),
|
style: metaTextStyle,
|
||||||
if (item.metadata['width'] != null &&
|
textAlign: TextAlign.center,
|
||||||
item.metadata['height'] != null)
|
),
|
||||||
Text(
|
if (doShowCameraInfo)
|
||||||
'${item.metadata['width']}x${item.metadata['height']}',
|
Row(
|
||||||
style: metaTextStyle,
|
spacing: 4,
|
||||||
),
|
mainAxisSize: MainAxisSize.min,
|
||||||
],
|
children: [
|
||||||
|
if (exif?['Megapixels'] != null)
|
||||||
|
Text(
|
||||||
|
'${exif?['Megapixels']}MP',
|
||||||
|
style: metaTextStyle,
|
||||||
|
),
|
||||||
|
if (exif?['ISO'] != null)
|
||||||
|
Text(
|
||||||
|
'ISO${exif['ISO']}',
|
||||||
|
style: metaTextStyle,
|
||||||
|
),
|
||||||
|
if (exif?['FNumber'] != null)
|
||||||
|
Text(
|
||||||
|
'f/${exif['FNumber']}',
|
||||||
|
style: metaTextStyle,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Gap(4),
|
IconButton(
|
||||||
InkWell(
|
constraints: const BoxConstraints(),
|
||||||
onTap: () {
|
padding: EdgeInsets.zero,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
icon: Container(
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
child: !_isDownloading
|
||||||
|
? !_isCompletedDownload
|
||||||
|
? const Icon(Symbols.save_alt)
|
||||||
|
: const Icon(Symbols.download_done)
|
||||||
|
: SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
backgroundColor: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.surfaceContainerHighest,
|
||||||
|
value: _progressOfDownload,
|
||||||
|
strokeWidth: 3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed:
|
||||||
|
_isDownloading ? null : () => _saveToAlbum(_page),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
iconSize: 18,
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
|
icon: const Icon(Icons.info_outline),
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.all(
|
||||||
|
Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.surface
|
||||||
|
.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
_showDetail = true;
|
_showDetail = true;
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => _AttachmentZoomDetailPopup(
|
builder: (context) => _AttachmentZoomDetailPopup(
|
||||||
data: widget.data.elementAt(
|
data: widget.data.elementAt(_page),
|
||||||
widget.data.length > 1
|
|
||||||
? _pageController.page?.round() ?? 0
|
|
||||||
: 0),
|
|
||||||
),
|
),
|
||||||
).then((_) {
|
).then((_) {
|
||||||
_showDetail = false;
|
_showDetail = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Text(
|
|
||||||
'viewDetailedAttachment'.tr(),
|
|
||||||
style: metaTextStyle.copyWith(
|
|
||||||
decoration: TextDecoration.underline),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -427,18 +386,20 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
if (_showOverlay) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setState(() => _showOverlay = !_showOverlay);
|
setState(() => _showOverlay = !_showOverlay);
|
||||||
},
|
},
|
||||||
onVerticalDragUpdate: (details) {
|
onVerticalDragUpdate: (details) {
|
||||||
if (_showDetail) return;
|
if (_showDetail || !_dismissable) return;
|
||||||
if (details.delta.dy <= -20) {
|
if (details.delta.dy <= -20) {
|
||||||
_showDetail = true;
|
_showDetail = true;
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => _AttachmentZoomDetailPopup(
|
builder: (context) => _AttachmentZoomDetailPopup(
|
||||||
data: widget.data.elementAt(widget.data.length > 1
|
data: widget.data.elementAt(_page),
|
||||||
? _pageController.page?.round() ?? 0
|
|
||||||
: 0),
|
|
||||||
),
|
),
|
||||||
).then((_) {
|
).then((_) {
|
||||||
_showDetail = false;
|
_showDetail = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user