[editor] Add embed builder handlers protocol

This commit is contained in:
Jaylen Bian 2021-07-09 22:43:04 +08:00
parent ef11bbbb2b
commit f1c23ca91a
4 changed files with 154 additions and 39 deletions

View File

@ -8,6 +8,14 @@
},
"insert":"\n"
},
{
"insert": {
"flutter_logo": ""
},
"attributes":{
"size": 50.0
}
},
{
"insert":"\n"
}

View File

@ -0,0 +1,40 @@
PODS:
- flowy_editor (0.0.1):
- Flutter
- Flutter (1.0.0)
- flutter_keyboard_visibility (0.0.1):
- Flutter
- path_provider (0.0.1):
- Flutter
- url_launcher (0.0.1):
- Flutter
DEPENDENCIES:
- flowy_editor (from `.symlinks/plugins/flowy_editor/ios`)
- Flutter (from `Flutter`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
EXTERNAL SOURCES:
flowy_editor:
:path: ".symlinks/plugins/flowy_editor/ios"
Flutter:
:path: Flutter
flutter_keyboard_visibility:
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
url_launcher:
:path: ".symlinks/plugins/url_launcher/ios"
SPEC CHECKSUMS:
flowy_editor: bf8d58894ddb03453bd4d8521c57267ad638b837
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
COCOAPODS: 1.9.3

View File

@ -146,42 +146,3 @@ class EditorTextSelectionGestureDetectorBuilder {
);
}
}
/* ---------------------------------- Embed --------------------------------- */
class EmbedBuilder {
static const kImageTypeKey = 'image';
static const kVideoTypeKey = 'video';
static Widget defaultBuilder(BuildContext context, Embed node) {
assert(!kIsWeb, 'Please provide EmbedBuilder for Web');
switch (node.value.type) {
case kImageTypeKey:
return _generateImageEmbed(context, node);
default:
throw UnimplementedError('Embeddable type "${node.value.type}" is not supported by default embed '
'builder of QuillEditor. You must pass your own builder function to '
'embedBuilder property of QuillEditor or QuillField widgets.');
}
}
// Generator
static Widget _generateImageEmbed(BuildContext context, Embed node) {
final imageUrl = standardizeImageUrl(node.value.data);
return imageUrl.startsWith('http')
? Image.network(imageUrl)
: isBase64(imageUrl)
? Image.memory(base64.decode(imageUrl))
: Image.file(io.File(imageUrl));
}
// Helper
static String standardizeImageUrl(String url) {
if (url.contains('base64')) {
return url.split(',')[1];
}
return url;
}
}

View File

@ -0,0 +1,106 @@
import 'dart:convert';
import 'dart:io' as io;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:string_validator/string_validator.dart';
import '../model/document/node/leaf.dart' show Embed;
abstract class EmbedWidgetBuilder {
bool canHandle(String type);
Widget? buildeWidget(BuildContext context, Embed node);
}
/* ---------------------------------- Embed --------------------------------- */
class EmbedBuilder {
static const kImageTypeKey = 'image';
static const kFlutterLogoTypeKey = 'flutter_logo';
static const builtInTypes = [kImageTypeKey, kFlutterLogoTypeKey];
static Widget defaultBuilder(BuildContext context, Embed node) {
assert(!kIsWeb, 'Please provide EmbedBuilder for Web');
switch (node.value.type) {
case kImageTypeKey:
return _generateImageEmbed(context, node);
case kFlutterLogoTypeKey:
return _generateFlutterLogoEmbed(context, node);
default:
return Align(
alignment: Alignment.center,
child: _UnsupportedHintBlock(node),
);
}
}
// Generator
static Widget _generateImageEmbed(BuildContext context, Embed node) {
final imageUrl = standardizeImageUrl(node.value.data);
return imageUrl.startsWith('http')
? Image.network(imageUrl)
: isBase64(imageUrl)
? Image.memory(base64.decode(imageUrl))
: Image.file(io.File(imageUrl));
}
static Widget _generateFlutterLogoEmbed(BuildContext context, Embed node) {
final size = node.style.attributes['size'];
var logoSize = size != null ? size.value as double? ?? 100.0 : 100.0;
return Align(
alignment: Alignment.center,
child: Container(
width: logoSize,
height: logoSize,
color: Colors.red,
child: GestureDetector(
onTap: () {
print('Flutter logo tapped');
},
child: FlutterLogo(size: logoSize),
),
),
);
}
// Helper
static String standardizeImageUrl(String url) {
if (url.contains('base64')) {
return url.split(',')[1];
}
return url;
}
}
/* ---------------------------- Unsupported Hint ---------------------------- */
class _UnsupportedHintBlock extends StatelessWidget {
final Embed node;
final double height;
const _UnsupportedHintBlock(
this.node, {
Key? key,
this.height = 80.0,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: height,
child: Column(
children: [
Icon(
Icons.warning,
color: Colors.red,
),
Text('Unsupported block type "${node.value.type}"'),
],
),
);
}
}