mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-11-09 13:09:21 +03:00
[editor] Add embed builder handlers protocol
This commit is contained in:
parent
ef11bbbb2b
commit
f1c23ca91a
@ -8,6 +8,14 @@
|
||||
},
|
||||
"insert":"\n"
|
||||
},
|
||||
{
|
||||
"insert": {
|
||||
"flutter_logo": ""
|
||||
},
|
||||
"attributes":{
|
||||
"size": 50.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"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…
Reference in New Issue
Block a user