From f63fe3a5e5abfa157de9cf1599e7c76f134e74f8 Mon Sep 17 00:00:00 2001 From: xxdocobxx Date: Tue, 14 May 2019 23:29:11 +0800 Subject: [PATCH 1/3] Added more options to ZefyrThemeData. - Added the parameter horizontalRuleColor to ZefyrThemeData. - Added the parameter backgroundColor to quote and code BlockTheme --- packages/zefyr/lib/src/widgets/code.dart | 2 +- packages/zefyr/lib/src/widgets/horizontal_rule.dart | 10 +++++++--- packages/zefyr/lib/src/widgets/quote.dart | 8 ++++---- packages/zefyr/lib/src/widgets/theme.dart | 12 ++++++++++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/zefyr/lib/src/widgets/code.dart b/packages/zefyr/lib/src/widgets/code.dart index 1c5c60500..823a1ef94 100644 --- a/packages/zefyr/lib/src/widgets/code.dart +++ b/packages/zefyr/lib/src/widgets/code.dart @@ -28,7 +28,7 @@ class ZefyrCode extends StatelessWidget { child: new Container( // TODO: make decorations configurable decoration: BoxDecoration( - color: Colors.blueGrey.shade50, + color: theme.blockTheme.code.backgroundColor, borderRadius: BorderRadius.circular(3.0), ), padding: const EdgeInsets.all(16.0), diff --git a/packages/zefyr/lib/src/widgets/horizontal_rule.dart b/packages/zefyr/lib/src/widgets/horizontal_rule.dart index d9011f0ea..d948b1e36 100644 --- a/packages/zefyr/lib/src/widgets/horizontal_rule.dart +++ b/packages/zefyr/lib/src/widgets/horizontal_rule.dart @@ -9,6 +9,7 @@ import 'package:flutter/widgets.dart'; import 'package:notus/notus.dart'; import 'editable_box.dart'; +import 'theme.dart'; class ZefyrHorizontalRule extends LeafRenderObjectWidget { ZefyrHorizontalRule({@required this.node}) : assert(node != null); @@ -17,7 +18,7 @@ class ZefyrHorizontalRule extends LeafRenderObjectWidget { @override RenderHorizontalRule createRenderObject(BuildContext context) { - return new RenderHorizontalRule(node: node); + return new RenderHorizontalRule(node: node, context: context); } @override @@ -34,7 +35,8 @@ class RenderHorizontalRule extends RenderEditableBox { RenderHorizontalRule({ @required EmbedNode node, - }) : _node = node; + @required BuildContext context, + }) : _node = node, _context = context; @override EmbedNode get node => _node; @@ -45,6 +47,8 @@ class RenderHorizontalRule extends RenderEditableBox { markNeedsPaint(); } + BuildContext _context; + @override double get preferredLineHeight => size.height; @@ -77,7 +81,7 @@ class RenderHorizontalRule extends RenderEditableBox { @override void paint(PaintingContext context, Offset offset) { final rect = new Rect.fromLTWH(0.0, 0.0, size.width, _kThickness); - final paint = new ui.Paint()..color = Colors.grey.shade200; + final paint = new ui.Paint()..color = ZefyrTheme.of(_context).horizontalRuleColor; context.canvas.drawRect(rect.shift(offset), paint); } diff --git a/packages/zefyr/lib/src/widgets/quote.dart b/packages/zefyr/lib/src/widgets/quote.dart index a9eacd138..4975eb763 100644 --- a/packages/zefyr/lib/src/widgets/quote.dart +++ b/packages/zefyr/lib/src/widgets/quote.dart @@ -19,7 +19,7 @@ class ZefyrQuote extends StatelessWidget { final style = theme.blockTheme.quote.textStyle; List items = []; for (var line in node.children) { - items.add(_buildLine(line, style, theme.indentSize)); + items.add(_buildLine(line, style, theme)); } return Padding( @@ -31,7 +31,7 @@ class ZefyrQuote extends StatelessWidget { ); } - Widget _buildLine(Node node, TextStyle blockStyle, double indentSize) { + Widget _buildLine(Node node, TextStyle blockStyle, ZefyrThemeData theme) { LineNode line = node; Widget content; @@ -45,10 +45,10 @@ class ZefyrQuote extends StatelessWidget { return Container( decoration: BoxDecoration( border: Border( - left: BorderSide(width: 4.0, color: Colors.grey.shade300), + left: BorderSide(width: 4.0, color: theme.blockTheme.quote.backgroundColor), ), ), - padding: EdgeInsets.only(left: indentSize), + padding: EdgeInsets.only(left: theme.indentSize), child: row, ); } diff --git a/packages/zefyr/lib/src/widgets/theme.dart b/packages/zefyr/lib/src/widgets/theme.dart index 0f7c11602..c7e1a894a 100644 --- a/packages/zefyr/lib/src/widgets/theme.dart +++ b/packages/zefyr/lib/src/widgets/theme.dart @@ -59,6 +59,7 @@ class ZefyrThemeData { final StyleTheme paragraphTheme; final HeadingTheme headingTheme; final BlockTheme blockTheme; + final Color horizontalRuleColor; final Color selectionColor; final Color cursorColor; @@ -88,6 +89,7 @@ class ZefyrThemeData { new StyleTheme(textStyle: paragraphStyle, padding: padding), headingTheme: new HeadingTheme.fallback(), blockTheme: new BlockTheme.fallback(), + horizontalRuleColor: Colors.grey.shade200, selectionColor: Colors.lightBlueAccent.shade100, cursorColor: Colors.black, indentSize: 16.0, @@ -102,6 +104,7 @@ class ZefyrThemeData { this.paragraphTheme, this.headingTheme, this.blockTheme, + this.horizontalRuleColor, this.selectionColor, this.cursorColor, this.indentSize, @@ -116,6 +119,7 @@ class ZefyrThemeData { StyleTheme paragraphTheme, HeadingTheme headingTheme, BlockTheme blockTheme, + Color horizontalRuleColor, Color selectionColor, Color cursorColor, double indentSize, @@ -128,6 +132,7 @@ class ZefyrThemeData { paragraphTheme: paragraphTheme ?? this.paragraphTheme, headingTheme: headingTheme ?? this.headingTheme, blockTheme: blockTheme ?? this.blockTheme, + horizontalRuleColor: horizontalRuleColor?? this.horizontalRuleColor, selectionColor: selectionColor ?? this.selectionColor, cursorColor: cursorColor ?? this.cursorColor, indentSize: indentSize ?? this.indentSize, @@ -143,6 +148,7 @@ class ZefyrThemeData { paragraphTheme: other.paragraphTheme, headingTheme: other.headingTheme, blockTheme: other.blockTheme, + horizontalRuleColor: other.horizontalRuleColor, selectionColor: other.selectionColor, cursorColor: other.cursorColor, indentSize: other.indentSize, @@ -232,6 +238,7 @@ class BlockTheme { quote: new StyleTheme( textStyle: new TextStyle(color: Colors.grey.shade700), padding: padding, + backgroundColor: Colors.grey.shade300, ), code: new StyleTheme( textStyle: new TextStyle( @@ -241,6 +248,7 @@ class BlockTheme { height: 1.25, ), padding: padding, + backgroundColor: Colors.blueGrey.shade50, ), ); } @@ -257,10 +265,14 @@ class StyleTheme { /// Padding to apply around lines of text. final EdgeInsets padding; + /// Background color of this theme + final Color backgroundColor; + /// Creates a new [StyleTheme]. StyleTheme({ this.textStyle, this.padding, + this.backgroundColor, }); } From d98836b9bf20aadce2281f815dda2920c470ccee Mon Sep 17 00:00:00 2001 From: xxdocobxx Date: Wed, 15 May 2019 00:11:01 +0800 Subject: [PATCH 2/3] Revert "Added more options to ZefyrThemeData." This reverts commit f63fe3a5e5abfa157de9cf1599e7c76f134e74f8. --- packages/zefyr/lib/src/widgets/code.dart | 2 +- packages/zefyr/lib/src/widgets/horizontal_rule.dart | 10 +++------- packages/zefyr/lib/src/widgets/quote.dart | 8 ++++---- packages/zefyr/lib/src/widgets/theme.dart | 12 ------------ 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/packages/zefyr/lib/src/widgets/code.dart b/packages/zefyr/lib/src/widgets/code.dart index 823a1ef94..1c5c60500 100644 --- a/packages/zefyr/lib/src/widgets/code.dart +++ b/packages/zefyr/lib/src/widgets/code.dart @@ -28,7 +28,7 @@ class ZefyrCode extends StatelessWidget { child: new Container( // TODO: make decorations configurable decoration: BoxDecoration( - color: theme.blockTheme.code.backgroundColor, + color: Colors.blueGrey.shade50, borderRadius: BorderRadius.circular(3.0), ), padding: const EdgeInsets.all(16.0), diff --git a/packages/zefyr/lib/src/widgets/horizontal_rule.dart b/packages/zefyr/lib/src/widgets/horizontal_rule.dart index d948b1e36..d9011f0ea 100644 --- a/packages/zefyr/lib/src/widgets/horizontal_rule.dart +++ b/packages/zefyr/lib/src/widgets/horizontal_rule.dart @@ -9,7 +9,6 @@ import 'package:flutter/widgets.dart'; import 'package:notus/notus.dart'; import 'editable_box.dart'; -import 'theme.dart'; class ZefyrHorizontalRule extends LeafRenderObjectWidget { ZefyrHorizontalRule({@required this.node}) : assert(node != null); @@ -18,7 +17,7 @@ class ZefyrHorizontalRule extends LeafRenderObjectWidget { @override RenderHorizontalRule createRenderObject(BuildContext context) { - return new RenderHorizontalRule(node: node, context: context); + return new RenderHorizontalRule(node: node); } @override @@ -35,8 +34,7 @@ class RenderHorizontalRule extends RenderEditableBox { RenderHorizontalRule({ @required EmbedNode node, - @required BuildContext context, - }) : _node = node, _context = context; + }) : _node = node; @override EmbedNode get node => _node; @@ -47,8 +45,6 @@ class RenderHorizontalRule extends RenderEditableBox { markNeedsPaint(); } - BuildContext _context; - @override double get preferredLineHeight => size.height; @@ -81,7 +77,7 @@ class RenderHorizontalRule extends RenderEditableBox { @override void paint(PaintingContext context, Offset offset) { final rect = new Rect.fromLTWH(0.0, 0.0, size.width, _kThickness); - final paint = new ui.Paint()..color = ZefyrTheme.of(_context).horizontalRuleColor; + final paint = new ui.Paint()..color = Colors.grey.shade200; context.canvas.drawRect(rect.shift(offset), paint); } diff --git a/packages/zefyr/lib/src/widgets/quote.dart b/packages/zefyr/lib/src/widgets/quote.dart index 4975eb763..a9eacd138 100644 --- a/packages/zefyr/lib/src/widgets/quote.dart +++ b/packages/zefyr/lib/src/widgets/quote.dart @@ -19,7 +19,7 @@ class ZefyrQuote extends StatelessWidget { final style = theme.blockTheme.quote.textStyle; List items = []; for (var line in node.children) { - items.add(_buildLine(line, style, theme)); + items.add(_buildLine(line, style, theme.indentSize)); } return Padding( @@ -31,7 +31,7 @@ class ZefyrQuote extends StatelessWidget { ); } - Widget _buildLine(Node node, TextStyle blockStyle, ZefyrThemeData theme) { + Widget _buildLine(Node node, TextStyle blockStyle, double indentSize) { LineNode line = node; Widget content; @@ -45,10 +45,10 @@ class ZefyrQuote extends StatelessWidget { return Container( decoration: BoxDecoration( border: Border( - left: BorderSide(width: 4.0, color: theme.blockTheme.quote.backgroundColor), + left: BorderSide(width: 4.0, color: Colors.grey.shade300), ), ), - padding: EdgeInsets.only(left: theme.indentSize), + padding: EdgeInsets.only(left: indentSize), child: row, ); } diff --git a/packages/zefyr/lib/src/widgets/theme.dart b/packages/zefyr/lib/src/widgets/theme.dart index c7e1a894a..0f7c11602 100644 --- a/packages/zefyr/lib/src/widgets/theme.dart +++ b/packages/zefyr/lib/src/widgets/theme.dart @@ -59,7 +59,6 @@ class ZefyrThemeData { final StyleTheme paragraphTheme; final HeadingTheme headingTheme; final BlockTheme blockTheme; - final Color horizontalRuleColor; final Color selectionColor; final Color cursorColor; @@ -89,7 +88,6 @@ class ZefyrThemeData { new StyleTheme(textStyle: paragraphStyle, padding: padding), headingTheme: new HeadingTheme.fallback(), blockTheme: new BlockTheme.fallback(), - horizontalRuleColor: Colors.grey.shade200, selectionColor: Colors.lightBlueAccent.shade100, cursorColor: Colors.black, indentSize: 16.0, @@ -104,7 +102,6 @@ class ZefyrThemeData { this.paragraphTheme, this.headingTheme, this.blockTheme, - this.horizontalRuleColor, this.selectionColor, this.cursorColor, this.indentSize, @@ -119,7 +116,6 @@ class ZefyrThemeData { StyleTheme paragraphTheme, HeadingTheme headingTheme, BlockTheme blockTheme, - Color horizontalRuleColor, Color selectionColor, Color cursorColor, double indentSize, @@ -132,7 +128,6 @@ class ZefyrThemeData { paragraphTheme: paragraphTheme ?? this.paragraphTheme, headingTheme: headingTheme ?? this.headingTheme, blockTheme: blockTheme ?? this.blockTheme, - horizontalRuleColor: horizontalRuleColor?? this.horizontalRuleColor, selectionColor: selectionColor ?? this.selectionColor, cursorColor: cursorColor ?? this.cursorColor, indentSize: indentSize ?? this.indentSize, @@ -148,7 +143,6 @@ class ZefyrThemeData { paragraphTheme: other.paragraphTheme, headingTheme: other.headingTheme, blockTheme: other.blockTheme, - horizontalRuleColor: other.horizontalRuleColor, selectionColor: other.selectionColor, cursorColor: other.cursorColor, indentSize: other.indentSize, @@ -238,7 +232,6 @@ class BlockTheme { quote: new StyleTheme( textStyle: new TextStyle(color: Colors.grey.shade700), padding: padding, - backgroundColor: Colors.grey.shade300, ), code: new StyleTheme( textStyle: new TextStyle( @@ -248,7 +241,6 @@ class BlockTheme { height: 1.25, ), padding: padding, - backgroundColor: Colors.blueGrey.shade50, ), ); } @@ -265,14 +257,10 @@ class StyleTheme { /// Padding to apply around lines of text. final EdgeInsets padding; - /// Background color of this theme - final Color backgroundColor; - /// Creates a new [StyleTheme]. StyleTheme({ this.textStyle, this.padding, - this.backgroundColor, }); } From 039bb3d3fd3f27faeebd3891337b7a58edbabf65 Mon Sep 17 00:00:00 2001 From: xxdocobxx Date: Wed, 15 May 2019 00:40:39 +0800 Subject: [PATCH 3/3] Custom URL launcher - Added the parameter onLaunchUrl to ZefyrEditor and ZefyrView. - Impletemented launchUrl on ZefyrView. --- packages/zefyr/lib/src/widgets/buttons.dart | 5 +--- packages/zefyr/lib/src/widgets/common.dart | 30 ++++++++++++++++++- .../zefyr/lib/src/widgets/editable_text.dart | 2 ++ packages/zefyr/lib/src/widgets/editor.dart | 19 ++++++++++++ packages/zefyr/lib/src/widgets/scope.dart | 23 ++++++++++++-- packages/zefyr/lib/src/widgets/view.dart | 25 +++++++++++++--- 6 files changed, 92 insertions(+), 12 deletions(-) diff --git a/packages/zefyr/lib/src/widgets/buttons.dart b/packages/zefyr/lib/src/widgets/buttons.dart index 675f4ea38..2bd61f00a 100644 --- a/packages/zefyr/lib/src/widgets/buttons.dart +++ b/packages/zefyr/lib/src/widgets/buttons.dart @@ -411,10 +411,7 @@ class _LinkButtonState extends State { final editor = ZefyrToolbar.of(context).editor; var link = getLink(); assert(link != null); - if (await canLaunch(link)) { - editor.hideKeyboard(); - await launch(link, forceWebView: true); - } + await ZefyrToolbar.of(context).editor.onLaunchUrl(link); } void _handleInputChange() { diff --git a/packages/zefyr/lib/src/widgets/common.dart b/packages/zefyr/lib/src/widgets/common.dart index aabc8b8f1..380eb741e 100644 --- a/packages/zefyr/lib/src/widgets/common.dart +++ b/packages/zefyr/lib/src/widgets/common.dart @@ -1,9 +1,11 @@ // Copyright (c) 2018, the Zefyr project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. + import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:notus/notus.dart'; +import 'package:flutter/gestures.dart'; import 'editable_box.dart'; import 'horizontal_rule.dart'; @@ -110,9 +112,20 @@ class _RawZefyrLineState extends State { TextSpan buildText(BuildContext context) { final theme = ZefyrTheme.of(context); - final List children = widget.node.children + + List children; + + if(ZefyrScope.of(context).isEditable) { + children = widget.node.children .map((node) => _segmentToTextSpan(node, theme)) .toList(growable: false); + } else { + children = widget.node.children + .map((node) => _segmentToTextSpanView(node, theme)) + .toList(growable: true); + children.add(TextSpan(text: ' ', style: TextStyle(fontSize: 1.0))); + } + return new TextSpan(style: widget.style, children: children); } @@ -126,6 +139,21 @@ class _RawZefyrLineState extends State { ); } + TextSpan _segmentToTextSpanView(Node node, ZefyrThemeData theme) { + final TextNode segment = node; + final attrs = segment.style; + + return new TextSpan( + text: segment.value, + style: _getTextStyle(attrs, theme), + recognizer: (attrs.contains(NotusAttribute.link) ? + (new TapGestureRecognizer()..onTap = () async { + var link = attrs.get(NotusAttribute.link).value; + await ZefyrScope.of(context).onLaunchUrl(link); + }) : null), + ); + } + TextStyle _getTextStyle(NotusStyle style, ZefyrThemeData theme) { TextStyle result = new TextStyle(); if (style.containsSame(NotusAttribute.bold)) { diff --git a/packages/zefyr/lib/src/widgets/editable_text.dart b/packages/zefyr/lib/src/widgets/editable_text.dart index 59f01a738..4d63a0539 100644 --- a/packages/zefyr/lib/src/widgets/editable_text.dart +++ b/packages/zefyr/lib/src/widgets/editable_text.dart @@ -33,6 +33,7 @@ class ZefyrEditableText extends StatefulWidget { @required this.controller, @required this.focusNode, @required this.imageDelegate, + @required this.onLaunchUrl, this.autofocus: true, this.enabled: true, this.padding: const EdgeInsets.symmetric(horizontal: 16.0), @@ -42,6 +43,7 @@ class ZefyrEditableText extends StatefulWidget { final ZefyrController controller; final FocusNode focusNode; final ZefyrImageDelegate imageDelegate; + final Function onLaunchUrl; final bool autofocus; final bool enabled; final ScrollPhysics physics; diff --git a/packages/zefyr/lib/src/widgets/editor.dart b/packages/zefyr/lib/src/widgets/editor.dart index 4a37337e8..bccaee43d 100644 --- a/packages/zefyr/lib/src/widgets/editor.dart +++ b/packages/zefyr/lib/src/widgets/editor.dart @@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:flutter/widgets.dart'; +import 'package:url_launcher/url_launcher.dart'; import 'controller.dart'; import 'editable_text.dart'; @@ -22,6 +23,7 @@ class ZefyrEditor extends StatefulWidget { this.padding: const EdgeInsets.symmetric(horizontal: 16.0), this.toolbarDelegate, this.imageDelegate, + this.onLaunchUrl, this.physics, }) : super(key: key); @@ -31,6 +33,7 @@ class ZefyrEditor extends StatefulWidget { final bool enabled; final ZefyrToolbarDelegate toolbarDelegate; final ZefyrImageDelegate imageDelegate; + final Function onLaunchUrl; final ScrollPhysics physics; /// Padding around editable area. @@ -42,6 +45,7 @@ class ZefyrEditor extends StatefulWidget { class _ZefyrEditorState extends State { ZefyrImageDelegate _imageDelegate; + Function _onLaunchUrl; ZefyrScope _scope; ZefyrThemeData _themeData; GlobalKey _toolbarKey; @@ -85,10 +89,18 @@ class _ZefyrEditorState extends State { } } + Future _launchUrl(String link) async { + if(await canLaunch(link)) { + await launch(link, forceWebView: true); + } + } + @override void initState() { super.initState(); _imageDelegate = widget.imageDelegate ?? new ZefyrDefaultImageDelegate(); + + _onLaunchUrl = widget.onLaunchUrl ?? _launchUrl; } @override @@ -100,6 +112,11 @@ class _ZefyrEditorState extends State { _imageDelegate = widget.imageDelegate ?? new ZefyrDefaultImageDelegate(); _scope.imageDelegate = _imageDelegate; } + + if (widget.onLaunchUrl != oldWidget.onLaunchUrl) { + _onLaunchUrl = widget.onLaunchUrl ?? _launchUrl; + _scope.onLaunchUrl = _onLaunchUrl; + } } @override @@ -114,6 +131,7 @@ class _ZefyrEditorState extends State { if (_scope == null) { _scope = ZefyrScope.editable( imageDelegate: _imageDelegate, + onLaunchUrl: _onLaunchUrl, controller: widget.controller, focusNode: widget.focusNode, focusScope: FocusScope.of(context), @@ -147,6 +165,7 @@ class _ZefyrEditorState extends State { controller: _scope.controller, focusNode: _scope.focusNode, imageDelegate: _scope.imageDelegate, + onLaunchUrl: _scope.onLaunchUrl, autofocus: widget.autofocus, enabled: widget.enabled, padding: widget.padding, diff --git a/packages/zefyr/lib/src/widgets/scope.dart b/packages/zefyr/lib/src/widgets/scope.dart index 2853a8a20..399c99a1d 100644 --- a/packages/zefyr/lib/src/widgets/scope.dart +++ b/packages/zefyr/lib/src/widgets/scope.dart @@ -24,10 +24,14 @@ class ZefyrScope extends ChangeNotifier { /// Creates a view-only scope. /// /// Normally used in [ZefyrView]. - ZefyrScope.view({@required ZefyrImageDelegate imageDelegate}) - : assert(imageDelegate != null), + ZefyrScope.view({ + @required ZefyrImageDelegate imageDelegate, + @required Future onLaunchUrl(String url), + }) : assert(imageDelegate != null), + assert(onLaunchUrl != null), isEditable = false, - _imageDelegate = imageDelegate; + _imageDelegate = imageDelegate, + _onLaunchUrl = onLaunchUrl; /// Creates editable scope. /// @@ -35,15 +39,18 @@ class ZefyrScope extends ChangeNotifier { ZefyrScope.editable({ @required ZefyrController controller, @required ZefyrImageDelegate imageDelegate, + @required Future onLaunchUrl(String url), @required FocusNode focusNode, @required FocusScopeNode focusScope, }) : assert(controller != null), assert(imageDelegate != null), + assert(onLaunchUrl != null), assert(focusNode != null), assert(focusScope != null), isEditable = true, _controller = controller, _imageDelegate = imageDelegate, + _onLaunchUrl = onLaunchUrl, _focusNode = focusNode, _focusScope = focusScope, _cursorTimer = CursorTimer(), @@ -70,6 +77,16 @@ class ZefyrScope extends ChangeNotifier { } } + Function _onLaunchUrl; + Function get onLaunchUrl => _onLaunchUrl; + set onLaunchUrl(Future func(String url)) { + assert(func != null); + if (_onLaunchUrl != func) { + _onLaunchUrl = func; + notifyListeners(); + } + } + ZefyrController _controller; ZefyrController get controller => _controller; set controller(ZefyrController value) { diff --git a/packages/zefyr/lib/src/widgets/view.dart b/packages/zefyr/lib/src/widgets/view.dart index d7b7b13e3..bbba576d8 100644 --- a/packages/zefyr/lib/src/widgets/view.dart +++ b/packages/zefyr/lib/src/widgets/view.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; import 'package:notus/notus.dart'; +import 'package:url_launcher/url_launcher.dart'; import 'code.dart'; import 'common.dart'; @@ -16,9 +17,14 @@ import 'theme.dart'; class ZefyrView extends StatefulWidget { final NotusDocument document; final ZefyrImageDelegate imageDelegate; + final Function onLaunchUrl; - const ZefyrView({Key key, @required this.document, this.imageDelegate}) - : super(key: key); + const ZefyrView({ + Key key, + @required this.document, + this.imageDelegate, + this.onLaunchUrl, + }) : super(key: key); @override ZefyrViewState createState() => ZefyrViewState(); @@ -29,17 +35,22 @@ class ZefyrViewState extends State { ZefyrThemeData _themeData; ZefyrImageDelegate get imageDelegate => widget.imageDelegate; + Function get onLaunchUrl => widget.onLaunchUrl; @override void initState() { super.initState(); - _scope = ZefyrScope.view(imageDelegate: widget.imageDelegate); + _scope = ZefyrScope.view( + imageDelegate: widget.imageDelegate ?? new ZefyrDefaultImageDelegate(), + onLaunchUrl: widget.onLaunchUrl ?? _launchUrl, + ); } @override void didUpdateWidget(ZefyrView oldWidget) { super.didUpdateWidget(oldWidget); - _scope.imageDelegate = widget.imageDelegate; + _scope.imageDelegate = widget.imageDelegate ?? new ZefyrDefaultImageDelegate(); + _scope.onLaunchUrl = widget.onLaunchUrl ?? _launchUrl; } @override @@ -104,4 +115,10 @@ class ZefyrViewState extends State { throw new UnimplementedError('Block format $blockStyle.'); } + + Future _launchUrl(String link) async { + if(await canLaunch(link)) { + await launch(link, forceWebView: true); + } + } }