Skip to content

Commit

Permalink
Merge branch 'main' into title_plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
rileyhawk1417 committed Oct 7, 2023
2 parents 482a99a + af8d96b commit 065c8aa
Show file tree
Hide file tree
Showing 52 changed files with 1,310 additions and 544 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 1.4.3
* fix: the text within the `<mark>` tag didn't parse correctly when pasting HTML by @LucasXu0 in ([#501](https://github.com/AppFlowy-IO/appflowy-editor/pull/501))

## 1.4.2
* fix: platform issue on Web by @LucasXu0 in ([#498](https://github.com/AppFlowy-IO/appflowy-editor/pull/498))

## 1.4.1
* fix: build error on Flutter 3.13 by @LucasXu0 in ([#488](https://github.com/AppFlowy-IO/appflowy-editor/pull/488))

Expand Down
Binary file modified documentation/images/showcase.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion example/lib/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'dart:math';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:example/pages/customize_theme_for_editor.dart';
import 'package:example/pages/editor.dart';
import 'package:example/pages/focus_example_for_editor.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -154,7 +155,7 @@ class _HomePageState extends State<HomePage> {
}),

// Theme Demo
_buildSeparator(context, 'Theme Demo'),
_buildSeparator(context, 'Showcases'),
_buildListTile(context, 'Custom Theme', () {
Navigator.push(
context,
Expand All @@ -173,6 +174,14 @@ class _HomePageState extends State<HomePage> {
textDirection: TextDirection.rtl,
);
}),
_buildListTile(context, 'Focus Example', () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const FocusExampleForEditor(),
),
);
}),

// Encoder Demo
_buildSeparator(context, 'Export To X Demo'),
Expand Down
14 changes: 10 additions & 4 deletions example/lib/pages/customize_theme_for_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';

class CustomizeThemeForEditor extends StatefulWidget {
const CustomizeThemeForEditor({super.key});
Expand Down Expand Up @@ -63,6 +64,11 @@ class _CustomizeThemeForEditorState extends State<CustomizeThemeForEditor> {
editorState: editorState,
editorStyle: customizeEditorStyle(),
blockComponentBuilders: customBuilder(),
header: Image.asset(
'assets/images/header.png',
height: 200,
fit: BoxFit.cover,
),
),
);
}
Expand All @@ -74,7 +80,7 @@ class _CustomizeThemeForEditorState extends State<CustomizeThemeForEditor> {
if (HeadingBlockKeys.type == node.type) {
return const EdgeInsets.symmetric(vertical: 30);
}
return const EdgeInsets.symmetric(vertical: 10);
return const EdgeInsets.symmetric(vertical: 5);
},
textStyle: (node) {
if (HeadingBlockKeys.type == node.type) {
Expand Down Expand Up @@ -139,13 +145,13 @@ class _CustomizeThemeForEditorState extends State<CustomizeThemeForEditor> {
EditorStyle customizeEditorStyle() {
return EditorStyle(
padding: PlatformExtension.isDesktopOrWeb
? const EdgeInsets.only(left: 100, right: 100, top: 20)
? const EdgeInsets.only(left: 200, right: 200)
: const EdgeInsets.symmetric(horizontal: 20),
cursorColor: Colors.green,
selectionColor: Colors.green.withOpacity(0.5),
textStyleConfiguration: TextStyleConfiguration(
text: const TextStyle(
fontSize: 18.0,
text: GoogleFonts.poppins(
fontSize: 14.0,
color: Colors.white,
),
bold: const TextStyle(
Expand Down
10 changes: 10 additions & 0 deletions example/lib/pages/desktop_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ class _DesktopEditorState extends State<DesktopEditor> {
commandShortcuts = _buildCommandShortcuts();
}

@override
void dispose() {
editorScrollController.dispose();
editorState.dispose();

super.dispose();
}

@override
void reassemble() {
super.reassemble();
Expand Down Expand Up @@ -66,6 +74,7 @@ class _DesktopEditorState extends State<DesktopEditor> {
...alignmentItems,
],
editorState: editorState,
textDirection: widget.textDirection,
editorScrollController: editorScrollController,
child: Directionality(
textDirection: widget.textDirection,
Expand Down Expand Up @@ -173,6 +182,7 @@ class _DesktopEditorState extends State<DesktopEditor> {
close: 'Close',
replace: 'Replace',
replaceAll: 'Replace all',
noResult: 'No result',
),
),
];
Expand Down
69 changes: 69 additions & 0 deletions example/lib/pages/focus_example_for_editor.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import 'dart:convert';

import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class FocusExampleForEditor extends StatefulWidget {
const FocusExampleForEditor({super.key});

@override
State<FocusExampleForEditor> createState() => _FocusExampleForEditorState();
}

class _FocusExampleForEditorState extends State<FocusExampleForEditor> {
late final Future<EditorState> editorState;

@override
void initState() {
super.initState();

final jsonString = PlatformExtension.isDesktopOrWeb
? rootBundle.loadString('assets/example.json')
: rootBundle.loadString('assets/mobile_example.json');
editorState = jsonString.then((value) {
return EditorState(
document: Document.fromJson(
Map<String, Object>.from(
json.decode(value),
),
),
);
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: const Text('Custom Theme For Editor'),
titleTextStyle: const TextStyle(color: Colors.white),
iconTheme: const IconThemeData(
color: Colors.white,
),
),
body: Column(
children: [
SizedBox(
height: 400,
child: FutureBuilder(
future: editorState,
builder: (context, snapshot) {
return !snapshot.hasData
? const Center(child: CircularProgressIndicator())
: AppFlowyEditor(editorState: snapshot.data!);
},
),
),
const TextField(
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: 'Please input something ...',
),
),
],
),
);
}
}
1 change: 1 addition & 0 deletions lib/appflowy_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export 'src/editor/block_component/rich_text/appflowy_rich_text_keys.dart';
export 'src/editor/block_component/rich_text/default_selectable_mixin.dart';
// editor part, including editor component, block component, etc.
export 'src/editor/editor.dart';
export 'src/editor/find_replace_menu/find_and_replace.dart';
export 'src/editor/selection_menu/selection_menu.dart';
// editor state
export 'src/editor_state.dart';
Expand Down
41 changes: 39 additions & 2 deletions lib/src/core/document/node.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:collection';

import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:nanoid/non_secure.dart';

Expand Down Expand Up @@ -144,6 +145,7 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {

Log.editor.debug('insert Node $entry at path ${path + [index]}}');

entry._resetRelationshipIfNeeded();
entry.parent = this;

_cacheChildren = null;
Expand Down Expand Up @@ -189,9 +191,9 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
}

@override
void unlink() {
bool unlink() {
if (parent == null) {
return;
return false;
}
Log.editor.debug('delete Node $this from path $path');
super.unlink();
Expand All @@ -200,6 +202,17 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {

parent?.notifyListeners();
parent = null;
return true;
}

// reset the relationship of the node before inserting it to another node
// to ensure it is not in the tree
// otherwise, it will throw a state error
// 'Bad state: LinkedNode is already in a LinkedList'
void _resetRelationshipIfNeeded() {
if (parent != null || list != null) {
unlink();
}
}

@override
Expand Down Expand Up @@ -266,6 +279,30 @@ final class Node extends ChangeNotifier with LinkedListEntry<Node> {
final index = parent.children.indexOf(this);
return parent._computePath([index, ...previous]);
}

/// check the integrity of the document (for DEBUG only)
void checkDocumentIntegrity() {
// skip the root node
if (path.isNotEmpty) {
// if node is rendered in the tree, its parent should not be null
final errorMessage =
'''Please submit an issue to https://github.com/AppFlowy-IO/appflowy-editor/issues if you see this error!
node = ${toJson()}''';
assert(
parent != null,
errorMessage,
);
// also, its parent should contain this node
assert(
parent!.children.where((element) => element.id == id).length == 1,
errorMessage,
);
}

for (final child in children) {
child.checkDocumentIntegrity();
}
}
}

@Deprecated('Use Paragraph instead')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,14 @@ class _BlockSelectionAreaState extends State<BlockSelectionArea> {
});
}
}
} else if (prevBlockRect != null ||
prevSelectionRects != null ||
prevCursorRect != null) {
setState(() {
prevBlockRect = null;
prevSelectionRects = null;
prevCursorRect = null;
});
}

WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
Expand Down
1 change: 1 addition & 0 deletions lib/src/editor/block_component/block_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export 'title_block_component/title_block_component.dart';
// image
export 'image_block_component/image_block_component.dart';
export 'image_block_component/image_upload_widget.dart';
export 'image_block_component/resizable_image.dart';
// numbered list
export 'numbered_list_block_component/numbered_list_block_component.dart';
export 'numbered_list_block_component/numbered_list_character_shortcut.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ class _HeadingBlockComponentWidgetState
// make the width of the rich text as small as possible to avoid
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
textDirection: textDirection,
children: [
Flexible(
child: AppFlowyRichText(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'resizable_image.dart';

class ImageBlockKeys {
const ImageBlockKeys._();

Expand Down Expand Up @@ -233,7 +231,11 @@ class ImageBlockComponentWidgetState extends State<ImageBlockComponentWidget>
Rect getBlockRect({
bool shiftWithBaseOffset = false,
}) {
return getCursorRectInPosition(Position.invalid()) ?? Rect.zero;
final imageBox = imageKey.currentContext?.findRenderObject();
if (imageBox is RenderBox) {
return Offset.zero & imageBox.size;
}
return Rect.zero;
}

@override
Expand All @@ -257,11 +259,11 @@ class ImageBlockComponentWidgetState extends State<ImageBlockComponentWidget>
return [];
}
final parentBox = context.findRenderObject();
final dividerBox = imageKey.currentContext?.findRenderObject();
if (parentBox is RenderBox && dividerBox is RenderBox) {
final imageBox = imageKey.currentContext?.findRenderObject();
if (parentBox is RenderBox && imageBox is RenderBox) {
return [
dividerBox.localToGlobal(Offset.zero, ancestor: parentBox) &
dividerBox.size,
imageBox.localToGlobal(Offset.zero, ancestor: parentBox) &
imageBox.size,
];
}
return [Offset.zero & _renderBox!.size];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,13 @@ extension InsertImage on EditorState {
);
}

transaction.afterSelection = Selection.collapsed(
Position(
path: node.path.next,
offset: 0,
),
);

return apply(transaction);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,11 @@ class _ResizableImageState extends State<ResizableImage> {
},
onHorizontalDragUpdate: (details) {
if (onUpdate != null) {
onUpdate((details.globalPosition.dx - initialOffset) * 2.0);
var offset = (details.globalPosition.dx - initialOffset);
if (widget.alignment == Alignment.center) {
offset *= 2.0;
}
onUpdate(offset);
}
},
onHorizontalDragEnd: (details) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,13 @@ Future<void> onDelete(

// IME
if (selection.isSingle) {
if (deletion.composing.isValid || !deletion.deletedRange.isCollapsed) {
final node = editorState.getNodeAtPath(selection.start.path);
if (node?.delta != null &&
(deletion.composing.isValid || !deletion.deletedRange.isCollapsed)) {
final node = editorState.getNodesInSelection(selection).first;
final start = deletion.deletedRange.start;
final length = deletion.deletedRange.end - start;
// final firstNodeContainsDelta = editorState.document.root.children
// .firstWhereOrNull((element) => element.delta != null);
// if (firstNodeContainsDelta != null &&
// node.path.equals(firstNodeContainsDelta.path) && start == 0) {

// }
final transaction = editorState.transaction;

transaction.deleteText(node, start, length);
await editorState.apply(transaction);
return;
Expand Down
Loading

0 comments on commit 065c8aa

Please sign in to comment.