1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
| | import 'dart:typed_data';
| |
| | import 'package:flutter/material.dart';
| | import 'package:share_plus/share_plus.dart';
| | import 'package:path_provider/path_provider.dart';
| | import 'dart:io';
| |
| | /// Full-screen zoomable image viewer with share and close controls.
| | class ImageViewer extends StatelessWidget {
| | final Uint8List imageBytes;
| |
| | const ImageViewer({super.key, required this.imageBytes});
| |
| | @override
| | Widget build(BuildContext context) {
| | return Scaffold(
| | backgroundColor: Colors.black,
| | body: SafeArea(
| | child: Stack(
| | children: [
| | // Zoomable image
| | Center(
| | child: InteractiveViewer(
| | minScale: 1.0,
| | maxScale: 5.0,
| | child: Image.memory(
| | imageBytes,
| | fit: BoxFit.contain,
| | ),
| | ),
| | ),
| | // Top bar with actions
| | Positioned(
| | top: 0,
| | left: 0,
| | right: 0,
| | child: Container(
| | padding:
| | const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
| | decoration: BoxDecoration(
| | gradient: LinearGradient(
| | begin: Alignment.topCenter,
| | end: Alignment.bottomCenter,
| | colors: [
| | Colors.black.withAlpha(180),
| | Colors.transparent,
| | ],
| | ),
| | ),
| | child: Row(
| | mainAxisAlignment: MainAxisAlignment.spaceBetween,
| | children: [
| | IconButton(
| | icon: const Icon(Icons.close, color: Colors.white),
| | onPressed: () => Navigator.pop(context),
| | ),
| | Row(
| | children: [
| | IconButton(
| | icon: const Icon(Icons.share, color: Colors.white),
| | onPressed: () => _share(context),
| | ),
| | ],
| | ),
| | ],
| | ),
| | ),
| | ),
| | ],
| | ),
| | ),
| | );
| | }
| |
| | Future<void> _share(BuildContext context) async {
| | try {
| | final dir = await getTemporaryDirectory();
| | final file = File(
| | '${dir.path}/pailot_image_${DateTime.now().millisecondsSinceEpoch}.png');
| | await file.writeAsBytes(imageBytes);
| | await SharePlus.instance.share(
| | ShareParams(files: [XFile(file.path)]),
| | );
| | } catch (e) {
| | if (context.mounted) {
| | ScaffoldMessenger.of(context).showSnackBar(
| | SnackBar(content: Text('Share failed: $e')),
| | );
| | }
| | }
| | }
| | }
|
|