import 'dart:io' show File; import 'package:flutter/foundation.dart' show Uint8List; import 'package:gal/gal.dart'; import 'package:http/http.dart' as http; // I would like to orgnize the project structure and the code more // but here I don't want to change too much since that is a community project RegExp _base64 = RegExp( r'^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$', ); bool isBase64(String str) { return _base64.hasMatch(str); } bool isHttpBasedUrl(String url) { try { final uri = Uri.parse(url.trim()); return uri.isScheme('HTTP') || uri.isScheme('HTTPS'); } catch (_) { return false; } } bool isYouTubeUrl(String videoUrl) { try { final uri = Uri.parse(videoUrl); return uri.host == 'www.youtube.com' || uri.host == 'youtube.com' || uri.host == 'youtu.be'; } catch (_) { return false; } } bool isImageBase64(String imageUrl) { return !isHttpBasedUrl(imageUrl) && isBase64(imageUrl); } enum SaveImageResultMethod { network, localStorage } class _SaveImageResult { const _SaveImageResult({required this.isSuccess, required this.method}); final bool isSuccess; final SaveImageResultMethod method; } Future<_SaveImageResult> saveImage(String imageUrl) async { final imageFile = File(imageUrl); final hasPermission = await Gal.hasAccess(); final imageExistsLocally = await imageFile.exists(); if (!hasPermission) { await Gal.requestAccess(); } if (!imageExistsLocally) { final success = await _saveNetworkImageToLocal(imageUrl); return _SaveImageResult( isSuccess: success, method: SaveImageResultMethod.network, ); } final success = await _saveImageLocally(imageFile); return _SaveImageResult( isSuccess: success, method: SaveImageResultMethod.localStorage, ); } Future _saveNetworkImageToLocal(String imageUrl) async { try { final response = await http.get( Uri.parse(imageUrl), ); if (response.statusCode != 200) { return false; } final imageBytes = response.bodyBytes; await Gal.putImageBytes(imageBytes); return true; } catch (e) { return false; } } Future _convertFileToUint8List(File file) async { try { final uint8list = await file.readAsBytes(); return uint8list; } catch (e) { return Uint8List(0); } } Future _saveImageLocally(File imageFile) async { try { final imageBytes = await _convertFileToUint8List(imageFile); await Gal.putImageBytes(imageBytes); return true; } catch (e) { return false; } }