parent
03e587b970
commit
63a616e7eb
10 changed files with 142 additions and 240 deletions
@ -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, |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
@ -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(); |
|
Loading…
Reference in new issue