|
@@ -118,16 +118,16 @@ class ZefyrButton extends StatelessWidget {
|
118
|
118
|
|
119
|
119
|
Color _getColor(ZefyrScope editor, ToolbarTheme theme) {
|
120
|
120
|
if (kToolbarButtonIcons.contains(action)) {
|
121
|
|
- return editor.toolbarAction == action ? theme.toggleColor : theme.surfaceColor;
|
|
121
|
+ return editor.toolbarAction == action
|
|
122
|
+ ? theme.toggleColor
|
|
123
|
+ : theme.surfaceColor;
|
122
|
124
|
} else {
|
123
|
125
|
if (isAttributeAction) {
|
124
|
126
|
final attribute = kZefyrToolbarAttributeActions[action];
|
125
|
127
|
final isToggled = (attribute is NotusAttribute)
|
126
|
128
|
? editor.selectionStyle.containsSame(attribute)
|
127
|
129
|
: editor.selectionStyle.contains(attribute);
|
128
|
|
- return isToggled
|
129
|
|
- ? theme.toggleColor
|
130
|
|
- : theme.iconColor;
|
|
130
|
+ return isToggled ? theme.toggleColor : theme.iconColor;
|
131
|
131
|
}
|
132
|
132
|
return null;
|
133
|
133
|
}
|
|
@@ -262,7 +262,7 @@ class RawZefyrButton extends StatelessWidget {
|
262
|
262
|
|
263
|
263
|
// Widget button = Row(
|
264
|
264
|
// children: <Widget>[
|
265
|
|
-
|
|
265
|
+
|
266
|
266
|
// // if (action == ZefyrToolbarAction.showKeyboard || action == ZefyrToolbarAction.hideKeyboard || action == ZefyrToolbarAction.link)
|
267
|
267
|
// // Container(
|
268
|
268
|
// // width: 1,
|
|
@@ -328,9 +328,18 @@ class _HeadingButtonState extends State<HeadingButton> {
|
328
|
328
|
);
|
329
|
329
|
}
|
330
|
330
|
|
|
331
|
+ bool hasColor(NotusStyle style, String color) {
|
|
332
|
+ if (style.contains(NotusAttribute.color)) {
|
|
333
|
+ var _style = style.get(NotusAttribute.color);
|
|
334
|
+ return _style.value.toLowerCase() == color.toLowerCase();
|
|
335
|
+ }
|
|
336
|
+ return false;
|
|
337
|
+ }
|
|
338
|
+
|
331
|
339
|
Widget buildOverlay(BuildContext context) {
|
332
|
340
|
final theme = ZefyrTheme.of(context).toolbarTheme;
|
333
|
341
|
final toolbar = ZefyrToolbar.of(context);
|
|
342
|
+
|
334
|
343
|
final headingButtons = <Widget>[
|
335
|
344
|
toolbar.buildButton(context, ZefyrToolbarAction.headingLevel1),
|
336
|
345
|
toolbar.buildButton(context, ZefyrToolbarAction.headingLevel2),
|
|
@@ -354,112 +363,110 @@ class _HeadingButtonState extends State<HeadingButton> {
|
354
|
363
|
toolbar.buildButton(context, ZefyrToolbarAction.horizontalRule),
|
355
|
364
|
toolbar.buildButton(context, ZefyrToolbarAction.code),
|
356
|
365
|
];
|
|
366
|
+ final textColors = [
|
|
367
|
+ ZefyrTheme.of(context).defaultLineTheme.textStyle.color, ...List.of(kTextColors),
|
|
368
|
+ ];
|
|
369
|
+
|
357
|
370
|
return Material(
|
358
|
371
|
color: theme.color,
|
359
|
372
|
child: Container(
|
360
|
373
|
decoration: BoxDecoration(
|
361
|
374
|
border: Border(top: BorderSide(color: theme.dividerColor, width: 1)),
|
362
|
375
|
),
|
363
|
|
- child: Column(
|
364
|
|
- children: [
|
365
|
|
- Container(
|
366
|
|
- padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15),
|
367
|
|
- child: Column(
|
368
|
|
- children: [
|
369
|
|
- _buildButtonsView(headingButtons),
|
370
|
|
- _buildButtonsView(textButtons),
|
371
|
|
- _buildButtonsView(listButtons),
|
372
|
|
- _buildButtonsView(otherButtons),
|
373
|
|
- ],
|
374
|
|
- ),
|
375
|
|
- ),
|
376
|
|
- Container(
|
377
|
|
- decoration: BoxDecoration(
|
378
|
|
- border: Border(
|
379
|
|
- top: BorderSide(color: theme.dividerColor, width: 1)),
|
|
376
|
+ child: SingleChildScrollView(
|
|
377
|
+ physics: ClampingScrollPhysics(),
|
|
378
|
+ child: Column(
|
|
379
|
+ children: [
|
|
380
|
+ Container(
|
|
381
|
+ padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15),
|
|
382
|
+ child: Column(
|
|
383
|
+ children: [
|
|
384
|
+ _buildButtonsView(headingButtons),
|
|
385
|
+ _buildButtonsView(textButtons),
|
|
386
|
+ _buildButtonsView(listButtons),
|
|
387
|
+ _buildButtonsView(otherButtons),
|
|
388
|
+ ],
|
|
389
|
+ ),
|
380
|
390
|
),
|
381
|
|
- padding: EdgeInsets.symmetric(vertical: 16),
|
382
|
|
- margin: EdgeInsets.symmetric(horizontal: 16),
|
383
|
|
- child: Row(
|
384
|
|
- children: <Widget>[
|
385
|
|
- Padding(
|
386
|
|
- padding: EdgeInsets.only(right: 12),
|
387
|
|
- child: Text(
|
388
|
|
- '文字色',
|
389
|
|
- style: Theme.of(context).textTheme.caption.copyWith(
|
390
|
|
- color: Theme.of(context).colorScheme.onSurface,
|
391
|
|
- fontSize: 14,
|
392
|
|
- fontWeight: FontWeight.w500,
|
393
|
|
- ),
|
394
|
|
- ),
|
395
|
|
- ),
|
396
|
|
- Expanded(
|
397
|
|
- child: Container(
|
398
|
|
- height: 20,
|
399
|
|
- child: ListView(
|
400
|
|
- scrollDirection: Axis.horizontal,
|
401
|
|
- children: [
|
402
|
|
- Container(
|
403
|
|
- padding: EdgeInsets.all(1),
|
404
|
|
- decoration: ShapeDecoration(
|
405
|
|
- shape: CircleBorder(
|
406
|
|
- side: BorderSide(
|
407
|
|
- width: 1, color: theme.toggleColor),
|
408
|
|
- ),
|
409
|
|
- ),
|
410
|
|
- margin: EdgeInsets.symmetric(horizontal: 8),
|
411
|
|
- child: Container(
|
412
|
|
- width: 16,
|
413
|
|
- height: 16,
|
414
|
|
- decoration: ShapeDecoration(
|
415
|
|
- color: Color(0xFFE02020),
|
416
|
|
- shape: CircleBorder(),
|
417
|
|
- ),
|
418
|
|
- ),
|
419
|
|
- ),
|
420
|
|
- Container(
|
421
|
|
- padding: EdgeInsets.all(1),
|
422
|
|
- decoration: ShapeDecoration(
|
423
|
|
- shape: CircleBorder(
|
424
|
|
- side: BorderSide.none,
|
425
|
|
- ),
|
426
|
|
- ),
|
427
|
|
- margin: EdgeInsets.symmetric(horizontal: 8),
|
428
|
|
- child: Container(
|
429
|
|
- width: 16,
|
430
|
|
- height: 16,
|
431
|
|
- decoration: ShapeDecoration(
|
432
|
|
- color: Color(0xFFFA6400),
|
433
|
|
- shape: CircleBorder(),
|
434
|
|
- ),
|
435
|
|
- ),
|
436
|
|
- ),
|
437
|
|
- Container(
|
438
|
|
- padding: EdgeInsets.all(1),
|
439
|
|
- decoration: ShapeDecoration(
|
440
|
|
- shape: CircleBorder(
|
441
|
|
- side: BorderSide.none,
|
442
|
|
- ),
|
|
391
|
+ Container(
|
|
392
|
+ decoration: BoxDecoration(
|
|
393
|
+ border: Border(
|
|
394
|
+ top: BorderSide(color: theme.dividerColor, width: 1)),
|
|
395
|
+ ),
|
|
396
|
+ padding: EdgeInsets.symmetric(vertical: 16),
|
|
397
|
+ margin: EdgeInsets.symmetric(horizontal: 16),
|
|
398
|
+ child: Row(
|
|
399
|
+ children: <Widget>[
|
|
400
|
+ Padding(
|
|
401
|
+ padding: EdgeInsets.only(right: 12),
|
|
402
|
+ child: Text(
|
|
403
|
+ '文字色',
|
|
404
|
+ style: Theme.of(context).textTheme.caption.copyWith(
|
|
405
|
+ color: Theme.of(context).colorScheme.onSurface,
|
|
406
|
+ fontSize: 14,
|
|
407
|
+ fontWeight: FontWeight.w500,
|
443
|
408
|
),
|
444
|
|
- margin: EdgeInsets.symmetric(horizontal: 8),
|
445
|
|
- child: Container(
|
446
|
|
- width: 16,
|
447
|
|
- height: 16,
|
448
|
|
- decoration: ShapeDecoration(
|
449
|
|
- color: Color(0xFF0091FF),
|
450
|
|
- shape: CircleBorder(),
|
|
409
|
+ ),
|
|
410
|
+ ),
|
|
411
|
+ Expanded(
|
|
412
|
+ child: Container(
|
|
413
|
+ height: 20,
|
|
414
|
+ child: ListView(
|
|
415
|
+ scrollDirection: Axis.horizontal,
|
|
416
|
+ children: textColors.map((color) {
|
|
417
|
+ var hex = color.value.toRadixString(16).substring(2, 8);
|
|
418
|
+ var has = false;
|
|
419
|
+ if (!toolbar.editor.selectionStyle.contains(NotusAttribute.color)) {
|
|
420
|
+ if (color == ZefyrTheme.of(context).defaultLineTheme.textStyle.color) {
|
|
421
|
+ has = true;
|
|
422
|
+ }
|
|
423
|
+ } else {
|
|
424
|
+ has = hasColor(toolbar.editor.selectionStyle, '#$hex');
|
|
425
|
+ }
|
|
426
|
+ // var key = kTextColors[index].value;
|
|
427
|
+ return GestureDetector(
|
|
428
|
+ behavior: HitTestBehavior.translucent,
|
|
429
|
+ onTap: () {
|
|
430
|
+ toolbar.editor.formatSelection(NotusAttribute.color.fromString('#$hex'));
|
|
431
|
+ },
|
|
432
|
+ child: Container(
|
|
433
|
+ padding: EdgeInsets.all(1),
|
|
434
|
+ width: 20,
|
|
435
|
+ height: 20,
|
|
436
|
+ decoration: ShapeDecoration(
|
|
437
|
+ shape: CircleBorder(
|
|
438
|
+ side: has ? BorderSide(
|
|
439
|
+ width: 1,
|
|
440
|
+ color: theme.toggleColor,
|
|
441
|
+ ) : BorderSide.none,
|
|
442
|
+ ),
|
|
443
|
+ ),
|
|
444
|
+ margin: EdgeInsets.symmetric(horizontal: 8),
|
|
445
|
+ child: Container(
|
|
446
|
+ // width: 16,
|
|
447
|
+ // height: 16,
|
|
448
|
+ decoration: ShapeDecoration(
|
|
449
|
+ color: color,
|
|
450
|
+ shape: CircleBorder(
|
|
451
|
+ side: color == Color(0xFFFFFFFF) && !has ? BorderSide(
|
|
452
|
+ width: 1,
|
|
453
|
+ color: theme.dividerColor,
|
|
454
|
+ ) : BorderSide.none,
|
|
455
|
+ ),
|
|
456
|
+ ),
|
|
457
|
+ ),
|
451
|
458
|
),
|
452
|
|
- ),
|
453
|
|
- ),
|
454
|
|
- ],
|
455
|
|
- physics: ClampingScrollPhysics(),
|
|
459
|
+ );
|
|
460
|
+ }).toList(),
|
|
461
|
+ physics: ClampingScrollPhysics(),
|
|
462
|
+ ),
|
456
|
463
|
),
|
457
|
464
|
),
|
458
|
|
- ),
|
459
|
|
- ],
|
|
465
|
+ ],
|
|
466
|
+ ),
|
460
|
467
|
),
|
461
|
|
- ),
|
462
|
|
- ],
|
|
468
|
+ ],
|
|
469
|
+ ),
|
463
|
470
|
),
|
464
|
471
|
),
|
465
|
472
|
);
|
|
@@ -470,6 +477,45 @@ class _HeadingButtonState extends State<HeadingButton> {
|
470
|
477
|
}
|
471
|
478
|
}
|
472
|
479
|
|
|
480
|
+// class TextColorButton extends StatelessWidget {
|
|
481
|
+
|
|
482
|
+// const TextColorButton({Key key, String color, ZefyrThemeData theme}) : super(key: key);
|
|
483
|
+
|
|
484
|
+// @override
|
|
485
|
+// Widget build(BuildContext context) {
|
|
486
|
+// return GestureDetector(
|
|
487
|
+// behavior: HitTestBehavior.translucent,
|
|
488
|
+// onTap: () {
|
|
489
|
+// // onTap(color);
|
|
490
|
+// // toolbar.editor.formatSelection(NotusAttribute.color.fromString('#000000'));
|
|
491
|
+// },
|
|
492
|
+// child: Container(
|
|
493
|
+// padding: EdgeInsets.all(1),
|
|
494
|
+// decoration: ShapeDecoration(
|
|
495
|
+// shape: CircleBorder(
|
|
496
|
+// side: BorderSide(
|
|
497
|
+// width: 1,
|
|
498
|
+// color: theme,
|
|
499
|
+// ),
|
|
500
|
+// ),
|
|
501
|
+// ),
|
|
502
|
+// margin: EdgeInsets.symmetric(horizontal: 8),
|
|
503
|
+// child: Container(
|
|
504
|
+// width: 16,
|
|
505
|
+// height: 16,
|
|
506
|
+// decoration: ShapeDecoration(
|
|
507
|
+// color: ZefyrTheme.of(context)
|
|
508
|
+// .defaultLineTheme
|
|
509
|
+// .textStyle
|
|
510
|
+// .color,
|
|
511
|
+// shape: CircleBorder(),
|
|
512
|
+// ),
|
|
513
|
+// ),
|
|
514
|
+// ),
|
|
515
|
+// );
|
|
516
|
+// }
|
|
517
|
+// }
|
|
518
|
+
|
473
|
519
|
/// Controls image attribute.
|
474
|
520
|
///
|
475
|
521
|
/// When pressed, this button displays overlay toolbar with three
|
|
@@ -576,7 +622,10 @@ class _ImageButtonState extends State<ImageButton> {
|
576
|
622
|
shape: RoundedRectangleBorder(),
|
577
|
623
|
color: Color(0xFFF6F6F6),
|
578
|
624
|
onPressed: () {
|
579
|
|
- toolbar.editor.keepOverlay = true;
|
|
625
|
+ final editor =
|
|
626
|
+ ZefyrToolbar.of(context).editor;
|
|
627
|
+ // var _selection = toolbar.editor.selection;
|
|
628
|
+ editor.closeKeyboard(true);
|
580
|
629
|
PhotoPicker.pickAsset(
|
581
|
630
|
context: context,
|
582
|
631
|
rowCount: 4,
|
|
@@ -588,9 +637,6 @@ class _ImageButtonState extends State<ImageButton> {
|
588
|
637
|
photoPathList: null,
|
589
|
638
|
).then((PickedEntity entity) async {
|
590
|
639
|
if (entity.asset.isNotEmpty) {
|
591
|
|
- toolbar.closeOverlay();
|
592
|
|
- final editor =
|
593
|
|
- ZefyrToolbar.of(context).editor;
|
594
|
640
|
for (var asset in entity.asset) {
|
595
|
641
|
var file = await asset.originFile;
|
596
|
642
|
final image = await editor.imageDelegate
|
|
@@ -599,6 +645,7 @@ class _ImageButtonState extends State<ImageButton> {
|
599
|
645
|
editor.formatSelection(NotusAttribute
|
600
|
646
|
.embed
|
601
|
647
|
.image(image));
|
|
648
|
+ editor.closeKeyboard();
|
602
|
649
|
}
|
603
|
650
|
}
|
604
|
651
|
}
|
|
@@ -642,18 +689,19 @@ class _ImageButtonState extends State<ImageButton> {
|
642
|
689
|
initialData: PickedEntity(),
|
643
|
690
|
builder: (context, snapshot) {
|
644
|
691
|
return PhotoPicker.buildGallery(
|
645
|
|
- context: context,
|
646
|
|
- padding: 4,
|
647
|
|
- thumbSize: 300,
|
648
|
|
- itemRadio: 0.5,
|
649
|
|
- provider: I18nProvider.chinese,
|
650
|
|
- sortDelegate: SortDelegate.common,
|
651
|
|
- pickType: PickType.onlyImage,
|
652
|
|
- photoPathList: null,
|
653
|
|
- isFullImage: snapshot.data.isFullImage,
|
654
|
|
- onSelected: (PickedEntity entity) {
|
655
|
|
- pickedChangeController.add(entity);
|
656
|
|
- });
|
|
692
|
+ context: context,
|
|
693
|
+ padding: 4,
|
|
694
|
+ thumbSize: 300,
|
|
695
|
+ itemRadio: 0.5,
|
|
696
|
+ provider: I18nProvider.chinese,
|
|
697
|
+ sortDelegate: SortDelegate.common,
|
|
698
|
+ pickType: PickType.onlyImage,
|
|
699
|
+ photoPathList: null,
|
|
700
|
+ isFullImage: snapshot.data.isFullImage,
|
|
701
|
+ onSelected: (PickedEntity entity) {
|
|
702
|
+ pickedChangeController.add(entity);
|
|
703
|
+ },
|
|
704
|
+ );
|
657
|
705
|
},
|
658
|
706
|
),
|
659
|
707
|
),
|
|
@@ -724,15 +772,19 @@ class _ImageButtonState extends State<ImageButton> {
|
724
|
772
|
onPressed: snapshot.data.asset.isNotEmpty
|
725
|
773
|
? () async {
|
726
|
774
|
pickedChangeController.add(PickedEntity());
|
727
|
|
- toolbar.closeOverlay();
|
|
775
|
+ // toolbar.closeOverlay();
|
|
776
|
+ toolbar.editor.closeKeyboard(true);
|
728
|
777
|
for (var asset in snapshot.data.asset) {
|
729
|
778
|
var file = await asset.originFile;
|
730
|
779
|
final image = await toolbar
|
731
|
780
|
.editor.imageDelegate
|
732
|
781
|
.picked(file, snapshot.data.isFullImage);
|
733
|
782
|
if (image != null) {
|
|
783
|
+ // toolbar.editor.toolbarAction = null;
|
|
784
|
+ // toolbar.editor.keepOverlay = true;
|
734
|
785
|
toolbar.editor.formatSelection(
|
735
|
786
|
NotusAttribute.embed.image(image));
|
|
787
|
+ toolbar.editor.closeKeyboard();
|
736
|
788
|
}
|
737
|
789
|
}
|
738
|
790
|
}
|
|
@@ -826,27 +878,35 @@ class _LinkButtonState extends State<LinkButton> {
|
826
|
878
|
OverlayEntry _overlayEntry;
|
827
|
879
|
|
828
|
880
|
Future<void> showOverlay() async {
|
829
|
|
- final toolbar = ZefyrToolbar.of(context);
|
830
|
|
- var _selection = toolbar.editor.selection;
|
|
881
|
+ final editor = ZefyrToolbar.of(context).editor;
|
|
882
|
+ editor.closeKeyboard(true);
|
|
883
|
+ var _selection = editor.selection;
|
831
|
884
|
var value = ZefyrLinkEntity();
|
832
|
|
- if (hasLink(toolbar.editor.selectionStyle)) {
|
833
|
|
- value = value.copyWith(url: toolbar.editor.selectionStyle.value(NotusAttribute.link));
|
|
885
|
+ if (hasLink(editor.selectionStyle)) {
|
|
886
|
+ value =
|
|
887
|
+ value.copyWith(url: editor.selectionStyle.value(NotusAttribute.link));
|
834
|
888
|
}
|
835
|
889
|
// 已选中
|
836
|
|
- if(!toolbar.editor.selection.isCollapsed) {
|
837
|
|
- var text = toolbar.editor.controller.document.toPlainText().substring(toolbar.editor.selection.start, toolbar.editor.selection.end);
|
|
890
|
+ if (!editor.selection.isCollapsed) {
|
|
891
|
+ var text = editor.controller.document
|
|
892
|
+ .toPlainText()
|
|
893
|
+ .substring(editor.selection.start, editor.selection.end);
|
838
|
894
|
value = value.copyWith(text: text);
|
839
|
|
- };
|
840
|
|
- var result = await toolbar.editor.linkDelegate.fillLink(context, value);
|
841
|
|
-
|
|
895
|
+ }
|
|
896
|
+ ;
|
|
897
|
+ var result = await editor.linkDelegate.fillLink(context, value);
|
|
898
|
+
|
842
|
899
|
if (result != null) {
|
843
|
|
- toolbar.editor.updateSelection(_selection, source: ChangeSource.local);
|
844
|
|
- _selection = toolbar.editor.selection;
|
845
|
|
- toolbar.editor.controller.replaceText(_selection.start, _selection.end - _selection.start, result.text, selection: _selection.copyWith(
|
846
|
|
- baseOffset: _selection.start,
|
847
|
|
- extentOffset: _selection.start + result.text.length,
|
848
|
|
- ));
|
849
|
|
- toolbar.editor.formatSelection(NotusAttribute.link.fromString(result.url));
|
|
900
|
+ // toolbar.editor.updateSelection(_selection, source: ChangeSource.local);
|
|
901
|
+ // _selection = toolbar.editor.selection;
|
|
902
|
+ editor.controller.replaceText(
|
|
903
|
+ _selection.start, _selection.end - _selection.start, result.text,
|
|
904
|
+ selection: _selection.copyWith(
|
|
905
|
+ baseOffset: _selection.start,
|
|
906
|
+ extentOffset: _selection.start + result.text.length,
|
|
907
|
+ ));
|
|
908
|
+ editor.formatSelection(NotusAttribute.link.fromString(result.url));
|
|
909
|
+ editor.closeKeyboard();
|
850
|
910
|
}
|
851
|
911
|
}
|
852
|
912
|
|