dartlangeditorflutterflutter-appsflutter-examplesflutter-packageflutter-widgetquillquill-deltaquilljsreactquillrich-textrich-text-editorwysiwygwysiwyg-editor
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.5 KiB
105 lines
2.5 KiB
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<bool> _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<Uint8List> _convertFileToUint8List(File file) async { |
|
try { |
|
final uint8list = await file.readAsBytes(); |
|
return uint8list; |
|
} catch (e) { |
|
return Uint8List(0); |
|
} |
|
} |
|
|
|
Future<bool> _saveImageLocally(File imageFile) async { |
|
try { |
|
final imageBytes = await _convertFileToUint8List(imageFile); |
|
await Gal.putImageBytes(imageBytes); |
|
return true; |
|
} catch (e) { |
|
return false; |
|
} |
|
}
|
|
|