creek
The AI Image Editor of 2030git clone https://github.com/maydayv7/creek
lib/ui/pages/share_handler_page.dart (5475B)
1import 'dart:io';
2import 'package:flutter/material.dart';
3import 'package:creekui/services/download_service.dart';
4import 'package:creekui/services/instagram_download_service.dart';
5import 'package:creekui/services/image_service.dart';
6import 'package:creekui/ui/styles/variables.dart';
7import 'package:creekui/ui/widgets/primary_button.dart';
8import 'package:creekui/ui/widgets/app_bar.dart';
9import 'share_to_moodboard_page.dart';
10import 'share_to_file_page.dart';
11
12class ShareHandlerPage extends StatefulWidget {
13 final String sharedText;
14 final String destination;
15
16 const ShareHandlerPage({
17 super.key,
18 required this.sharedText,
19 required this.destination,
20 });
21
22 @override
23 State<ShareHandlerPage> createState() => _ShareHandlerPageState();
24}
25
26class _ShareHandlerPageState extends State<ShareHandlerPage> {
27 final _downloadService = DownloadService();
28 final _instagramService = InstagramDownloadService();
29 final _imageService = ImageService();
30
31 bool _hasError = false;
32 String? _errorMessage;
33
34 @override
35 void initState() {
36 super.initState();
37 _processSharedContent();
38 }
39
40 Future<void> _processSharedContent() async {
41 final sharedContent = widget.sharedText.trim();
42 List<File> tempFiles = [];
43
44 try {
45 // CASE A: Local File Path
46 if (await File(sharedContent).exists()) {
47 tempFiles.add(File(sharedContent));
48 }
49 // CASE B: URL
50 else {
51 final urlRegExp = RegExp(r'(https?://\S+)');
52 final match = urlRegExp.firstMatch(sharedContent);
53
54 if (match != null) {
55 final url = match.group(0)!;
56 if (url.contains('instagram.com')) {
57 // Instagram Logic
58 final downloadedPaths = await _instagramService
59 .downloadInstagramImage(url);
60 if (downloadedPaths != null && downloadedPaths.isNotEmpty) {
61 tempFiles.addAll(downloadedPaths.map((path) => File(path)));
62 }
63 } else {
64 // Generic Download Logic
65 final savedPath = await _downloadService.downloadAndSaveImage(url);
66 if (savedPath != null) {
67 tempFiles.add(File(savedPath));
68 }
69 }
70 } else {
71 throw Exception("Invalid content: Not a valid file path or URL.");
72 }
73 }
74
75 // Success: Route based on Destination
76 if (tempFiles.isNotEmpty) {
77 if (!mounted) return;
78 if (widget.destination == 'files') {
79 // Files
80 Navigator.pushReplacement(
81 context,
82 MaterialPageRoute(
83 builder: (_) => ShareToFilePage(sharedImage: tempFiles.first),
84 ),
85 );
86 } else {
87 // Moodboard
88 List<File> permanentFiles = [];
89 for (var file in tempFiles) {
90 final id = await _imageService.saveImage(file, 0, tags: []);
91 final savedImage = await _imageService.getImage(id);
92 if (savedImage != null) {
93 permanentFiles.add(File(savedImage.filePath));
94 }
95 }
96 if (mounted) {
97 Navigator.pushReplacement(
98 context,
99 MaterialPageRoute(
100 builder:
101 (_) => ShareToMoodboardPage(imageFiles: permanentFiles),
102 ),
103 );
104 }
105 }
106 } else {
107 throw Exception("Could not retrieve any media files.");
108 }
109 } catch (e) {
110 if (mounted) {
111 setState(() {
112 _hasError = true;
113 _errorMessage = e.toString();
114 });
115 }
116 }
117 }
118
119 @override
120 Widget build(BuildContext context) {
121 return Scaffold(
122 backgroundColor: Variables.background,
123 appBar: const CommonAppBar(title: "Processing", showBack: false),
124 body: Center(
125 child:
126 _hasError
127 ? Padding(
128 padding: const EdgeInsets.all(24.0),
129 child: Column(
130 mainAxisAlignment: MainAxisAlignment.center,
131 children: [
132 const Icon(
133 Icons.error_outline,
134 color: Colors.red,
135 size: 50,
136 ),
137 const SizedBox(height: 16),
138 Text(
139 "Error processing media",
140 style: Variables.headerStyle.copyWith(fontSize: 18),
141 ),
142 const SizedBox(height: 8),
143 Text(
144 _errorMessage ?? "Unknown Error",
145 textAlign: TextAlign.center,
146 style: const TextStyle(color: Colors.grey),
147 ),
148 const SizedBox(height: 24),
149 SizedBox(
150 width: 200,
151 child: PrimaryButton(
152 text: "Close",
153 onPressed: () => Navigator.pop(context),
154 ),
155 ),
156 ],
157 ),
158 )
159 : const Column(
160 mainAxisAlignment: MainAxisAlignment.center,
161 children: [
162 CircularProgressIndicator(color: Variables.textPrimary),
163 SizedBox(height: 20),
164 Text("Downloading media..."),
165 ],
166 ),
167 ),
168 );
169 }
170}