|
|
|
import 'dart:convert';
|
|
|
|
import 'dart:io' show File;
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_quill/flutter_quill.dart';
|
|
|
|
import 'package:photo_view/photo_view.dart';
|
|
|
|
|
|
|
|
import '../utils.dart';
|
|
|
|
|
|
|
|
const List<String> imageFileExtensions = [
|
|
|
|
'.jpeg',
|
|
|
|
'.png',
|
|
|
|
'.jpg',
|
|
|
|
'.gif',
|
|
|
|
'.webp',
|
|
|
|
'.tif',
|
|
|
|
'.heic'
|
|
|
|
];
|
|
|
|
|
|
|
|
String getImageStyleString(QuillController controller) {
|
|
|
|
final String? s = controller
|
|
|
|
.getAllSelectionStyles()
|
|
|
|
.firstWhere((s) => s.attributes.containsKey(Attribute.style.key),
|
|
|
|
orElse: Style.new)
|
|
|
|
.attributes[Attribute.style.key]
|
|
|
|
?.value;
|
|
|
|
return s ?? '';
|
|
|
|
}
|
|
|
|
|
|
|
|
Image imageByUrl(String imageUrl,
|
|
|
|
{double? width,
|
|
|
|
double? height,
|
|
|
|
AlignmentGeometry alignment = Alignment.center}) {
|
|
|
|
if (isImageBase64(imageUrl)) {
|
|
|
|
return Image.memory(base64.decode(imageUrl),
|
|
|
|
width: width, height: height, alignment: alignment);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (imageUrl.startsWith('http')) {
|
|
|
|
return Image.network(imageUrl,
|
|
|
|
width: width, height: height, alignment: alignment);
|
|
|
|
}
|
|
|
|
return Image.file(File(imageUrl),
|
|
|
|
width: width, height: height, alignment: alignment);
|
|
|
|
}
|
|
|
|
|
|
|
|
String standardizeImageUrl(String url) {
|
|
|
|
if (url.contains('base64')) {
|
|
|
|
return url.split(',')[1];
|
|
|
|
}
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This is a bug of Gallery Saver Package.
|
|
|
|
/// It can not save image that's filename does not end with it's file extension
|
|
|
|
/// like below.
|
|
|
|
// "https://firebasestorage.googleapis.com/v0/b/eventat-4ba96.appspot.com/o/2019-Metrology-Events.jpg?alt=media&token=bfc47032-5173-4b3f-86bb-9659f46b362a"
|
|
|
|
/// If imageUrl does not end with it's file extension,
|
|
|
|
/// file extension is added to image url for saving.
|
|
|
|
String appendFileExtensionToImageUrl(String url) {
|
|
|
|
final endsWithImageFileExtension = imageFileExtensions
|
|
|
|
.firstWhere((s) => url.toLowerCase().endsWith(s), orElse: () => '');
|
|
|
|
if (endsWithImageFileExtension.isNotEmpty) {
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
final imageFileExtension = imageFileExtensions
|
|
|
|
.firstWhere((s) => url.toLowerCase().contains(s), orElse: () => '');
|
|
|
|
|
|
|
|
return url + imageFileExtension;
|
|
|
|
}
|
|
|
|
|
|
|
|
class ImageTapWrapper extends StatelessWidget {
|
|
|
|
const ImageTapWrapper({
|
|
|
|
required this.imageUrl,
|
|
|
|
});
|
|
|
|
|
|
|
|
final String imageUrl;
|
|
|
|
|
|
|
|
ImageProvider _imageProviderByUrl(String imageUrl) {
|
|
|
|
if (imageUrl.startsWith('http')) {
|
|
|
|
return NetworkImage(imageUrl);
|
|
|
|
}
|
|
|
|
|
|
|
|
return FileImage(File(imageUrl));
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Scaffold(
|
|
|
|
body: Container(
|
|
|
|
constraints: BoxConstraints.expand(
|
|
|
|
height: MediaQuery.of(context).size.height,
|
|
|
|
),
|
|
|
|
child: Stack(
|
|
|
|
children: [
|
|
|
|
PhotoView(
|
|
|
|
imageProvider: _imageProviderByUrl(imageUrl),
|
|
|
|
loadingBuilder: (context, event) {
|
|
|
|
return Container(
|
|
|
|
color: Colors.black,
|
|
|
|
child: const Center(
|
|
|
|
child: CircularProgressIndicator(),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
Positioned(
|
|
|
|
right: 10,
|
|
|
|
top: MediaQuery.of(context).padding.top + 10.0,
|
|
|
|
child: InkWell(
|
|
|
|
onTap: () {
|
|
|
|
Navigator.pop(context);
|
|
|
|
},
|
|
|
|
child: Stack(
|
|
|
|
children: [
|
|
|
|
Opacity(
|
|
|
|
opacity: 0.2,
|
|
|
|
child: Container(
|
|
|
|
height: 30,
|
|
|
|
width: 30,
|
|
|
|
decoration: const BoxDecoration(
|
|
|
|
shape: BoxShape.circle,
|
|
|
|
color: Colors.black87,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Positioned(
|
|
|
|
top: 0,
|
|
|
|
bottom: 0,
|
|
|
|
left: 0,
|
|
|
|
right: 0,
|
|
|
|
child:
|
|
|
|
Icon(Icons.close, color: Colors.grey[400], size: 28),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|