relatica/lib/screens/image_viewer_screen.dart

154 wiersze
4.7 KiB
Dart

import 'dart:io';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import '../controls/login_aware_cached_network_image.dart';
import '../friendica_client/friendica_client.dart';
import '../globals.dart';
import '../models/media_attachment.dart';
import '../services/auth_service.dart';
import '../utils/clipboard_utils.dart';
import '../utils/snackbar_builder.dart';
class ImageViewerScreen extends StatefulWidget {
final List<MediaAttachment> attachments;
final int initialIndex;
const ImageViewerScreen({
super.key,
required this.attachments,
this.initialIndex = 0,
});
@override
State<ImageViewerScreen> createState() => _ImageViewerScreenState();
}
class _ImageViewerScreenState extends State<ImageViewerScreen> {
MediaAttachment? currentAttachment;
@override
void initState() {
super.initState();
currentAttachment = widget.attachments[widget.initialIndex];
}
Future<void> saveImage(
BuildContext context,
MediaAttachment attachment,
) async {
buildSnackbar(context, 'Downloading full image to save locally');
final appsDir = await getApplicationDocumentsDirectory();
final filename = p.basename(attachment.fullFileUri.path);
final bytesResult =
await RemoteFileClient(getIt<AccountsService>().currentProfile)
.getFileBytes(attachment.uri);
if (bytesResult.isFailure && mounted) {
buildSnackbar(context,
'Error getting full size version of file: ${bytesResult.error}');
return;
}
if (Platform.isAndroid || Platform.isIOS) {
final params = SaveFileDialogParams(
data: bytesResult.value,
fileName: filename,
);
await FlutterFileDialog.saveFile(params: params);
} else {
final location = await FilePicker.platform.saveFile(
dialogTitle: 'Save Image',
fileName: filename,
initialDirectory: appsDir.path,
);
if (location != null) {
await File(location).writeAsBytes(bytesResult.value);
}
}
}
@override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
final carouselHeight =
widget.attachments.length == 1 ? height * 0.9 : height * 0.8;
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
onPressed: currentAttachment == null
? null
: () => saveImage(context, currentAttachment!),
icon: const Icon(Icons.download))
],
),
body: SafeArea(
child: Column(
children: [
CarouselSlider.builder(
disableGesture: true,
itemCount: widget.attachments.length,
itemBuilder: (context, index, realIndex) {
return SizedBox(
width: width,
height: carouselHeight,
child: InteractiveViewer(
maxScale: 10.0,
scaleFactor: 400,
child: LoginAwareCachedNetworkImage(
imageUrl: widget.attachments[index].uri.toString()),
),
);
},
options: CarouselOptions(
height: carouselHeight,
initialPage: widget.initialIndex,
enableInfiniteScroll: false,
enlargeCenterPage: true,
viewportFraction: 0.95,
onPageChanged: (index, reason) {
setState(() {
currentAttachment = widget.attachments[index];
});
}),
),
if (currentAttachment != null) buildTextArea(currentAttachment!),
],
),
),
);
}
Widget buildTextArea(MediaAttachment attachment) {
return Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: SingleChildScrollView(
child: Text(attachment.description),
)),
IconButton(
onPressed: () async {
await copyToClipboard(
context: context,
text: attachment.description,
message: 'Image description copied to clipboard');
},
icon: Icon(Icons.copy),
),
],
),
),
);
}
}