feat: improve outline block (#4722)

This commit is contained in:
Lucas.Xu 2024-02-24 20:54:21 +07:00 committed by GitHub
parent 2abb396467
commit cea1c17b76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 92 additions and 70 deletions

View File

@ -114,9 +114,12 @@ enum OptionAlignType {
} }
enum OptionDepthType { enum OptionDepthType {
h1(1, "H1"), h1(1, 'H1'),
h2(2, "H2"), h2(2, 'H2'),
h3(3, "H3"); h3(3, 'H3'),
h4(4, 'H4'),
h5(5, 'H5'),
h6(6, 'H6');
const OptionDepthType(this.level, this.description); const OptionDepthType(this.level, this.description);

View File

@ -32,6 +32,12 @@ Node outlineBlockNode() {
); );
} }
enum _OutlineBlockStatus {
noHeadings,
noMatchHeadings,
success;
}
class OutlineBlockComponentBuilder extends BlockComponentBuilder { class OutlineBlockComponentBuilder extends BlockComponentBuilder {
OutlineBlockComponentBuilder({ OutlineBlockComponentBuilder({
super.configuration, super.configuration,
@ -75,7 +81,7 @@ class _OutlineBlockWidgetState extends State<OutlineBlockWidget>
BlockComponentTextDirectionMixin, BlockComponentTextDirectionMixin,
BlockComponentBackgroundColorMixin { BlockComponentBackgroundColorMixin {
// Change the value if the heading block type supports heading levels greater than '3' // Change the value if the heading block type supports heading levels greater than '3'
static const finalHeadingLevel = 3; static const maxVisibleDepth = 6;
@override @override
BlockComponentConfiguration get configuration => widget.configuration; BlockComponentConfiguration get configuration => widget.configuration;
@ -120,81 +126,97 @@ class _OutlineBlockWidgetState extends State<OutlineBlockWidget>
final textDirection = calculateTextDirection( final textDirection = calculateTextDirection(
layoutDirection: Directionality.maybeOf(context), layoutDirection: Directionality.maybeOf(context),
); );
final (status, headings) = getHeadingNodes();
final children = getHeadingNodes() Widget child;
.map(
(e) => Container( switch (status) {
padding: const EdgeInsets.only( case _OutlineBlockStatus.noHeadings:
bottom: 4.0, child = Align(
), alignment: Alignment.centerLeft,
width: double.infinity, child: Text(
child: OutlineItemWidget( LocaleKeys.document_plugins_outline_addHeadingToCreateOutline.tr(),
node: e, style: configuration.placeholderTextStyle(node),
textDirection: textDirection,
),
), ),
) );
.toList(); case _OutlineBlockStatus.noMatchHeadings:
child = Align(
final child = children.isEmpty alignment: Alignment.centerLeft,
? Align( child: Text(
alignment: Alignment.centerLeft, LocaleKeys.document_plugins_outline_noMatchHeadings.tr(),
child: Text( style: configuration.placeholderTextStyle(node),
LocaleKeys.document_plugins_outline_addHeadingToCreateOutline ),
.tr(), );
style: configuration.placeholderTextStyle(node), case _OutlineBlockStatus.success:
), final children = headings
) .map(
: Container( (e) => Container(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.only(
vertical: 2.0, bottom: 4.0,
horizontal: 5.0,
),
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
color: backgroundColor,
),
child: Column(
key: ValueKey(children.hashCode),
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
textDirection: textDirection,
children: [
Text(
LocaleKeys.document_outlineBlock_placeholder.tr(),
style: Theme.of(context).textTheme.titleLarge,
), ),
const VSpace(8.0), width: double.infinity,
Padding( child: OutlineItemWidget(
padding: const EdgeInsets.only(left: 15.0), node: e,
child: Column( textDirection: textDirection,
children: children,
),
), ),
], ),
), )
); .toList();
child = Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Column(
children: children,
),
);
}
return Container( return Container(
constraints: const BoxConstraints( constraints: const BoxConstraints(
minHeight: 40.0, minHeight: 40.0,
), ),
padding: padding, padding: padding,
child: child, child: Container(
padding: const EdgeInsets.symmetric(
vertical: 2.0,
horizontal: 5.0,
),
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
color: backgroundColor,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
textDirection: textDirection,
children: [
Text(
LocaleKeys.document_outlineBlock_placeholder.tr(),
style: Theme.of(context).textTheme.titleLarge,
),
const VSpace(8.0),
child,
],
),
),
); );
} }
Iterable<Node> getHeadingNodes() { (_OutlineBlockStatus, Iterable<Node>) getHeadingNodes() {
final children = editorState.document.root.children; final children = editorState.document.root.children;
final int level = final int level =
node.attributes[OutlineBlockKeys.depth] ?? finalHeadingLevel; node.attributes[OutlineBlockKeys.depth] ?? maxVisibleDepth;
var headings = children.where(
return children.where( (e) => e.type == HeadingBlockKeys.type && e.delta?.isNotEmpty == true,
(element) =>
element.type == HeadingBlockKeys.type &&
element.delta?.isNotEmpty == true &&
element.attributes[HeadingBlockKeys.level] <= level,
); );
if (headings.isEmpty) {
return (_OutlineBlockStatus.noHeadings, []);
}
headings =
headings.where((e) => e.attributes[HeadingBlockKeys.level] <= level);
if (headings.isEmpty) {
return (_OutlineBlockStatus.noMatchHeadings, []);
}
return (_OutlineBlockStatus.success, headings);
} }
} }
@ -263,12 +285,8 @@ extension on Node {
return 0.0; return 0.0;
} }
final level = attributes[HeadingBlockKeys.level]; final level = attributes[HeadingBlockKeys.level];
if (level == 2) { final indent = (level - 1) * 15.0 + 10.0;
return 20; return indent;
} else if (level == 3) {
return 40;
}
return 0;
} }
String get outlineItemText { String get outlineItemText {

View File

@ -793,7 +793,8 @@
"copiedToPasteBoard": "The link has been copied to the clipboard" "copiedToPasteBoard": "The link has been copied to the clipboard"
}, },
"outline": { "outline": {
"addHeadingToCreateOutline": "Add headings to create a table of contents." "addHeadingToCreateOutline": "Add headings to create a table of contents.",
"noMatchHeadings": "No matching headings found."
}, },
"table": { "table": {
"addAfter": "Add after", "addAfter": "Add after",