Remove universal_html dependency

pull/123/head
Xin Yao 4 years ago
parent 03e587b970
commit 63a616e7eb
  1. 88
      example/lib/pages/home_page.dart
  2. 33
      example/lib/pages/read_only_page.dart
  3. 0
      example/lib/universal_ui/fake_ui.dart
  4. 0
      example/lib/universal_ui/real_ui.dart
  5. 57
      example/lib/universal_ui/universal_ui.dart
  6. 142
      example/lib/widgets/field.dart
  7. 2
      example/pubspec.yaml
  8. 21
      lib/utils/universal_ui/universal_ui.dart
  9. 38
      lib/widgets/editor.dart
  10. 1
      pubspec.yaml

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:app/universal_ui/universal_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -38,13 +39,13 @@ class _HomePageState extends State<HomePage> {
final doc = Document.fromJson(jsonDecode(result));
setState(() {
_controller = QuillController(
document: doc, selection: TextSelection.collapsed(offset: 0));
document: doc, selection: const TextSelection.collapsed(offset: 0));
});
} catch (error) {
final doc = Document()..insert(0, 'Empty asset');
setState(() {
_controller = QuillController(
document: doc, selection: TextSelection.collapsed(offset: 0));
document: doc, selection: const TextSelection.collapsed(offset: 0));
});
}
}
@ -52,7 +53,7 @@ class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
if (_controller == null) {
return Scaffold(body: Center(child: Text('Loading...')));
return const Scaffold(body: Center(child: Text('Loading...')));
}
return Scaffold(
@ -60,7 +61,7 @@ class _HomePageState extends State<HomePage> {
backgroundColor: Colors.grey.shade800,
elevation: 0,
centerTitle: false,
title: Text(
title: const Text(
'Flutter Quill',
),
actions: [],
@ -93,6 +94,55 @@ class _HomePageState extends State<HomePage> {
}
Widget _buildWelcomeEditor(BuildContext context) {
var quillEditor = QuillEditor(
controller: _controller!,
scrollController: ScrollController(),
scrollable: true,
focusNode: _focusNode,
autoFocus: false,
readOnly: false,
placeholder: 'Add content',
expands: false,
padding: EdgeInsets.zero,
customStyles: DefaultStyles(
h1: DefaultTextBlockStyle(
const TextStyle(
fontSize: 32.0,
color: Colors.black,
height: 1.15,
fontWeight: FontWeight.w300,
),
const Tuple2(16.0, 0.0),
const Tuple2(0.0, 0.0),
null),
sizeSmall: const TextStyle(fontSize: 9.0),
));
if (kIsWeb) {
quillEditor = QuillEditor(
controller: _controller!,
scrollController: ScrollController(),
scrollable: true,
focusNode: _focusNode,
autoFocus: false,
readOnly: false,
placeholder: 'Add content',
expands: false,
padding: EdgeInsets.zero,
customStyles: DefaultStyles(
h1: DefaultTextBlockStyle(
const TextStyle(
fontSize: 32.0,
color: Colors.black,
height: 1.15,
fontWeight: FontWeight.w300,
),
const Tuple2(16.0, 0.0),
const Tuple2(0.0, 0.0),
null),
sizeSmall: const TextStyle(fontSize: 9.0),
),
embedBuilder: defaultEmbedBuilderWeb);
}
return SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -102,36 +152,14 @@ class _HomePageState extends State<HomePage> {
child: Container(
color: Colors.white,
padding: const EdgeInsets.only(left: 16.0, right: 16.0),
child: QuillEditor(
controller: _controller!,
scrollController: ScrollController(),
scrollable: true,
focusNode: _focusNode,
autoFocus: false,
readOnly: false,
placeholder: 'Add content',
expands: false,
padding: EdgeInsets.zero,
customStyles: DefaultStyles(
h1: DefaultTextBlockStyle(
TextStyle(
fontSize: 32.0,
color: Colors.black,
height: 1.15,
fontWeight: FontWeight.w300,
),
Tuple2(16.0, 0.0),
Tuple2(0.0, 0.0),
null),
sizeSmall: TextStyle(fontSize: 9.0),
),
),
child: quillEditor,
),
),
kIsWeb
? Expanded(
child: Container(
padding: EdgeInsets.symmetric(vertical: 16, horizontal: 8),
padding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 8),
child: QuillToolbar.basic(
controller: _controller!,
onImagePickCallback: _onImagePickCallback),
@ -158,7 +186,7 @@ class _HomePageState extends State<HomePage> {
Widget _buildMenuBar(BuildContext context) {
Size size = MediaQuery.of(context).size;
final itemStyle = TextStyle(
final itemStyle = const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,

@ -1,3 +1,5 @@
import 'package:app/universal_ui/universal_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_quill/widgets/controller.dart';
import 'package:flutter_quill/widgets/editor.dart';
@ -28,15 +30,19 @@ class _ReadOnlyPageState extends State<ReadOnlyPage> {
}
Widget _buildContent(BuildContext context, QuillController? controller) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.grey.shade200),
),
child: QuillEditor(
controller: controller!,
var quillEditor = QuillEditor(
controller: controller!,
scrollController: ScrollController(),
scrollable: true,
focusNode: _focusNode,
autoFocus: true,
readOnly: !_edit,
expands: false,
padding: EdgeInsets.zero,
);
if (kIsWeb) {
quillEditor = QuillEditor(
controller: controller,
scrollController: ScrollController(),
scrollable: true,
focusNode: _focusNode,
@ -44,7 +50,16 @@ class _ReadOnlyPageState extends State<ReadOnlyPage> {
readOnly: !_edit,
expands: false,
padding: EdgeInsets.zero,
embedBuilder: defaultEmbedBuilderWeb);
}
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.grey.shade200),
),
child: quillEditor,
),
);
}

@ -0,0 +1,57 @@
library universal_ui;
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_quill/models/documents/nodes/leaf.dart' as leaf;
import 'package:flutter_quill/widgets/responsive_widget.dart';
import 'package:universal_html/html.dart' as html;
import 'fake_ui.dart' if (dart.library.html) 'real_ui.dart' as ui_instance;
class PlatformViewRegistryFix {
void registerViewFactory(dynamic x, dynamic y) {
if (kIsWeb) {
ui_instance.PlatformViewRegistry.registerViewFactory(
x,
y,
);
}
}
}
class UniversalUI {
PlatformViewRegistryFix platformViewRegistry = PlatformViewRegistryFix();
}
var ui = UniversalUI();
Widget defaultEmbedBuilderWeb(BuildContext context, leaf.Embed node) {
switch (node.value.type) {
case 'image':
String imageUrl = node.value.data;
Size size = MediaQuery.of(context).size;
UniversalUI().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.');
}
}

@ -1,142 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_quill/widgets/controller.dart';
import 'package:flutter_quill/widgets/delegate.dart';
import 'package:flutter_quill/widgets/editor.dart';
class QuillField extends StatefulWidget {
final QuillController controller;
final FocusNode? focusNode;
final ScrollController? scrollController;
final bool scrollable;
final EdgeInsetsGeometry padding;
final bool autofocus;
final bool showCursor;
final bool readOnly;
final bool enableInteractiveSelection;
final double? minHeight;
final double? maxHeight;
final bool expands;
final TextCapitalization textCapitalization;
final Brightness keyboardAppearance;
final ScrollPhysics? scrollPhysics;
final ValueChanged<String>? onLaunchUrl;
final InputDecoration? decoration;
final Widget? toolbar;
final EmbedBuilder? embedBuilder;
QuillField({
Key? key,
required this.controller,
this.focusNode,
this.scrollController,
this.scrollable = true,
this.padding = EdgeInsets.zero,
this.autofocus = false,
this.showCursor = true,
this.readOnly = false,
this.enableInteractiveSelection = true,
this.minHeight,
this.maxHeight,
this.expands = false,
this.textCapitalization = TextCapitalization.sentences,
this.keyboardAppearance = Brightness.light,
this.scrollPhysics,
this.onLaunchUrl,
this.decoration,
this.toolbar,
this.embedBuilder,
}) : super(key: key);
@override
_QuillFieldState createState() => _QuillFieldState();
}
class _QuillFieldState extends State<QuillField> {
late bool _focused;
void _editorFocusChanged() {
setState(() {
_focused = widget.focusNode!.hasFocus;
});
}
@override
void initState() {
super.initState();
_focused = widget.focusNode!.hasFocus;
widget.focusNode!.addListener(_editorFocusChanged);
}
@override
void didUpdateWidget(covariant QuillField oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.focusNode != oldWidget.focusNode) {
oldWidget.focusNode!.removeListener(_editorFocusChanged);
widget.focusNode!.addListener(_editorFocusChanged);
_focused = widget.focusNode!.hasFocus;
}
}
@override
Widget build(BuildContext context) {
Widget child = QuillEditor(
controller: widget.controller,
focusNode: widget.focusNode!,
scrollController: widget.scrollController!,
scrollable: widget.scrollable,
padding: widget.padding,
autoFocus: widget.autofocus,
showCursor: widget.showCursor,
readOnly: widget.readOnly,
enableInteractiveSelection: widget.enableInteractiveSelection,
minHeight: widget.minHeight,
maxHeight: widget.maxHeight,
expands: widget.expands,
textCapitalization: widget.textCapitalization,
keyboardAppearance: widget.keyboardAppearance,
scrollPhysics: widget.scrollPhysics,
onLaunchUrl: widget.onLaunchUrl,
embedBuilder: widget.embedBuilder!,
);
if (widget.toolbar != null) {
child = Column(
children: [
child,
Visibility(
visible: _focused,
maintainSize: true,
maintainAnimation: true,
maintainState: true,
child: widget.toolbar!,
),
],
);
}
return AnimatedBuilder(
animation:
Listenable.merge(<Listenable?>[widget.focusNode, widget.controller]),
builder: (BuildContext context, Widget? child) {
return InputDecorator(
decoration: _getEffectiveDecoration(),
isFocused: widget.focusNode!.hasFocus,
// TODO: Document should be considered empty of it has single empty line with no styles applied
isEmpty: widget.controller.document.length == 1,
child: child,
);
},
child: child,
);
}
InputDecoration _getEffectiveDecoration() {
return (widget.decoration ?? const InputDecoration())
.applyDefaults(Theme.of(context).inputDecorationTheme)
.copyWith(
enabled: !widget.readOnly,
hintMaxLines: widget.decoration?.hintMaxLines,
);
}
}

@ -23,7 +23,7 @@ environment:
dependencies:
flutter:
sdk: flutter
universal_html: ^2.0.7
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.

@ -1,21 +0,0 @@
library universal_ui;
import 'package:flutter/foundation.dart';
import 'fake_ui.dart' if (dart.library.html) 'real_ui.dart' as ui_instance;
class PlatformViewRegistryFix {
void registerViewFactory(dynamic x, dynamic y) {
if (kIsWeb) {
ui_instance.PlatformViewRegistry.registerViewFactory(
x,
y,
);
}
}
}
class UniversalUI {
PlatformViewRegistryFix platformViewRegistry = PlatformViewRegistryFix();
}
var ui = UniversalUI();

@ -16,13 +16,10 @@ import 'package:flutter_quill/models/documents/nodes/embed.dart';
import 'package:flutter_quill/models/documents/nodes/leaf.dart' as leaf;
import 'package:flutter_quill/models/documents/nodes/line.dart';
import 'package:flutter_quill/models/documents/nodes/node.dart';
import 'package:flutter_quill/utils/universal_ui/universal_ui.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:string_validator/string_validator.dart';
import 'package:universal_html/html.dart' as html;
import 'package:url_launcher/url_launcher.dart';
import 'box.dart';
@ -101,6 +98,7 @@ String _standardizeImageUrl(String url) {
}
Widget _defaultEmbedBuilder(BuildContext context, leaf.Embed node) {
assert(!kIsWeb, 'Please provide EmbedBuilder for Web');
switch (node.value.type) {
case 'image':
String imageUrl = _standardizeImageUrl(node.value.data);
@ -117,37 +115,6 @@ 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;
UniversalUI().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;
@ -188,8 +155,7 @@ class QuillEditor extends StatefulWidget {
this.keyboardAppearance = Brightness.light,
this.scrollPhysics,
this.onLaunchUrl,
this.embedBuilder =
kIsWeb ? _defaultEmbedBuilderWeb : _defaultEmbedBuilder});
this.embedBuilder = _defaultEmbedBuilder});
factory QuillEditor.basic(
{required QuillController controller, required bool readOnly}) {

@ -23,7 +23,6 @@ dependencies:
quiver: ^3.0.0
string_validator: ^0.3.0
tuple: ^2.0.0
universal_html: ^2.0.7
url_launcher: ^6.0.2
pedantic: ^1.11.0

Loading…
Cancel
Save