diff --git a/app/lib/main.dart b/app/lib/main.dart index 77622559..f3ec0666 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'pages/home_page.dart'; void main() { + WidgetsFlutterBinding.ensureInitialized(); runApp(MyApp()); } diff --git a/app/lib/pages/home_page.dart b/app/lib/pages/home_page.dart index 3663543f..422d0954 100644 --- a/app/lib/pages/home_page.dart +++ b/app/lib/pages/home_page.dart @@ -89,11 +89,11 @@ class _HomePageState extends State { } Widget _buildWelcomeEditor(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: Container( + return SafeArea( + child: Stack( + children: [ + Container( + height: MediaQuery.of(context).size.height * 0.88, color: Colors.white, padding: const EdgeInsets.only(left: 16.0, right: 16.0), child: QuillEditor( @@ -120,13 +120,15 @@ class _HomePageState extends State { sizeSmall: TextStyle(fontSize: 9.0)), ), ), - ), - Container( - child: QuillToolbar.basic( - controller: _controller, - uploadFileCallback: _fakeUploadImageCallBack), - ) - ], + Container( + padding: + EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.9), + child: QuillToolbar.basic( + controller: _controller, + uploadFileCallback: _fakeUploadImageCallBack), + ) + ], + ), ); } diff --git a/lib/widgets/FakeUi.dart b/lib/widgets/FakeUi.dart new file mode 100644 index 00000000..bc9799af --- /dev/null +++ b/lib/widgets/FakeUi.dart @@ -0,0 +1,4 @@ +// ignore: camel_case_types +class platformViewRegistry { + static registerViewFactory(String viewId, dynamic cb) {} +} diff --git a/lib/widgets/RealUi.dart b/lib/widgets/RealUi.dart new file mode 100644 index 00000000..c2b8ea23 --- /dev/null +++ b/lib/widgets/RealUi.dart @@ -0,0 +1,9 @@ +import 'dart:ui' as ui; + +// ignore: camel_case_types +class platformViewRegistry { + static registerViewFactory(String viewId, dynamic cb) { + // ignore:undefined_prefixed_name + ui.platformViewRegistry.registerViewFactory(viewId, cb); + } +} diff --git a/lib/widgets/editor.dart b/lib/widgets/editor.dart index 6a388ed8..57e51188 100644 --- a/lib/widgets/editor.dart +++ b/lib/widgets/editor.dart @@ -1,7 +1,6 @@ -import 'dart:html' as html; import 'dart:io'; import 'dart:math' as math; -import 'dart:ui' as ui; +import 'dart:math' if (dart.library.html) 'dart:html' as html; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; @@ -19,9 +18,11 @@ import 'package:flutter_quill/models/documents/nodes/line.dart'; import 'package:flutter_quill/models/documents/nodes/node.dart'; import 'package:flutter_quill/widgets/image.dart'; import 'package:flutter_quill/widgets/raw_editor.dart'; +import 'package:flutter_quill/widgets/responsive_widget.dart'; import 'package:flutter_quill/widgets/text_selection.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'FakeUi.dart' if (dart.library.html) 'RealUi.dart' as ui; import 'box.dart'; import 'controller.dart'; import 'cursor.dart'; @@ -79,21 +80,6 @@ abstract class RenderAbstractEditor { Widget _defaultEmbedBuilder(BuildContext context, leaf.Embed node) { switch (node.value.type) { case 'image': - if (kIsWeb) { - String imageUrl = node.value.data; - - ui.platformViewRegistry.registerViewFactory( - imageUrl, - (int viewId) => html.ImageElement()..src = imageUrl, - ); - return Container( - constraints: BoxConstraints(maxWidth: 300), - height: MediaQuery.of(context).size.height, - child: HtmlElementView( - viewType: imageUrl, - ), - ); - } String imageUrl = node.value.data; return imageUrl.startsWith('http') ? Image.network(imageUrl) @@ -106,6 +92,39 @@ Widget _defaultEmbedBuilder(BuildContext context, leaf.Embed node) { } } +Widget _defaultEmbedBuilderWeb(BuildContext context, leaf.Embed node) { + switch (node.value.type) { + case 'image': + String imageUrl = node.value.data; + Size size = MediaQuery.of(context).size; + ui.platformViewRegistry.registerViewFactory( + imageUrl, + (int viewId) => html.ImageElement()..src = imageUrl, + ); + return Padding( + padding: EdgeInsets.only( + right: ResponsiveWidget.isMediumScreen(context) + ? size.width * 0.5 + : (ResponsiveWidget.isLargeScreen(context)) + ? size.width * 0.75 + : size.width * 0.2, + ), + child: SizedBox( + height: MediaQuery.of(context).size.height * 0.45, + child: HtmlElementView( + viewType: imageUrl, + ), + ), + ); + + 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.'); + } +} + class QuillEditor extends StatefulWidget { final QuillController controller; final FocusNode focusNode; @@ -144,7 +163,8 @@ class QuillEditor extends StatefulWidget { this.keyboardAppearance = Brightness.light, this.scrollPhysics, this.onLaunchUrl, - this.embedBuilder = _defaultEmbedBuilder}) + this.embedBuilder = + kIsWeb ? _defaultEmbedBuilderWeb : _defaultEmbedBuilder}) : assert(controller != null), assert(scrollController != null), assert(scrollable != null), diff --git a/lib/widgets/responsive_widget.dart b/lib/widgets/responsive_widget.dart new file mode 100644 index 00000000..dae14b73 --- /dev/null +++ b/lib/widgets/responsive_widget.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +class ResponsiveWidget extends StatelessWidget { + final Widget largeScreen; + final Widget mediumScreen; + final Widget smallScreen; + + const ResponsiveWidget({Key key, @required this.largeScreen, this.mediumScreen, this.smallScreen}) : super(key: key); + + static bool isSmallScreen(BuildContext context) { + return MediaQuery.of(context).size.width < 800; + } + + static bool isLargeScreen(BuildContext context) { + return MediaQuery.of(context).size.width > 1200; + } + + static bool isMediumScreen(BuildContext context) { + return MediaQuery.of(context).size.width >= 800 && MediaQuery.of(context).size.width <= 1200; + } + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + if (constraints.maxWidth > 1200) { + return largeScreen; + } else if (constraints.maxWidth <= 1200 && constraints.maxWidth >= 800) { + return mediumScreen ?? largeScreen; + } else { + return smallScreen ?? largeScreen; + } + }, + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index fb373ad1..a90908d0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,6 +20,7 @@ dependencies: flutter_colorpicker: ^0.3.4 image_picker: ^0.6.7+17 photo_view: ^0.10.3 + universal_html: ^1.2.4 dev_dependencies: flutter_test: