memspace / zefyr

Soft and gentle rich text editing for Flutter applications.
https://zefyr-editor.gitbook.io
2.22k stars 551 forks source link

Feature request: Link and Image opener in edit mode #18

Open stemuk opened 6 years ago

stemuk commented 6 years ago

This is of course highly optional but I could see it being useful to allow users to open embedded links or images inside zefyr. Image opening can be done with the photo_view package (https://pub.dartlang.org/packages/photo_view#-changelog-tab-) and link opening can be done with the flutter_web_browser package (https://pub.dartlang.org/packages/flutter_web_browser).

Both packages work on Android and iOS respectively and should work with zefyr out of the box. If I find time this weekend I will look into options on how to implement this functionality.

pulyaevskiy commented 6 years ago

Thanks, this is definitely something I've been thinking about as well.

The way I see this is that there is two different workflows:

  1. Read-only workflow. This is fairly straightforward. When user taps on a link or image we just need to invoke a user-defined callback which is free to define whichever behavior is needed. This workflow should be applied when enabled is set to false.

  2. Editing workflow. This is what you are asking I suspect, but it is more tricky. We cannot bind to tap events because these are used to move caret position. I'm also not sure if opening an image in full screen while editing is really useful, I'd be curious to see your reasoning behind it. For links though it is already supported today, though not as user-friendly as I'd like it to be. When caret is on a link segment, you can tap on the link button of Zefyr toolbar which reveals link editing toolbar which includes an "open in browser" button. This button is powered by official url_launcher plugin from the Flutter team.

A better way to open links in editing mode is to move this button to the selection overlay toolbar (which includes copy and paste functionality). This is not a small task and would require writing our own toolbars for selection overlay (I'm currently using those provided by Flutter out of the box). I had plans to do this anyway at some point, as we can leverage custom selection toolbar for a few more useful things.

stemuk commented 6 years ago

True, I definitely agree with you on the workflow you described (I mixed up read and edit in the issue title), I think that tapping on a link in edit mode should definitely be reserved for the cursor and should not trigger opening the link. I would however suggest that if a user taps on a link in edit mode that the 'link view' opens in the zefyr toolbar immediately instead of opening the regular toolbar view (with bold, italic etc.), since the regular view makes it non-trivial to change the link text.

I just tried out the link open button (must have missed it before) and I feel like the exact same UI should be implemented for opening a link in read mode since not having a full browser-like experience (back button, URL field etc.) keeps things simple and elegant.

As for the Image opening I believe that generally the same workflow should be applied, since even though the cursor cannot be moved inside the image area in edit mode, having onTap open the image in photo_view would probably result in a lot of unintended image openings.

stemuk commented 6 years ago

Another issue I noticed is that it takes the Zefyr editor a considerable amount of time (sometimes 2-3 seconds) to load larger images (i.e. high-res) if they are included inside a document. This triggers the document to reload once the image has finally loaded, resulting in a rather bad user experience.

As I see it there are two solutions, with a) reducing the image size considerably upon including an image inside a document, and b) loading a placeholder image first (just a grey asset image or a grey Container.). A placeholder Image can be implemented with the FadeInImage class as explained here, and I would expect Zefyr to not reload the document one the placeholder gets replaced, which would pretty much fix the problem with the image loading delay.

pulyaevskiy commented 6 years ago

In short, I agree.

This is why in 0.1.3 image delegate is changed to use a builder which returns a widget instead of Image. This way users can implement their own desired flow.

The built-in default image delegate is purposely very barebones. It's very likely that users will require custom ways to handle images, e.g.:

  1. Upload images to different cloud services (aws, gcp, azure)
  2. Custom UX for showing upload progress
  3. Preprocess images before embedding, like you mentioned - resizing.

I'm currently not sure if built-in image delegate should be more opinionated, I see it more as a reference implementation which is just a starting point for users to implement their own handling.

I'm working on a doc about working with images which will be available together with 0.1.3 release.

mindeng commented 5 years ago

Thanks, this is definitely something I've been thinking about as well.

The way I see this is that there is two different workflows:

  1. Read-only workflow. This is fairly straightforward. When user taps on a link or image we just need to invoke a user-defined callback which is free to define whichever behavior is needed. This workflow should be applied when enabled is set to false.
  2. Editing workflow. This is what you are asking I suspect, but it is more tricky. We cannot bind to tap events because these are used to move caret position. I'm also not sure if opening an image in full screen while editing is really useful, I'd be curious to see your reasoning behind it. For links though it is already supported today, though not as user-friendly as I'd like it to be. When caret is on a link segment, you can tap on the link button of Zefyr toolbar which reveals link editing toolbar which includes an "open in browser" button. This button is powered by official url_launcher plugin from the Flutter team.

A better way to open links in editing mode is to move this button to the selection overlay toolbar (which includes copy and paste functionality). This is not a small task and would require writing our own toolbars for selection overlay (I'm currently using those provided by Flutter out of the box). I had plans to do this anyway at some point, as we can leverage custom selection toolbar for a few more useful things.

May I ask if read-only workflow is supported now? Thank you very much!

pulyaevskiy commented 5 years ago

I have a draft which I’m trying to get out sometime soon. It’s a substantial change so there will be a few breaking changes.

pavel-birdy commented 4 years ago

I would however suggest that if a user taps on a link in edit mode that the 'link view' opens in the zefyr toolbar immediately instead of opening the regular toolbar view (with bold, italic etc.), since the regular view makes it non-trivial to change the link text.

I agree with this. Otherwise, the user will think it should open the link or frozen.

JCKodel commented 4 years ago

1) "I'm also not sure if opening an image in full screen while editing is really useful, I'd be curious to see your reasoning behind it." In my case, it seems only natural that my user opens the editor in edit mode (I did even knew Zefyr had a readonly mode). What does not make sense to me is to present a notebook that you can't immediatelly write in.

2) This is a workaround to detect a tap on a image (either in view or edit modes):

_zefyrController.addListener(() {
    if (_zefyrController.getSelectionStyle().isNotEmpty) {
      final selection = _zefyrController.getSelectionStyle().single;

      if (selection.value["type"] == "image") {
        final imageUrl = selection.value["source"];

        // Do whatever you want with imageUrl;
      }
    }
  });

Since Zefyr is incapable of handling image clipboard (it can copy, but it can't paste), there is no huge problem in removing the tap on the image even while editing.

It would be awesome if we could just ditch the Zefyr toolbar and use our own. A code sample doing that would be amazing (this way, we could write toolbars on our own and even make them a pub.dev package (zefyr_toolbar_with_colors_fonts_and_sizes_with_open_images_in_photo_viewer)). It would also fix some issues with the current toolbar: (for instance, not being able to localize some terms as "Tap to edit link"