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

Sys - Full documentation #2

Closed
adrian-moisa opened this issue May 12, 2022 · 7 comments
Closed

Sys - Full documentation #2

adrian-moisa opened this issue May 12, 2022 · 7 comments
Assignees

Comments

@adrian-moisa
Copy link
Collaborator

adrian-moisa commented May 12, 2022

This was one of the major pain points when using Flutter Quill. I'm working in parallel with the refactoring work to develop a full set of documentation articles that cover all use cases. Please post here what you think it's missing from the documentation. I'll be happy to receive feedback.

Join on discord to get advice and help or follow us on YouTube Visual Coding to learn more about the architecture of Visual Editor and other Flutter apps.

@apalala-dev
Copy link

Since flutter-quill closed their issue section, the transition to this package seems even more urgent now 😅
I switched to your package easily thanks to his similarities with flutter-quill.
A migration guide might be useful at some point, when the refactoring will be done.

Your documentation seems nice atm (although it is not finished), but I would miss a FAQ section.

I am not sure you would accept PR since you are doing a big refactor with the package, so I'll just put my thoughts roughly here.

Let's start with the things I managed to do that should be documented.

How to add text manually?

Devs might want to insert text (or embeds) when something happens outside the VisualEditor / the toolbar.
This is what I did to add a space for instance:

_controller?.document.insert(index + 1, " ")

How to insert embeds?

final index = _controller!.selection.baseOffset;
setState(() {
  _controller!.document
      .insert(index, BlockEmbed('specialKey', 'someValue'));
});

Or to replace the current selection instead:

final index = _controller!.selection.baseOffset;
final length = _controller!.selection.extentOffset - index;
_controller!.replaceText(index, length,
    quill.BlockEmbed(RichTextDetails.userInput, uniqueId), null);

I only store an uniqueId and a type in the delta document and I retrieve other related data elsewhere.

Then, I use a special embedBuilder to display my custom embed:

VisualEditor(
    // ...
    embedBuilder: customEmbedBuilder,
),
Widget customEmbedBuilder(BuildContext context,
    EditorController controller, Embed node, bool readOnly) {
  switch (node.value.type) {
    case RichTextDetails.userInput:
      final input = _details.inputs[node.value.data];
      if (input is RichTextOptions) {
        return SomeCustomWidget(input);
      }
  }
  return Text("Unsupported embed");
}

How to detect when an Embed is removed by the user in the VisualEditor?

This might be important when one stores data elsewhere than directly in the delta document.
A simple use case could be to store an image in some cloud storage provider (Firebase, ...) and just store the link to that image in the delta document.
This image could then be used in other parts without being uploaded again.

_controller = EditorController(
    document: doc,
    selection: const TextSelection.collapsed(offset: 0),
    onReplaceText: (int index, int len, Object? data) {
      final leaf = _controller!.document.querySegmentLeafNode(index);
      if (leaf.item2 is quill.Embed &&
          (data is String && data.isEmpty)) {
        final embeddable = (leaf.item2 as quill.Embed).value;
        if (embeddable.type == mySpecialTypeKey) {
          // Remove associated data, such as the image file if it was stored elsewhere
          doStuff();
        }
      }
      return true;
    });

How to remove an embed from the VisualEditor manually?

If the embed is an image for instance, it could include a delete button in the top right corner. When the users taps on that button, the developer would have to remove manually the embed since it is not removed with the keyboard.

Here is a way of doing it:

final matches = _controller!.document
          .toPlainText()
          .allIndexesOf(quill.Embed.kObjectReplacementCharacter);
      int? idxUniqueId;
      for (var index in matches) {
        final leaf = _controller!.document.querySegmentLeafNode(index);
        if (leaf.item2 is quill.Embed) {
          final embeddable = (leaf.item2 as quill.Embed).value;
          if (embeddable.type == mySpecialTypeKey &&
              embeddable.data == uniqueId) {
            idxUniqueId = index;
            break;
          }
        }
      }
      if (idxUniqueId != null) {
        // replace the special character used for embeds by an empty String
        _controller?.replaceText(idxUniqueId, 1, '', null);
      }

The above method used the below extension on String:

extension StringExtension on String {
  List<int> allIndexesOf(String pattern) {
    List<int> result = [];
    int idx = indexOf(pattern);
    while (idx > 0 && idx < length) {
      result.add(idx);
      idx = indexOf(pattern, idx + 1);
    }
    return result;
  }
}

TODO

Here is a quick list of the things I would like to be documented but I don't know how to do them.

Lose / Give focus manually

After adding an image for instance using a custom workflow, I lose the focus on the VisualEditor or more specifically: the indicator was not displayed anymore until I started typing again.
I am talking about this indicator:
image

Size of embeds

See #43.
I am not sure if it's a bug or not, so I'll let it here for now

Replacement character for Embed

Currently, VisualEditor renders Embed with kObjectReplacementCharacter.
It could be nice to propose an alternative, like the alt text of an image for instance.
I think it should be doable by extending Embed but I am not sure of the side effects.
This would impact toPlainText().

If it is not recommended, the reason might be explained in the docs.

@adrian-moisa
Copy link
Collaborator Author

Hi @apalala-dev! Nice to see you take such great interest in the project. I'll attempt to answer all your queries.

  1. Migration Guide - That's something that I haven't considered yet. Mainly because I intend to keep most of the existing functionalities intact. So existing documents generated with Flutter Quill should be working identically (as of May 30 2022 this is still true). I don't think there's reason to break any such features. But in case it will happen, I will for sure explain clearly how to deal with the migration.

  2. Yes, documentation is WIP, barely started and I plan to go far deeper. I do intend to make it a lot easier to understand the whole framework so expect a lot more content. I'm working daily on the refactoring and gathering materials that will be published as YT videos but also improving the docs themselves. At some point I will migrate them to a better platform.

  3. I'll for sure accept PRs and I will provide a style guide to ensure PRs wont be bounced to much. At the moment I'd rather not receive PRs because there's so much more refactoring work ahead. I've been far slower the past weeks than anticipated due to many events overlapping in my spare time, but I expect a return to normal by the end of this week. I'm already back at work in my spare time on the editor repo. Once stable I'll make it clear that PRs are welcomed.

  4. Great examples to take in the docs. I will bookmark this ticket to make sure I'll go trough all of them. Thank you for providing indications.

  5. Detect when an Embed is removed - That's a fair point. I think at the moment the best solution is to extend the controller to expose callbacks to deal with the deletion event by using code provided by the user. That would make life a bit easier. Already added a ticket for it.

  6. In word processing parlance it's called the caret. My guess is that maybe you are reseting somehow the state of the editor with a new instance and a new document. I'll definitely provide examples for controlling the focus as well.

  7. I've responded in Blocks - Size of Embed elements differs if alone or not #43. Unless a blocker it's low prio. I'll return with an answer as soon the critical refactoring topics are done.

  8. At the moment I'm not super familiar with how embeds are parsed back and forth from text. I'll need to study more this topic before providing any feedback. I guess that we can take inspiration from Wordpress and it's magic tags syntax for Gutenberg blocks to develop something similar.

Thanks for joining the new repo. Your comments are very much welcomed. I'll try to get back to progressing on them as soon as the refactoring effort is complete. I suppose you already joined Discord and subscribed on Youtube Btw, how do you download it if it's not yet published to pub.dev?

@apalala-dev
Copy link

It is public but not published on pub.dev. Since the lib is on a public GitHub, one just needs to either download the project and uses it with a path dependency or use a git dependency like I did:

  visual_editor:
    git: https://github.com/visual-space/visual-editor.git

It's very useful for forks 😉

No worries about the other comments: first step is to stabilize the repo with the refactor and the base documentation.
The idea was more to give ideas for later and show some interest in the project.
VisualEditor could become a very great addition to the Flutter ecosystem.

People might want to contribute to the project at some point. It could help if you had a kanban (through the projects tabs on GitHub) where you report your progress and what is planned next.

@adrian-moisa
Copy link
Collaborator Author

Cool trick to know. I thought there must be some link. Will help me test it in my production project.

@adrian-moisa
Copy link
Collaborator Author

Latest status update:
I've managed to remove the 2 major mixins in RawEditor. Separated a lot of the code in standalone services, utils and states. I'm still digging at the RawEditor but made some great progress so far. Soon the RawEditor will be lightweight and easy to understand. Then I continue digging on the lower levels unil everything is easily accessible for maintenance.

@felix-mittermeier
Copy link

Latest status update:
I've managed to remove the 2 major mixins in RawEditor. Separated a lot of the code in standalone services, utils and states. I'm still digging at the RawEditor but made some great progress so far. Soon the RawEditor will be lightweight and easy to understand. Then I continue digging on the lower levels unil everything is easily accessible for maintenance.

Such great news 👍🏻 Thank you so much for your effort, really appreciated

@adrian-moisa
Copy link
Collaborator Author

I'll be closing this task since the seed of the documentation was started. This is an ever present task.

sebastian0107 pushed a commit that referenced this issue Jul 6, 2022
# This is the 1st commit message:

ImageM -> Tuple2<String, String>

# The commit message #2 will be skipped:

# Revert "ImageM -> Tuple2<String, String>"
#
# This reverts commit df01ae2.
@adrian-moisa adrian-moisa changed the title Full documentation Sys - Full documentation Nov 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants