1+ import 'dart:convert' ;
2+ import 'package:file_selector_platform_interface/file_selector_platform_interface.dart' ;
3+ import 'package:cookethflow/core/helpers/platform_file_helper.dart' ;
4+ import 'package:flutter/foundation.dart' ;
5+ import 'package:universal_html/html.dart' as html;
6+
7+ class FileServices {
8+ final FileSelectorPlatform fileSelector = FileSelectorPlatform .instance;
9+
10+ Future <String > exportFile ({
11+ required String defaultName,
12+ required String jsonString,
13+ }) async {
14+ try {
15+ // Ensure the default name ends with .json
16+ final sanitizedName = defaultName.toLowerCase ().endsWith ('.json' )
17+ ? defaultName
18+ : '$defaultName .json' ;
19+
20+ if (kIsWeb) {
21+ // Web: Use browser download API
22+ final bytes = Uint8List .fromList (utf8.encode (jsonString));
23+ final blob = html.Blob ([bytes], 'application/json' );
24+ final url = html.Url .createObjectUrlFromBlob (blob);
25+ final anchor = html.AnchorElement (href: url)
26+ ..setAttribute ('download' , sanitizedName)
27+ ..click ();
28+ html.Url .revokeObjectUrl (url);
29+ return 'success' ;
30+ } else {
31+ // Desktop: Use file_selector
32+ const XTypeGroup typeGroup = XTypeGroup (
33+ label: 'JSON' ,
34+ extensions: ['json' ],
35+ mimeTypes: ['application/json' ],
36+ );
37+
38+ final String ? path = await fileSelector.getSavePath (
39+ acceptedTypeGroups: [typeGroup],
40+ suggestedName: sanitizedName,
41+ );
42+
43+ if (path == null ) {
44+ return 'Save operation cancelled' ;
45+ }
46+
47+ // Ensure the selected path ends with .json
48+ final String savePath =
49+ path.toLowerCase ().endsWith ('.json' ) ? path : '$path .json' ;
50+
51+ final XFile file = XFile .fromData (
52+ Uint8List .fromList (utf8.encode (jsonString)),
53+ mimeType: 'application/json' ,
54+ name: savePath.split ('/' ).last,
55+ );
56+
57+ await file.saveTo (savePath);
58+ return 'success' ;
59+ }
60+ } catch (e) {
61+ return e.toString ();
62+ }
63+ }
64+
65+ Future <String > exportPNG ({
66+ required String defaultName,
67+ required Uint8List pngBytes,
68+ }) async {
69+ try {
70+ // Ensure the default name ends with .png
71+ final sanitizedName = defaultName.toLowerCase ().endsWith ('.png' )
72+ ? defaultName
73+ : '$defaultName .png' ;
74+
75+ if (kIsWeb) {
76+ // Web: Use browser download API
77+ final blob = html.Blob ([pngBytes], 'image/png' );
78+ final url = html.Url .createObjectUrlFromBlob (blob);
79+ final anchor = html.AnchorElement (href: url)
80+ ..setAttribute ('download' , sanitizedName)
81+ ..click ();
82+ html.Url .revokeObjectUrl (url);
83+ return 'success' ;
84+ } else {
85+ // Desktop: Use file_selector
86+ const XTypeGroup typeGroup = XTypeGroup (
87+ label: 'PNG Images' ,
88+ extensions: ['png' ],
89+ mimeTypes: ['image/png' ],
90+ );
91+
92+ final String ? path = await fileSelector.getSavePath (
93+ acceptedTypeGroups: [typeGroup],
94+ suggestedName: sanitizedName,
95+ );
96+
97+ if (path == null ) {
98+ return 'Save operation cancelled' ;
99+ }
100+
101+ // Ensure the selected path ends with .png
102+ final String savePath =
103+ path.toLowerCase ().endsWith ('.png' ) ? path : '$path .png' ;
104+
105+ final XFile file = XFile .fromData (
106+ pngBytes,
107+ mimeType: 'image/png' ,
108+ name: savePath.split ('/' ).last,
109+ );
110+
111+ await file.saveTo (savePath);
112+ return 'success' ;
113+ }
114+ } catch (e) {
115+ return e.toString ();
116+ }
117+ }
118+
119+ Future <String > exportSVG ({
120+ required String defaultName,
121+ required String svgString,
122+ }) async {
123+ try {
124+ // Ensure the default name ends with .svg
125+ final sanitizedName = defaultName.toLowerCase ().endsWith ('.svg' )
126+ ? defaultName
127+ : '$defaultName .svg' ;
128+
129+ if (kIsWeb) {
130+ // Web: Use browser download API
131+ final bytes = Uint8List .fromList (utf8.encode (svgString));
132+ final blob = html.Blob ([bytes], 'image/svg+xml' );
133+ final url = html.Url .createObjectUrlFromBlob (blob);
134+ final anchor = html.AnchorElement (href: url)
135+ ..setAttribute ('download' , sanitizedName)
136+ ..click ();
137+ html.Url .revokeObjectUrl (url);
138+ return 'success' ;
139+ } else {
140+ // Desktop: Use file_selector
141+ const XTypeGroup typeGroup = XTypeGroup (
142+ label: 'SVG Images' ,
143+ extensions: ['svg' ],
144+ mimeTypes: ['image/svg+xml' ],
145+ );
146+
147+ final String ? path = await fileSelector.getSavePath (
148+ acceptedTypeGroups: [typeGroup],
149+ suggestedName: sanitizedName,
150+ );
151+
152+ if (path == null ) {
153+ return 'Save operation cancelled' ;
154+ }
155+
156+ // Ensure the selected path ends with .svg
157+ final String savePath =
158+ path.toLowerCase ().endsWith ('.svg' ) ? path : '$path .svg' ;
159+
160+ final XFile file = XFile .fromData (
161+ Uint8List .fromList (utf8.encode (svgString)),
162+ mimeType: 'image/svg+xml' ,
163+ name: savePath.split ('/' ).last,
164+ );
165+
166+ await file.saveTo (savePath);
167+ return 'success' ;
168+ }
169+ } catch (e) {
170+ return e.toString ();
171+ }
172+ }
173+
174+ // For importing files
175+ Future <Map <String , dynamic >?> importJsonFile (Uint8List fileData) async {
176+ return await PlatformFileService .parseJSONFile (fileData);
177+ }
178+
179+ Future <Map <String , dynamic >?> pickAndReadJsonFile () async {
180+ return await PlatformFileService .pickJSONFile ();
181+ }
182+
183+ Future <XFile ?> selectImages () async {
184+ const XTypeGroup typeGroup = XTypeGroup (
185+ label: 'Images' ,
186+ mimeTypes: ['image/*' ],
187+ );
188+
189+ try {
190+ final XFile ? file =
191+ await fileSelector.openFile (acceptedTypeGroups: [typeGroup]);
192+
193+ if (file != null ) {
194+ print ('Selected file: ${file .path }' );
195+ }
196+ return file;
197+ } catch (e) {
198+ print ('Error selecting file: $e ' );
199+ return null ;
200+ }
201+ }
202+
203+ Future <XFile ?> importJsonFiles () async {
204+ const XTypeGroup typeGroup = XTypeGroup (
205+ label: 'JSON' ,
206+ mimeTypes: ['application/json' ],
207+ extensions: ['json' ],
208+ );
209+
210+ try {
211+ final XFile ? file =
212+ await fileSelector.openFile (acceptedTypeGroups: [typeGroup]);
213+ if (file != null ) {
214+ print ('Selected file: ${file .path }' );
215+ }
216+ return file;
217+ } catch (e) {
218+ print ('Error in selecting file: $e ' );
219+ return null ;
220+ }
221+ }
222+ }
0 commit comments