Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed Double Tap and Drag #3

Open
wants to merge 14 commits into
base: cc-custom
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
ios_text_example/
android_text_example/

.dart_tool
15 changes: 15 additions & 0 deletions melos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: super_editor
repository: https://github.com/superlistapp/super_editor

packages:
- super_editor/pubspec.yaml
- super_editor/example/pubspec.yaml
- super_editor_markdown/pubspec.yaml
- super_text_layout/pubspec.yaml
- super_text_layout/example/pubspec.yaml
- attributed_text/pubspec.yaml
- website/pubspec.yaml

command:
bootstrap:
usePubspecOverrides: true
2 changes: 1 addition & 1 deletion super_editor/example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ packages:
path: "../../super_editor_markdown"
relative: true
source: path
version: "0.1.3"
version: "0.1.4+1"
super_text_layout:
dependency: "direct main"
description:
Expand Down
4 changes: 0 additions & 4 deletions super_editor/lib/src/default_editor/blockquote.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:super_editor/src/core/edit_context.dart';
import 'package:super_editor/src/default_editor/attributions.dart';
import 'package:super_editor/src/infrastructure/_logging.dart';
import 'package:super_editor/src/infrastructure/attributed_text_styles.dart';
import 'package:super_editor/src/infrastructure/keyboard.dart';

Expand All @@ -14,9 +13,6 @@ import 'paragraph.dart';
import 'text.dart';
import 'text_tools.dart';

// ignore: unused_element
final _log = Logger(scope: 'blockquote.dart');

class BlockquoteComponentBuilder implements ComponentBuilder {
const BlockquoteComponentBuilder();

Expand Down
4 changes: 0 additions & 4 deletions super_editor/lib/src/default_editor/box_component.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import 'package:flutter/material.dart';
import 'package:super_editor/src/core/document.dart';
import 'package:super_editor/src/default_editor/selection_upstream_downstream.dart';
import 'package:super_editor/src/infrastructure/_logging.dart';

import '../core/document_layout.dart';

// ignore: unused_element
final _log = Logger(scope: 'box_component.dart');

/// Base implementation for a [DocumentNode] that only supports [UpstreamDownstreamNodeSelection]s.
abstract class BlockNode extends DocumentNode {
@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1441,7 +1441,7 @@ class CommonEditorOperations {

editorOpsLog.fine('_convertParagraphIfDesired', ' - text before caret: "$textBeforeCaret"');
if (hasUnorderedListItemMatch || hasOrderedListItemMatch) {
editorOpsLog.fine('_convertParagraphIfDesired', ' - found unordered list item prefix');
editorOpsLog.fine('_convertParagraphIfDesired', ' - found list item prefix');
int startOfNewText = textBeforeCaret.length;
while (startOfNewText < node.text.text.length && node.text.text[startOfNewText] == ' ') {
startOfNewText += 1;
Expand Down Expand Up @@ -1470,6 +1470,47 @@ class CommonEditorOperations {
return true;
}

final headingPattern = RegExp(r'^\s*(#+)\s+$');
final headingMatch = headingPattern.firstMatch(textBeforeCaret);
if (headingMatch != null) {
editorOpsLog.fine('_convertParagraphIfDesired', ' - found heading prefix');
int startOfNewText = textBeforeCaret.length;
while (startOfNewText < node.text.text.length && node.text.text[startOfNewText] == ' ') {
startOfNewText += 1;
}
final adjustedText = node.text.copyText(startOfNewText);
final headingLevel = min(headingMatch.group(1)!.length, 6);
final headingAttribution = (const [
header1Attribution,
header1Attribution,
header2Attribution,
header3Attribution,
header4Attribution,
header5Attribution,
header6Attribution
])[min(headingLevel,3)];
final newNode =
ParagraphNode(id: node.id, text: adjustedText, metadata: {...node.metadata, 'blockType': headingAttribution});

editor.executeCommand(
EditorCommandFunction((document, transaction) {
transaction.replaceNode(oldNode: node, newNode: newNode);
}),
);

// We removed some text at the beginning of the text.
// Move the selection back by that same amount.
final textPosition = composer.selection!.extent.nodePosition as TextNodePosition;
composer.selection = DocumentSelection.collapsed(
position: DocumentPosition(
nodeId: node.id,
nodePosition: TextNodePosition(offset: textPosition.offset - startOfNewText),
),
);

return true;
}

final hrMatch = RegExp(r'^---*\s$');
final hasHrMatch = hrMatch.hasMatch(textBeforeCaret);
if (hasHrMatch) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,6 @@ Updating drag selection:
_clearSelection();
return;
}
basePosition = baseWordSelection.base;

final extentWordSelection = getWordSelection(
docPosition: extentPosition,
Expand All @@ -568,7 +567,13 @@ Updating drag selection:
_clearSelection();
return;
}
extentPosition = extentWordSelection.extent;

if ([basePosition.nodePosition, extentPosition.nodePosition].every((e) => e is TextPosition)) {
bool isDraggingLeft =
(basePosition.nodePosition as TextPosition).offset > (extentPosition.nodePosition as TextPosition).offset;
basePosition = isDraggingLeft ? baseWordSelection.extent : baseWordSelection.base;
extentPosition = isDraggingLeft ? extentWordSelection.base : extentWordSelection.extent;
}
}

widget.selectionNotifier.value = DocumentSelection(
Expand Down
7 changes: 5 additions & 2 deletions super_editor/lib/src/default_editor/document_scrollable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 +410,12 @@ class AutoScrollController with ChangeNotifier {
globalRegion.height,
);

final beyondTopExtent = min(selectionExtentRectInViewport.top, 0).abs();
final beyondTopExtent = min(selectionExtentRectInViewport.top - selectionExtentAutoScrollBoundary.leading, 0).abs();

final beyondBottomExtent = max(selectionExtentRectInViewport.bottom - viewportBox.size.height, 0);
final beyondBottomExtent = max(
selectionExtentRectInViewport.bottom - viewportBox.size.height + selectionExtentAutoScrollBoundary.trailing,
0,
);

editorScrollingLog.finest('Ensuring extent is visible.');
editorScrollingLog.finest(' - viewport size: ${viewportBox.size}');
Expand Down
16 changes: 8 additions & 8 deletions super_editor/lib/src/default_editor/list_items.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import 'layout_single_column/layout_single_column.dart';
import 'paragraph.dart';
import 'text.dart';

final _log = Logger(scope: 'list_items.dart');
final _log = editorDocLog;

class ListItemNode extends TextNode {
ListItemNode.ordered({
Expand Down Expand Up @@ -444,7 +444,7 @@ class IndentListItemCommand implements EditorCommand {
final node = document.getNodeById(nodeId);
final listItem = node as ListItemNode;
if (listItem.indent >= 6) {
_log.log('IndentListItemCommand', 'WARNING: Editor does not support an indent level beyond 6.');
_log.warning('IndentListItemCommand: WARNING: Editor does not support an indent level beyond 6.');
return;
}

Expand Down Expand Up @@ -561,12 +561,12 @@ class SplitListItemCommand implements EditorCommand {
final text = listItemNode.text;
final startText = text.copyText(0, splitPosition.offset);
final endText = splitPosition.offset < text.text.length ? text.copyText(splitPosition.offset) : AttributedText();
_log.log('SplitListItemCommand', 'Splitting list item:');
_log.log('SplitListItemCommand', ' - start text: "$startText"');
_log.log('SplitListItemCommand', ' - end text: "$endText"');
_log.info('SplitListItemCommand: Splitting list item:');
_log.info(' - start text: "$startText"');
_log.info(' - end text: "$endText"');

// Change the current node's content to just the text before the caret.
_log.log('SplitListItemCommand', ' - changing the original list item text due to split');
_log.info(' - changing the original list item text due to split');
// TODO: figure out how node changes should work in terms of
// a DocumentEditorTransaction (#67)
listItemNode.text = startText;
Expand All @@ -586,13 +586,13 @@ class SplitListItemCommand implements EditorCommand {
);

// Insert the new node after the current node.
_log.log('SplitListItemCommand', ' - inserting new node in document');
_log.info(' - inserting new node in document');
transaction.insertNodeAfter(
existingNode: node,
newNode: newNode,
);

_log.log('SplitListItemCommand', ' - inserted new node: ${newNode.id} after old one: ${node.id}');
_log.info(' - inserted new node: ${newNode.id} after old one: ${node.id}');
}
}

Expand Down
42 changes: 21 additions & 21 deletions super_editor/lib/src/default_editor/multi_node_editing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import 'dart:math';

import 'package:attributed_text/attributed_text.dart';
import 'package:flutter/services.dart';
import 'package:super_editor/src/default_editor/selection_upstream_downstream.dart';
import 'package:super_editor/src/core/document.dart';
import 'package:super_editor/src/core/document_editor.dart';
import 'package:super_editor/src/core/document_selection.dart';
import 'package:super_editor/src/default_editor/selection_upstream_downstream.dart';
import 'package:super_editor/src/default_editor/text.dart';
import 'package:super_editor/src/infrastructure/_logging.dart';

import 'paragraph.dart';

final _log = Logger(scope: 'multi_node_editing.dart');
final _log = editorDocLog;

class DeleteSelectionCommand implements EditorCommand {
DeleteSelectionCommand({
Expand All @@ -22,7 +22,7 @@ class DeleteSelectionCommand implements EditorCommand {

@override
void execute(Document document, DocumentEditorTransaction transaction) {
_log.log('DeleteSelectionCommand', 'DocumentEditor: deleting selection: $documentSelection');
_log.info('Executing DeleteSelectionCommand: deleting selection $documentSelection');
final nodes = document.getNodesInside(documentSelection.base, documentSelection.extent);

if (nodes.length == 1) {
Expand Down Expand Up @@ -66,7 +66,7 @@ class DeleteSelectionCommand implements EditorCommand {
transaction: transaction,
);

_log.log('DeleteSelectionCommand', ' - deleting partial selection within the starting node.');
_log.info(' - deleting partial selection within the starting node.');
_deleteSelectionWithinNodeFromPositionToEnd(
document: document,
node: startNode,
Expand All @@ -75,7 +75,7 @@ class DeleteSelectionCommand implements EditorCommand {
replaceWithParagraph: false,
);

_log.log('DeleteSelectionCommand', ' - deleting partial selection within ending node.');
_log.info(' - deleting partial selection within ending node.');
_deleteSelectionWithinNodeFromStartToPosition(
document: document,
node: endNode,
Expand Down Expand Up @@ -109,13 +109,13 @@ class DeleteSelectionCommand implements EditorCommand {
return;
}

_log.log('DeleteSelectionCommand', ' - combining last node text with first node text');
_log.info(' - combining last node text with first node text');
startNodeAfterDeletion.text = startNodeAfterDeletion.text.copyAndAppend(endNodeAfterDeletion.text);

_log.log('DeleteSelectionCommand', ' - deleting last node');
_log.info(' - deleting last node');
transaction.deleteNode(endNodeAfterDeletion);

_log.log('DeleteSelectionCommand', ' - done with selection deletion');
_log.info(' - done with selection deletion');
}

void _deleteSelectionWithinSingleNode({
Expand All @@ -124,7 +124,7 @@ class DeleteSelectionCommand implements EditorCommand {
required DocumentEditorTransaction transaction,
required DocumentNode node,
}) {
_log.log('_deleteSelectionWithinSingleNode', ' - deleting selection within single node');
_log.info(' - deleting selection within single node');
final basePosition = documentSelection.base.nodePosition;
final extentPosition = documentSelection.extent.nodePosition;

Expand All @@ -142,12 +142,12 @@ class DeleteSelectionCommand implements EditorCommand {
newNode: ParagraphNode(id: node.id, text: AttributedText()),
);
} else if (node is TextNode) {
_log.log('_deleteSelectionWithinSingleNode', ' - its a TextNode');
_log.info(' - its a TextNode');
final baseOffset = (basePosition as TextPosition).offset;
final extentOffset = (extentPosition as TextPosition).offset;
final startOffset = baseOffset < extentOffset ? baseOffset : extentOffset;
final endOffset = baseOffset < extentOffset ? extentOffset : baseOffset;
_log.log('_deleteSelectionWithinSingleNode', ' - deleting from $startOffset to $endOffset');
_log.info(' - deleting from $startOffset to $endOffset');

node.text = node.text.removeRegion(
startOffset: startOffset,
Expand All @@ -166,14 +166,14 @@ class DeleteSelectionCommand implements EditorCommand {
final startIndex = document.getNodeIndexById(startNode.id);
final endIndex = document.getNodeIndexById(endNode.id);

_log.log('_deleteNodesBetweenFirstAndLast', ' - start node index: $startIndex');
_log.log('_deleteNodesBetweenFirstAndLast', ' - end node index: $endIndex');
_log.log('_deleteNodesBetweenFirstAndLast', ' - initially ${document.nodes.length} nodes');
_log.info(' - start node index: $startIndex');
_log.info(' - end node index: $endIndex');
_log.info(' - initially ${document.nodes.length} nodes');

// Remove nodes from last to first so that indices don't get
// screwed up during removal.
for (int i = endIndex - 1; i > startIndex; --i) {
_log.log('_deleteNodesBetweenFirstAndLast', ' - deleting node $i: ${document.getNodeAt(i)?.id}');
_log.info(' - deleting node $i: ${document.getNodeAt(i)?.id}');
transaction.deleteNodeAt(i);
}
}
Expand Down Expand Up @@ -268,12 +268,12 @@ class DeleteSelectionCommand implements EditorCommand {
// depending on the first node still existing at the end of
// the deletion. This is a fragile relationship between the
// composer and the editor and needs to be addressed.
_log.log('_deleteBlockNode', ' - replacing block-level node with a ParagraphNode: ${node.id}');
_log.info(' - replacing block-level node with a ParagraphNode: ${node.id}');

final newNode = ParagraphNode(id: node.id, text: AttributedText());
transaction.replaceNode(oldNode: node, newNode: newNode);
} else {
_log.log('_deleteBlockNode', ' - deleting block level node');
_log.info(' - deleting block level node');
transaction.deleteNode(node);
}
}
Expand All @@ -288,17 +288,17 @@ class DeleteNodeCommand implements EditorCommand {

@override
void execute(Document document, DocumentEditorTransaction transaction) {
_log.log('DeleteNodeCommand', 'DocumentEditor: deleting node: $nodeId');
_log.info('Executing DeleteNodeCommand: deleting node $nodeId');

final node = document.getNodeById(nodeId);
if (node == null) {
_log.log('DeleteNodeCommand', 'No such node. Returning.');
_log.info('No such node. Returning.');
return;
}

_log.log('DeleteNodeCommand', ' - deleting node');
_log.info(' - deleting node');
transaction.deleteNode(node);

_log.log('DeleteNodeCommand', ' - done with node deletion');
_log.info(' - done with node deletion');
}
}
Loading