Skip to content

Commit 3080fc2

Browse files
authored
Fix image button cancel causes crash (singerdmx#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 singerdmx#137.
1 parent 48d176d commit 3080fc2

File tree

1 file changed

+65
-68
lines changed

1 file changed

+65
-68
lines changed

lib/widgets/toolbar.dart

Lines changed: 65 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ double iconSize = 18;
1818
double kToolbarHeight = iconSize * 2;
1919

2020
typedef OnImagePickCallback = Future<String> Function(File file);
21-
typedef ImagePickImpl = Future<String> Function(ImageSource source);
21+
typedef ImagePickImpl = Future<String?> Function(ImageSource source);
2222

2323
class InsertEmbedButton extends StatelessWidget {
2424
const InsertEmbedButton({
@@ -252,7 +252,8 @@ class _ToggleStyleButtonState extends State<ToggleStyleButton> {
252252
_selectionStyle.attributes.containsKey(Attribute.codeBlock.key);
253253
final isEnabled =
254254
!isInCodeBlock || widget.attribute.key == Attribute.codeBlock.key;
255-
return widget.childBuilder(context, widget.attribute, widget.icon, widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null);
255+
return widget.childBuilder(context, widget.attribute, widget.icon,
256+
widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null);
256257
}
257258

258259
void _toggleAttribute() {
@@ -339,7 +340,8 @@ class _ToggleCheckListButtonState extends State<ToggleCheckListButton> {
339340
_selectionStyle.attributes.containsKey(Attribute.codeBlock.key);
340341
final isEnabled =
341342
!isInCodeBlock || Attribute.list.key == Attribute.codeBlock.key;
342-
return widget.childBuilder(context, Attribute.unchecked, widget.icon, widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null);
343+
return widget.childBuilder(context, Attribute.unchecked, widget.icon,
344+
widget.fillColor, _isToggled, isEnabled ? _toggleAttribute : null);
343345
}
344346

345347
void _toggleAttribute() {
@@ -364,8 +366,9 @@ Widget defaultToggleStyleButtonBuilder(
364366
? theme.primaryIconTheme.color
365367
: theme.iconTheme.color
366368
: theme.disabledColor;
367-
final fill =
368-
isToggled == true ? theme.toggleableActiveColor : fillColor ?? theme.canvasColor;
369+
final fill = isToggled == true
370+
? theme.toggleableActiveColor
371+
: fillColor ?? theme.canvasColor;
369372
return QuillIconButton(
370373
highlightElevation: 0,
371374
hoverElevation: 0,
@@ -522,87 +525,81 @@ class ImageButton extends StatefulWidget {
522525
}
523526

524527
class _ImageButtonState extends State<ImageButton> {
525-
List<PlatformFile>? _paths;
526-
String? _extension;
527-
final _picker = ImagePicker();
528-
final FileType _pickingType = FileType.any;
528+
@override
529+
Widget build(BuildContext context) {
530+
final theme = Theme.of(context);
529531

530-
Future<String?> _pickImage(ImageSource source) async {
531-
final pickedFile = await _picker.getImage(source: source);
532-
if (pickedFile == null) return null;
532+
return QuillIconButton(
533+
icon: Icon(
534+
widget.icon,
535+
size: iconSize,
536+
color: theme.iconTheme.color,
537+
),
538+
highlightElevation: 0,
539+
hoverElevation: 0,
540+
size: iconSize * 1.77,
541+
fillColor: theme.canvasColor,
542+
onPressed: _handleImageButtonTap,
543+
);
544+
}
533545

534-
final file = File(pickedFile.path);
546+
Future<void> _handleImageButtonTap() async {
547+
final index = widget.controller.selection.baseOffset;
548+
final length = widget.controller.selection.extentOffset - index;
535549

536-
return widget.onImagePickCallback!(file);
550+
String? imageUrl;
551+
if (widget.imagePickImpl != null) {
552+
imageUrl = await widget.imagePickImpl!(widget.imageSource);
553+
} else {
554+
if (kIsWeb) {
555+
imageUrl = await _pickImageWeb();
556+
} else if (Platform.isAndroid || Platform.isIOS) {
557+
imageUrl = await _pickImage(widget.imageSource);
558+
} else {
559+
imageUrl = await _pickImageDesktop();
560+
}
561+
}
562+
563+
if (imageUrl != null) {
564+
widget.controller
565+
.replaceText(index, length, BlockEmbed.image(imageUrl), null);
566+
}
537567
}
538568

539569
Future<String?> _pickImageWeb() async {
540-
_paths = (await FilePicker.platform.pickFiles(
541-
type: _pickingType,
542-
allowedExtensions: (_extension?.isNotEmpty ?? false)
543-
? _extension?.replaceAll(' ', '').split(',')
544-
: null,
545-
))
546-
?.files;
547-
final _fileName =
548-
_paths != null ? _paths!.map((e) => e.name).toString() : '...';
549-
550-
if (_paths != null) {
551-
final file = File(_fileName);
552-
// We simply return the absolute path to selected file.
553-
return widget.onImagePickCallback!(file);
554-
} else {
555-
// User canceled the picker
570+
final result = await FilePicker.platform.pickFiles();
571+
if (result == null) {
572+
return null;
573+
}
574+
575+
// Take first, because we don't allow picking multiple files.
576+
final fileName = result.files.first.name!;
577+
final file = File(fileName);
578+
579+
return widget.onImagePickCallback!(file);
580+
}
581+
582+
Future<String?> _pickImage(ImageSource source) async {
583+
final pickedFile = await ImagePicker().getImage(source: source);
584+
if (pickedFile == null) {
585+
return null;
556586
}
557-
return null;
587+
588+
return widget.onImagePickCallback!(File(pickedFile.path));
558589
}
559590

560-
Future<String> _pickImageDesktop() async {
591+
Future<String?> _pickImageDesktop() async {
561592
final filePath = await FilesystemPicker.open(
562593
context: context,
563594
rootDirectory: await getApplicationDocumentsDirectory(),
564595
fsType: FilesystemType.file,
565596
fileTileSelectMode: FileTileSelectMode.wholeTile,
566597
);
567-
if (filePath != null && filePath.isEmpty) return '';
598+
if (filePath == null || filePath.isEmpty) return null;
568599

569-
final file = File(filePath!);
600+
final file = File(filePath);
570601
return widget.onImagePickCallback!(file);
571602
}
572-
573-
@override
574-
Widget build(BuildContext context) {
575-
final theme = Theme.of(context);
576-
final iconColor = theme.iconTheme.color;
577-
final fillColor = theme.canvasColor;
578-
return QuillIconButton(
579-
highlightElevation: 0,
580-
hoverElevation: 0,
581-
size: iconSize * 1.77,
582-
icon: Icon(widget.icon, size: iconSize, color: iconColor),
583-
fillColor: fillColor,
584-
onPressed: () {
585-
final index = widget.controller.selection.baseOffset;
586-
final length = widget.controller.selection.extentOffset - index;
587-
Future<String?> image;
588-
if (widget.imagePickImpl != null) {
589-
image = widget.imagePickImpl!(widget.imageSource);
590-
} else {
591-
if (kIsWeb) {
592-
image = _pickImageWeb();
593-
} else if (Platform.isAndroid || Platform.isIOS) {
594-
image = _pickImage(widget.imageSource);
595-
} else {
596-
image = _pickImageDesktop();
597-
}
598-
}
599-
image.then((imageUploadUrl) => {
600-
widget.controller.replaceText(
601-
index, length, BlockEmbed.image(imageUploadUrl!), null)
602-
});
603-
},
604-
);
605-
}
606603
}
607604

608605
/// Controls color styles.

0 commit comments

Comments
 (0)