|
@@ -866,7 +866,7 @@ class _LinkButtonState extends State<LinkButton> {
|
866
|
866
|
|
867
|
867
|
bool hasLink(NotusStyle style) => style.contains(NotusAttribute.link);
|
868
|
868
|
|
869
|
|
- String getLink([String defaultValue]) {
|
|
869
|
+ String getLink([String defaultValue = '']) {
|
870
|
870
|
final editor = ZefyrToolbar.of(context).editor;
|
871
|
871
|
final attrs = editor.selectionStyle;
|
872
|
872
|
if (hasLink(attrs)) {
|
|
@@ -875,26 +875,25 @@ class _LinkButtonState extends State<LinkButton> {
|
875
|
875
|
return defaultValue;
|
876
|
876
|
}
|
877
|
877
|
|
|
878
|
+ String getText([String defaultValue = '']) {
|
|
879
|
+ final editor = ZefyrToolbar.of(context).editor;
|
|
880
|
+ final plainTextEditingValue = editor.controller.plainTextEditingValue;
|
|
881
|
+ if (!editor.selection.isCollapsed) {
|
|
882
|
+ return plainTextEditingValue.text.substring(editor.selection.start, editor.selection.end);
|
|
883
|
+ }
|
|
884
|
+ return defaultValue;
|
|
885
|
+ }
|
|
886
|
+
|
878
|
887
|
OverlayEntry _overlayEntry;
|
879
|
888
|
|
880
|
889
|
Future<void> showOverlay() async {
|
881
|
890
|
final editor = ZefyrToolbar.of(context).editor;
|
882
|
891
|
editor.closeKeyboard(true);
|
883
|
892
|
var _selection = editor.selection;
|
884
|
|
- var value = ZefyrLinkEntity();
|
885
|
|
- if (hasLink(editor.selectionStyle)) {
|
886
|
|
- value =
|
887
|
|
- value.copyWith(url: editor.selectionStyle.value(NotusAttribute.link));
|
888
|
|
- }
|
889
|
|
- // 已选中
|
890
|
|
- if (!editor.selection.isCollapsed) {
|
891
|
|
- var text = editor.controller.document
|
892
|
|
- .toPlainText()
|
893
|
|
- .substring(editor.selection.start, editor.selection.end);
|
894
|
|
- value = value.copyWith(text: text);
|
895
|
|
- }
|
896
|
|
- ;
|
897
|
|
- var result = await editor.linkDelegate.fillLink(context, value);
|
|
893
|
+ var result = await editor.linkDelegate.fillLink(context, ZefyrLinkEntity(
|
|
894
|
+ text: getText(),
|
|
895
|
+ url: getLink(),
|
|
896
|
+ ));
|
898
|
897
|
|
899
|
898
|
if (result != null) {
|
900
|
899
|
// toolbar.editor.updateSelection(_selection, source: ChangeSource.local);
|
|
@@ -997,160 +996,5 @@ class _LinkButtonState extends State<LinkButton> {
|
997
|
996
|
toolbar.markNeedsRebuild();
|
998
|
997
|
});
|
999
|
998
|
}
|
1000
|
|
-
|
1001
|
|
- Widget buildOverlay(BuildContext context) {
|
1002
|
|
- final toolbar = ZefyrToolbar.of(context);
|
1003
|
|
- final style = toolbar.editor.selectionStyle;
|
1004
|
|
-
|
1005
|
|
- String value = 'Tap to edit link';
|
1006
|
|
- if (style.contains(NotusAttribute.link)) {
|
1007
|
|
- value = style.value(NotusAttribute.link);
|
1008
|
|
- }
|
1009
|
|
- final clipboardEnabled = value != 'Tap to edit link';
|
1010
|
|
- final body = !isEditing
|
1011
|
|
- ? _LinkView(value: value, onTap: edit)
|
1012
|
|
- : _LinkInput(
|
1013
|
|
- key: _inputKey,
|
1014
|
|
- controller: _inputController,
|
1015
|
|
- formatError: _formatError,
|
1016
|
|
- );
|
1017
|
|
- final items = <Widget>[Expanded(child: body)];
|
1018
|
|
- if (!isEditing) {
|
1019
|
|
- final unlinkHandler = hasLink(style) ? unlink : null;
|
1020
|
|
- final copyHandler = clipboardEnabled ? copyToClipboard : null;
|
1021
|
|
- final openHandler = hasLink(style) ? openInBrowser : null;
|
1022
|
|
- final buttons = <Widget>[
|
1023
|
|
- toolbar.buildButton(context, ZefyrToolbarAction.unlink,
|
1024
|
|
- onPressed: unlinkHandler),
|
1025
|
|
- toolbar.buildButton(context, ZefyrToolbarAction.clipboardCopy,
|
1026
|
|
- onPressed: copyHandler),
|
1027
|
|
- toolbar.buildButton(
|
1028
|
|
- context,
|
1029
|
|
- ZefyrToolbarAction.openInBrowser,
|
1030
|
|
- onPressed: openHandler,
|
1031
|
|
- ),
|
1032
|
|
- ];
|
1033
|
|
- items.addAll(buttons);
|
1034
|
|
- }
|
1035
|
|
- final trailingPressed = isEditing ? doneEdit : closeOverlay;
|
1036
|
|
- final trailingAction =
|
1037
|
|
- isEditing ? ZefyrToolbarAction.confirm : ZefyrToolbarAction.close;
|
1038
|
|
-
|
1039
|
|
- return ZefyrToolbarScaffold(
|
1040
|
|
- body: Row(children: items),
|
1041
|
|
- trailing: toolbar.buildButton(
|
1042
|
|
- context,
|
1043
|
|
- trailingAction,
|
1044
|
|
- onPressed: trailingPressed,
|
1045
|
|
- ),
|
1046
|
|
- );
|
1047
|
|
- }
|
1048
|
999
|
}
|
1049
|
1000
|
|
1050
|
|
-class _LinkInput extends StatefulWidget {
|
1051
|
|
- final TextEditingController controller;
|
1052
|
|
- final bool formatError;
|
1053
|
|
-
|
1054
|
|
- const _LinkInput(
|
1055
|
|
- {Key key, @required this.controller, this.formatError = false})
|
1056
|
|
- : super(key: key);
|
1057
|
|
-
|
1058
|
|
- @override
|
1059
|
|
- _LinkInputState createState() {
|
1060
|
|
- return _LinkInputState();
|
1061
|
|
- }
|
1062
|
|
-}
|
1063
|
|
-
|
1064
|
|
-class _LinkInputState extends State<_LinkInput> {
|
1065
|
|
- final FocusNode _focusNode = FocusNode();
|
1066
|
|
-
|
1067
|
|
- ZefyrScope _editor;
|
1068
|
|
- bool _didAutoFocus = false;
|
1069
|
|
-
|
1070
|
|
- @override
|
1071
|
|
- void didChangeDependencies() {
|
1072
|
|
- super.didChangeDependencies();
|
1073
|
|
- if (!_didAutoFocus) {
|
1074
|
|
- FocusScope.of(context).requestFocus(_focusNode);
|
1075
|
|
- _didAutoFocus = true;
|
1076
|
|
- }
|
1077
|
|
-
|
1078
|
|
- final toolbar = ZefyrToolbar.of(context);
|
1079
|
|
-
|
1080
|
|
- if (_editor != toolbar.editor) {
|
1081
|
|
- _editor?.toolbarFocusNode = null;
|
1082
|
|
- _editor = toolbar.editor;
|
1083
|
|
- _editor.toolbarFocusNode = _focusNode;
|
1084
|
|
- }
|
1085
|
|
- }
|
1086
|
|
-
|
1087
|
|
- @override
|
1088
|
|
- void dispose() {
|
1089
|
|
- _editor?.toolbarFocusNode = null;
|
1090
|
|
- _focusNode.dispose();
|
1091
|
|
- _editor = null;
|
1092
|
|
- super.dispose();
|
1093
|
|
- }
|
1094
|
|
-
|
1095
|
|
- @override
|
1096
|
|
- Widget build(BuildContext context) {
|
1097
|
|
- final theme = Theme.of(context);
|
1098
|
|
- final toolbarTheme = ZefyrTheme.of(context).toolbarTheme;
|
1099
|
|
- final color =
|
1100
|
|
- widget.formatError ? Colors.redAccent : toolbarTheme.iconColor;
|
1101
|
|
- final style = theme.textTheme.subhead.copyWith(color: color);
|
1102
|
|
- return TextField(
|
1103
|
|
- style: style,
|
1104
|
|
- keyboardType: TextInputType.url,
|
1105
|
|
- focusNode: _focusNode,
|
1106
|
|
- controller: widget.controller,
|
1107
|
|
- autofocus: true,
|
1108
|
|
- decoration: InputDecoration(
|
1109
|
|
- hintText: 'https://',
|
1110
|
|
- filled: true,
|
1111
|
|
- fillColor: toolbarTheme.color,
|
1112
|
|
- border: InputBorder.none,
|
1113
|
|
- contentPadding: const EdgeInsets.all(10.0),
|
1114
|
|
- ),
|
1115
|
|
- );
|
1116
|
|
- }
|
1117
|
|
-}
|
1118
|
|
-
|
1119
|
|
-class _LinkView extends StatelessWidget {
|
1120
|
|
- const _LinkView({Key key, @required this.value, this.onTap})
|
1121
|
|
- : super(key: key);
|
1122
|
|
- final String value;
|
1123
|
|
- final VoidCallback onTap;
|
1124
|
|
-
|
1125
|
|
- @override
|
1126
|
|
- Widget build(BuildContext context) {
|
1127
|
|
- final theme = Theme.of(context);
|
1128
|
|
- final toolbarTheme = ZefyrTheme.of(context).toolbarTheme;
|
1129
|
|
- Widget widget = ClipRect(
|
1130
|
|
- child: ListView(
|
1131
|
|
- scrollDirection: Axis.horizontal,
|
1132
|
|
- children: <Widget>[
|
1133
|
|
- Container(
|
1134
|
|
- alignment: AlignmentDirectional.centerStart,
|
1135
|
|
- constraints: BoxConstraints(minHeight: ZefyrToolbar.kToolbarHeight),
|
1136
|
|
- padding: const EdgeInsets.all(10.0),
|
1137
|
|
- child: Text(
|
1138
|
|
- value,
|
1139
|
|
- maxLines: 1,
|
1140
|
|
- overflow: TextOverflow.ellipsis,
|
1141
|
|
- style: theme.textTheme.subhead
|
1142
|
|
- .copyWith(color: toolbarTheme.disabledIconColor),
|
1143
|
|
- ),
|
1144
|
|
- )
|
1145
|
|
- ],
|
1146
|
|
- ),
|
1147
|
|
- );
|
1148
|
|
- if (onTap != null) {
|
1149
|
|
- widget = GestureDetector(
|
1150
|
|
- child: widget,
|
1151
|
|
- onTap: onTap,
|
1152
|
|
- );
|
1153
|
|
- }
|
1154
|
|
- return widget;
|
1155
|
|
- }
|
1156
|
|
-}
|