mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
[editor] Add embed builder handlers protocol
This commit is contained in:
parent
ef11bbbb2b
commit
f1c23ca91a
@ -8,6 +8,14 @@
|
|||||||
},
|
},
|
||||||
"insert":"\n"
|
"insert":"\n"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"insert": {
|
||||||
|
"flutter_logo": ""
|
||||||
|
},
|
||||||
|
"attributes":{
|
||||||
|
"size": 50.0
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"insert":"\n"
|
"insert":"\n"
|
||||||
}
|
}
|
||||||
|
40
app_flowy/packages/flowy_editor/example/ios/Podfile.lock
Normal file
40
app_flowy/packages/flowy_editor/example/ios/Podfile.lock
Normal 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
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
106
app_flowy/packages/flowy_editor/lib/src/widget/embed.dart
Normal file
106
app_flowy/packages/flowy_editor/lib/src/widget/embed.dart
Normal 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}"'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user