Fix image button cancel causes crash (#145)

I also restructured the code slightly to make it more readable 
and fixed some minor bugs in the desktop and web version.

I also noticed that the image button doesn't work in the desktop
version as well as in the web version. This is not part of the PR.

Closes #137.
pull/150/head
Till Friebe 4 years ago committed by GitHub
parent 48d176d864
commit 3080fc2ad1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 133
      lib/widgets/toolbar.dart

@ -18,7 +18,7 @@ double iconSize = 18;
double kToolbarHeight = iconSize * 2; double kToolbarHeight = iconSize * 2;
typedef OnImagePickCallback = Future<String> Function(File file); typedef OnImagePickCallback = Future<String> Function(File file);
typedef ImagePickImpl = Future<String> Function(ImageSource source); typedef ImagePickImpl = Future<String?> Function(ImageSource source);
class InsertEmbedButton extends StatelessWidget { class InsertEmbedButton extends StatelessWidget {
const InsertEmbedButton({ const InsertEmbedButton({
@ -252,7 +252,8 @@ class _ToggleStyleButtonState extends State<ToggleStyleButton> {
_selectionStyle.attributes.containsKey(Attribute.codeBlock.key); _selectionStyle.attributes.containsKey(Attribute.codeBlock.key);
final isEnabled = final isEnabled =
!isInCodeBlock || widget.attribute.key == Attribute.codeBlock.key; !isInCodeBlock || widget.attribute.key == Attribute.codeBlock.key;
return widget.childBuilder(context, widget.attribute, widget.icon, widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null); return widget.childBuilder(context, widget.attribute, widget.icon,
widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null);
} }
void _toggleAttribute() { void _toggleAttribute() {
@ -339,7 +340,8 @@ class _ToggleCheckListButtonState extends State<ToggleCheckListButton> {
_selectionStyle.attributes.containsKey(Attribute.codeBlock.key); _selectionStyle.attributes.containsKey(Attribute.codeBlock.key);
final isEnabled = final isEnabled =
!isInCodeBlock || Attribute.list.key == Attribute.codeBlock.key; !isInCodeBlock || Attribute.list.key == Attribute.codeBlock.key;
return widget.childBuilder(context, Attribute.unchecked, widget.icon, widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null); return widget.childBuilder(context, Attribute.unchecked, widget.icon,
widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null);
} }
void _toggleAttribute() { void _toggleAttribute() {
@ -364,8 +366,9 @@ Widget defaultToggleStyleButtonBuilder(
? theme.primaryIconTheme.color ? theme.primaryIconTheme.color
: theme.iconTheme.color : theme.iconTheme.color
: theme.disabledColor; : theme.disabledColor;
final fill = final fill = isToggled == true
isToggled == true ? theme.toggleableActiveColor : fillColor ?? theme.canvasColor; ? theme.toggleableActiveColor
: fillColor ?? theme.canvasColor;
return QuillIconButton( return QuillIconButton(
highlightElevation: 0, highlightElevation: 0,
hoverElevation: 0, hoverElevation: 0,
@ -522,87 +525,81 @@ class ImageButton extends StatefulWidget {
} }
class _ImageButtonState extends State<ImageButton> { class _ImageButtonState extends State<ImageButton> {
List<PlatformFile>? _paths; @override
String? _extension; Widget build(BuildContext context) {
final _picker = ImagePicker(); final theme = Theme.of(context);
final FileType _pickingType = FileType.any;
Future<String?> _pickImage(ImageSource source) async { return QuillIconButton(
final pickedFile = await _picker.getImage(source: source); icon: Icon(
if (pickedFile == null) return null; widget.icon,
size: iconSize,
color: theme.iconTheme.color,
),
highlightElevation: 0,
hoverElevation: 0,
size: iconSize * 1.77,
fillColor: theme.canvasColor,
onPressed: _handleImageButtonTap,
);
}
final file = File(pickedFile.path); Future<void> _handleImageButtonTap() async {
final index = widget.controller.selection.baseOffset;
final length = widget.controller.selection.extentOffset - index;
return widget.onImagePickCallback!(file); String? imageUrl;
if (widget.imagePickImpl != null) {
imageUrl = await widget.imagePickImpl!(widget.imageSource);
} else {
if (kIsWeb) {
imageUrl = await _pickImageWeb();
} else if (Platform.isAndroid || Platform.isIOS) {
imageUrl = await _pickImage(widget.imageSource);
} else {
imageUrl = await _pickImageDesktop();
}
}
if (imageUrl != null) {
widget.controller
.replaceText(index, length, BlockEmbed.image(imageUrl), null);
}
} }
Future<String?> _pickImageWeb() async { Future<String?> _pickImageWeb() async {
_paths = (await FilePicker.platform.pickFiles( final result = await FilePicker.platform.pickFiles();
type: _pickingType, if (result == null) {
allowedExtensions: (_extension?.isNotEmpty ?? false) return null;
? _extension?.replaceAll(' ', '').split(',') }
: null,
)) // Take first, because we don't allow picking multiple files.
?.files; final fileName = result.files.first.name!;
final _fileName = final file = File(fileName);
_paths != null ? _paths!.map((e) => e.name).toString() : '...';
return widget.onImagePickCallback!(file);
if (_paths != null) { }
final file = File(_fileName);
// We simply return the absolute path to selected file. Future<String?> _pickImage(ImageSource source) async {
return widget.onImagePickCallback!(file); final pickedFile = await ImagePicker().getImage(source: source);
} else { if (pickedFile == null) {
// User canceled the picker return null;
} }
return null;
return widget.onImagePickCallback!(File(pickedFile.path));
} }
Future<String> _pickImageDesktop() async { Future<String?> _pickImageDesktop() async {
final filePath = await FilesystemPicker.open( final filePath = await FilesystemPicker.open(
context: context, context: context,
rootDirectory: await getApplicationDocumentsDirectory(), rootDirectory: await getApplicationDocumentsDirectory(),
fsType: FilesystemType.file, fsType: FilesystemType.file,
fileTileSelectMode: FileTileSelectMode.wholeTile, fileTileSelectMode: FileTileSelectMode.wholeTile,
); );
if (filePath != null && filePath.isEmpty) return ''; if (filePath == null || filePath.isEmpty) return null;
final file = File(filePath!); final file = File(filePath);
return widget.onImagePickCallback!(file); return widget.onImagePickCallback!(file);
} }
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final iconColor = theme.iconTheme.color;
final fillColor = theme.canvasColor;
return QuillIconButton(
highlightElevation: 0,
hoverElevation: 0,
size: iconSize * 1.77,
icon: Icon(widget.icon, size: iconSize, color: iconColor),
fillColor: fillColor,
onPressed: () {
final index = widget.controller.selection.baseOffset;
final length = widget.controller.selection.extentOffset - index;
Future<String?> image;
if (widget.imagePickImpl != null) {
image = widget.imagePickImpl!(widget.imageSource);
} else {
if (kIsWeb) {
image = _pickImageWeb();
} else if (Platform.isAndroid || Platform.isIOS) {
image = _pickImage(widget.imageSource);
} else {
image = _pickImageDesktop();
}
}
image.then((imageUploadUrl) => {
widget.controller.replaceText(
index, length, BlockEmbed.image(imageUploadUrl!), null)
});
},
);
}
} }
/// Controls color styles. /// Controls color styles.

Loading…
Cancel
Save