memspace / zefyr Goto Github PK
View Code? Open in Web Editor NEWSoft and gentle rich text editing for Flutter applications.
Home Page: https://zefyr-editor.gitbook.io
Soft and gentle rich text editing for Flutter applications.
Home Page: https://zefyr-editor.gitbook.io
1、Hyperlink cannot be triggered in non edit state.
2、EditableBox will terminate the GestureDetector event of custom widgets.
Allows indenting blocks and individual lines.
When applied to an individual line (without block
style) simply indents the line by adding Padding
around it with value configurable through ZefyrTheme
.
When applied to a line with block
style following is expected:
quote
) visually creates a nested block of the same style for that line. Similarly to how markdown handles nested blocks:First level quote
Second level quote
etc.
First level quote
- nested list item
Currently it is required for all lines within a block to have the same block
style. This change introduces a need for block nodes to accommodate any group of block-styled lines. Nesting and rendering would be solved outside of the document model in widget layer.
This is blocked by Flutter.
After the latest Dart SDK update to 2.1.0-dev.1.0.flutter-ccb16f7282
I get the following error:
Because quiver_hashcode 1.0.0 requires SDK version >=1.8.0 <2.0.0 and no versions of quiver_hashcode match >1.0.0 <2.0.0, quiver_hashcode ^1.0.0 is forbidden.
So, because overwrite depends on quill_delta ^1.0.0-dev.1.0 which depends on quiver_hashcode ^1.0.0, version solving failed.
pub get failed (1)
It seems like a simple bump to the latest quiver_hashcode version would fix this issue.
Thank you making awesome package.
I am thinking to use in my product.
In the pub, The license of this package is BSD.
But not sure which BSD.
So could you provide detailed license?
I would like the ability to disable specific features so that they cannot be selected from the editor menu, similar to what you can do with the quill editor.
I may be mistaken, but I believe Notus is essentially an ot-type definition with different semantics to ottypes/richtext; is this the case? If so, what would be involved in supporting other types?
I'm looking to hook Zefyr up to ShareDB, which uses ottypes/rich-text
There are a couple potential issues with the standard TextInputPlugin used in Flutter:
Editing documents involves moving the whole document between native and Dart sides for each and every modification, including selection changes. With large documents this could be rather inefficient.
Since communication with the native side is asynchronous there is a risk of running into race conditions (which already happened once). Current workaround is to prevent document updates from being sent too often to the native side.
How custom text input plugin could address the above issues:
This requires a smarter native side implementation which (a) knows how to compose deltas; (b) keeps track of current revision so that updates can be sorted and applied in the correct order. Essentially this would require a local OT server running on the native side.
As I am working on an app for web contents, I want multiple parameters for one attributes, e.g. target="_blank" for the link attribute.
Do you have any ideas on how I archive that or have any plan for this feature ?
Thank you.
Tapping on the blank space of zefyr editor does not make the editor focused, which means when there is no text, it will be hard to make it focused.
Really hope tapping on anywhere of the editor will make the editor focused.
It would be useful to add onPaste interface on the editable text. It makes URL pasting experience great.
Hi @pulyaevskiy ,
Please help me, how we save to format json and parsing fromJson on NotusDocument besause I try it someting wrong with my format
rror Parsing JSON: FormatException: Control character in string (at character 26)
from save I just do with jsonEncode and call document variable of NotesDocument and parsing with jsondecode and NotusDocument.fromJson
The zefyr is great work(Although I don't know how to read it).
Is there a method can add a new custom item to the toolbar, and delete some tools which I will not use.
For example, I want to add a Name Card Widget with the toolbar, and display a custom widget.
Thank you.
Version Solving failed because I am using the latest url_launcher package.
Because project depends on zefyr ^0.2.0 which depends on url_launcher ^3.0.0, url_launcher ^3.0.0 is required.
So, because project depends on url_launcher ^4.0.1, version solving failed.
pub get failed (1)
compiler message: file:///C:/src/flutter/.pub-cache/hosted/pub.flutter-io.cn/zefyr-0.1.2/lib/src/widgets/common.dart:96:61: Error: The getter 'offset' isn't defined for the class 'dart.core::double'.
compiler message: Try correcting the name to the name of an existing getter, or defining a getter or field named 'offset'.
compiler message: double target = viewport.getOffsetToReveal(object, 0.0).offset;
First of all, thanks a lot for this awesome project, I really appreciate the time and effort you must have put into zefyr to make this work!
In my own tests I ran into (only) one major issue that resolves around text input at a certain speed. If certain actions such as text input or or text deletion are preformed at a certain speed (for instance simply holding down the delete button on the keyboard) the entire application will crash and throw the following errors in frequent succession:
W/IInputConnectionWrapper( 5484): getTextBeforeCursor on inactive InputConnection
W/IInputConnectionWrapper( 5484): getSelectedText on inactive InputConnection
W/IInputConnectionWrapper( 5484): requestCursorAnchorInfo on inactive InputConnection
Even worse, the keybord will persist in its opened state even after the application has been closed by the user, as seen in this image, effectively rendering the device useless for several minutes.
The error might be caused by the race conditions you mentioned in #10 and seems to happen less frequently on more performant devices, which would suggest that performance optimizations might eliminate this issue for the most part.
Again, thanks a lot for creating this otherwise awesome widget, I think with the scope of this project issues like these are mostly unavoidable. 👍
compiler message: file:///C:/Users/Aman%20gautam/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/zefyr-0.1.2/lib/src/widgets/common.dart:96:61: Error: The getter 'offset' isn't defined for the class 'dart.core::double'.
compiler message: Try correcting the name to the name of an existing getter, or defining a getter or field named 'offset'.
compiler message: double target = viewport.getOffsetToReveal(object, 0.0).offset;
compiler message: ^
compiler message: file:///C:/Users/Aman%20gautam/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/zefyr-0.1.2/lib/src/widgets/common.dart:101:54: Error: The getter 'offset' isn't defined for the class 'dart.core::double'.
compiler message: Try correcting the name to the name of an existing getter, or defining a getter or field named 'offset'.
compiler message: target = viewport.getOffsetToReveal(object, 1.0).offset;
compiler message: ^
Compiler failed on C:\flutterprojects\codelin\lib\main.dart
FAILURE: Build failed with an exception.
Where:
Script 'C:\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 435
What went wrong:
Execution failed for task ':app:flutterBuildDebug'.
Process 'command 'C:\flutter\bin\flutter.bat'' finished with non-zero exit value 1
Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
Get more help at https://help.gradle.org
BUILD FAILED in 24s
Finished with error: Gradle build failed: 1
Hi @pulyaevskiy,
what about having the ZefyrField height to not be fixed but to expand based on the content?
Just like a TextField behavior setting maxLines to null to allow it to auto grow vertically.
I took some time off last weekend to test the Zefyr editor and to record some footage of the issues that I encountered. During that process I found two rather minor issues, one concerning the creation of ordered and unordered lists, one concerning the divider functionality.
List creation issue: https://streamable.com/62rn4
Divider issue: https://streamable.com/ze8yj
The issue with the List creation only seems to occur on non-emulated android devices (the footage was recorded on a physical Android 7.1.1 device), since I couldn't reproduce it on my emulated Android device.
The Divider issue can be reproduced on emulated Android devices as well, and throws the error:
W/IInputConnectionWrapper( 3850): getTextBeforeCursor on inactive InputConnection
which would make me think that it is caused by a race condition.
Edit: I just looked at the footage again and it seems like zefyr has a problem with auto corrected text, both in the List creation issue and when you mark text as bold/italic.
Lists creation seems to work fine until you have an autocorrect suggestion and decide NOT to use it and press enter. In this case the autocorrect suggestion seems to be used anyway (and not the original text you typed) and the error occurs.
Hi,
I am not sure this is bug or spec.
But when I tried to compose embed image attribute into NotusDocument, the image information was lost.
Here is the code I wrote.
test('compose embed image', () {
final imageDelta = Delta.fromJson([
{
"insert": "",
"attributes": {
"embed": {"type": "image", "source": "http://img.jpg"},
}
}
])
..insert('\n');
final doc = NotusDocument();
doc.compose(imageDelta, ChangeSource.local);
expect(doc.toDelta(), imageDelta);
});
Expected: Delta:<insert⟨ ⟩ + {embed: {type: image, source: http://img.jpg}}
insert⟨ ⏎ ⟩>
Actual: Delta:<insert⟨ ⏎⏎ ⟩>
Hi @pulyaevskiy,
first of all thanks for this great RTE!
How can I use the editor and the toolbar separately? I can see in your source code that ZefyrEditor
is composed by a ZefyrEditableText
into an Expanded widget and a ZefyrToolbar
; how can I use them to achieve what you can see in the image below?
I need to use the editor ("inline" and not "fullscreen") in a screen with other widgets (post title, post subtitle, images carousel, ..) and maybe set the toolbar in a different and custom position.
Could you please provide some example?
Thank you!
First off, big thanks for this package, much needed, well implemented and very capable. I got it integrated into my app easily enough, just a few minor hickups when coding it in, but got past most of the tricky bits. Just a few things I'm trying to work out now... When embedding an image, it's saved there with {"embed":{"type":"image","source":"file:///... but naturally I needed to take the local file and upload it to server (I'm personally using Firebase Cloud Storage, but may also push to an ftp with Dio or something) to make it shared. Thought there would of been a built in way to do it, but I ended up writing a method to search through the Delta List for the embed attribute, look for the source that starts with file:/// then clean the path, upload the file, wait for complete, get the new image url, make the source attribute = url as an https://...jpg and I'd be good to go. After going through all that and getting the updated delta in place correctly, I end up with this exception:
I/flutter ( 3628): The following UnsupportedError was thrown building RawZefyrLine(state: _RawZefyrLineState#6e77e):
I/flutter ( 3628): Unsupported operation: Cannot extract a file path from a https URI
I/flutter ( 3628): When the exception was thrown, this was the stack:
I/flutter ( 3628): #0 _Uri.toFilePath (dart:core/uri.dart:2606:7)
I/flutter ( 3628): #1 new File.fromUri (dart:io/file.dart:263:49)
So either I'm missing a trick in the way to do a network embed source, or the ability is not in there yet and it's only meant for local files.. Suggestions?
Next thing was, I've got a place where I was stacking up a list of dynamic Delta descriptions from the database for viewing only, didn't need the extra controllers and focusnode stuff but got it in there anyways because I had to. So I got it mostly working, but a few problems I could use help with.. One is I wanted to height to be Flexible/Expaded to fit like I have the Text component, but I could only get it working with a fixed height in the parent container. No matter how I experimented with it, I couldn't make it sized dynamic. I hope there's a way to do it, just couldn't find it.
I also wanted to change the line-spacing, the fontFamily, fontSize, color like we have in the standard Text components, but didn't see any method to change the text style. I expected to see those options as part of the ZefyrThemeData class or ZefyrEditor properties, but wasn't there, I could live with those limitations in the editor, but where I'm displaying it, just doesn't look right..
What I would propose is a separate ZefyrViewer component without the extras in the Editor, but with more options for displaying and a flexible height without the ScrollView in it. I'm pretty sure most people using this would find that useful... There were more little things I was gonna bring up, but probably asking too much already. Thanks guys, much appreciated, looking great so far...
I got an error in xcode when I tried to archive about the 2 plugin that this project uses.
I don't have it to copy paste ( sorry but was last night ).
But it was referring to a folder called "derived data".
Did you hit this for iOS archiving ?
Hello,
I would like to disable the functionality of editing to only make it possible to view the text.
I thought about not passing a FocusNode to the ZefyrEditor but this results in a crash.
Love this project.
We can add offline editing by using Lamport clocks. What this does is ensure globally ordering or OT operations.
THis also allows git style branches and merges to be possible. Users can edit in a branch, and merge to Master and have no conflicts.
If your interested in this i would be happy to help collaborate on this to add it.
I have a widget that contains draggable elements.
I would like to be able to drag these into the text editor to insert text data held by this draggable object.
Would it be possible to display caret position while hovering over the text field? So that it can then be inserted at that position if dropped.
I am not really asking for a solid answer on how to do this.
Just, if it is possible with Zefyr or if I have to make a whole different custom widget centered around this goal.
I figure I just need to display the caret position when I hover over the editor and insert text at the exact position of the caret.
I would suggest to change the bold and italic text style buttons to toggle their respective styles on or off for all following entries.
The current implementation only allows for changing currently marked text to bold/italic, it however makes things very complicated if you mark your last typed text as bold/italic, since this means that all following text is automatically marked as bold or italic without the simple option to turn it off again.
IMHO the option to mark selected text as bold or italic should be kept, if no text is currently selected however the respective buttons should toggle the text styles on/off as described above.
The format of the text that get saved in database is not as the one needed by zefyr editor?
Text that obtained onSubmit:
[insert⟨ Zefyr ⟩, insert⟨ ⏎ ⟩ + {heading: 1}, insert⟨
Soft and gentle rich text editing for Flutter applications. ⟩ + {i: true}, insert⟨ ⏎ ⟩]
which is not valid json format.
I've been digging through the code, and I'm looking for a way to extend the editor with a custom widget. Looking for something similar to the way you can extend Quill.js with custom inline embeds. Any documentation or ideas on how i might go about that?
In many cases, we need to use multi-picture selection。
eg: multi_image_picker
Hi,
I m really stuck here. I don't know how can i show predefined HTML text in Editor With Proper format
Any help would be appreciable
Dummy HTML Text :
<br />\n<strong><u>X-RAY ANKLE JOINT AP/LAT VIEW</u></strong><br />\nNo evidence of fracture is seen.<br />\nBone density is normal<br />\nVisualized bones are normal.<br />\n <br />\n <br />\n<strong>IMPREESION: FINDINGS ARE S/O NORMAL STUDY.</strong> <br />\n<strong><u>X-RAY ANKLE JOINT AP/LAT VIEW</u></strong><br />\nNo evidence of fracture is seen.<br />\nBone density is normal<br />\nVisualized bones are normal.<br />\n <br />\n <br />\n<strong>IMPREESION: FINDINGS ARE S/O NORMAL STUDY.</strong> <br />\n<strong><u>X-RAY ANKLE JOINT AP/LAT VIEW</u></strong><br />\nNo evidence of fracture is seen.<br />\nBone density is normal<br />\nVisualized bones are normal.<br />\n <br />\n <br />\n<strong>IMPREESION: FINDINGS ARE S/O NORMAL STUDY.</strong> <br />\n<strong><u>X-RAY ANKLE JOINT AP/LAT VIEW</u></strong><br />\nNo evidence of fracture is seen.<br />\nBone density is normal<br />\nVis
I want to color the text ,how to achieve this effect?
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.
Here are the common keyboard shortcuts for manipulating text:
Ctrl+Z: Undo.
Ctrl+Shift+Z/Ctrl+Y: Redo.
Ctrl+Backspace: Delete last word.
Shift+Left/Right: Select, move selection to left/right.
Ctrl+A: Select all.
Is it possible to give image source as an https url? Something like this:
[{"insert":"","attributes":{"embed":{"type":"image","source":"https://random_image.jpg"}}},{"insert":"\n"}]
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:preDebugBuild'.
> Android dependency 'com.android.support:support-v4' has different version for the compile (26.1.0) and runtime (27.1.1) classpath. You should manually set the same version via DependencyResolution
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
* Get more help at https://help.gradle.org
BUILD FAILED in 2s
Finished with error: Gradle build failed: 1
Got above error message when I add zefyr to my existing flutter project. But works fine when I only flutter run
the example code in zefyr.
I'm new to android dev, so someone help me what might be the problem here.
Currently zefyr is full-screen and manage scrolling itself. However, as I want to put it in a column (to build a message stream, which looks like this issue page), I found that the ZefyrEditor widget doesn't have a size and tries to expand.
Althought I've looked into the source code, I found that it's hard to configure the selection layer to be the same size as the text which knows it size itself.
Do you have any suggestions? Or maybe this option can be added into zefyr?
Expected to move caret to the nearest paragraph (usually at the end of the document).
Using the example didn't help much for loading and saving data from JSON. Here is the code I used to get it working.
This will auto-insert text into Notus document for backwards compatibility of data stored as plain text and will handle errors too.
import 'package:flutter/material.dart';
import 'package:zefyr/zefyr.dart';
import 'dart:convert';
class MyWidget extends StatefulWidget {
final String json;
MyWidget({this.json});
@override
MyWidgetState createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
ZefyrController _controller;
FocusNode _focusNode;
@override
void initState() {
super.initState();
// Create an empty document or load existing if you have one.
// Here we create an empty document:
var document = NotusDocument();
if (widget.json != null) {
try {
var _json = json.decode(widget.json);
document = NotusDocument.fromJson(_json);
} catch (e) {
print('Error Parsing JSON: $e');
try {
document.insert(0, widget.json);
} catch (exp) {
print('Error Inserting into Document: $exp');
}
}
}
_controller = new ZefyrController(document);
_focusNode = new FocusNode();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Notes',
style: TextStyle(
color: globals.isDark ? Colors.white : Colors.black,
),
),
backgroundColor: globals.isDark ? null : Colors.white,
actions: <Widget>[
IconButton(
icon: Icon(Icons.save),
onPressed: () {
NotusDocument _data = _controller.document;
Navigator.pop(context, json.encode(_data.toJson()));
},
),
],
),
body: SafeArea(
child: ZefyrEditor(
autofocus: true,
controller: _controller,
focusNode: _focusNode,
),
),
);
}
}
is there any interest in this ?
This woudl allow a user to print a zefyr document by first converting it to PDF.
This dart package looks like the good:
https://github.com/DavBfr/dart_pdf
SO all we only need to do write a generic parser in Dart that takes the current zefyr / quill format and convert it to PDF. Because zefyr format is limited ( like markdown in a way) it should not be too hard.
I am not sure if its Notus that is the actual on data structure we work from ?
It seems that copy doesn't work in read mode.
Looking into the code I find that the selection layer disapprars in read mode. I'm not sure it is a bug or intended behavior?
Maybe its me but on both IOS and Android Bold and Italics does not work in the sim because you cant select words or sentence, but only the whole document.
Is this a current limitation of Flutter i wonder ? Being able to access the clipboard properly i mean.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.