Skip to content

Commit

Permalink
Merge pull request #63 from memspace/zefyr-view
Browse files Browse the repository at this point in the history
Zefyr view
  • Loading branch information
pulyaevskiy authored Jan 2, 2019
2 parents 858d2f1 + 11431dd commit 8e3e786
Show file tree
Hide file tree
Showing 42 changed files with 791 additions and 522 deletions.
2 changes: 1 addition & 1 deletion doc/quick_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Add `zefyr` package as a dependency to your `pubspec.yaml`:

```yaml
dependencies:
zefyr: ^0.3.0
zefyr: [latest_version]
```
And run `flutter packages get` to install. This installs both `zefyr`
Expand Down
7 changes: 4 additions & 3 deletions packages/notus/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
analyzer:
language:
enableSuperMixins: true
strong-mode:
implicit-casts: false
implicit-dynamic: false

# Lint rules and documentation, see http://dart-lang.github.io/linter/lints
linter:
rules:
# - avoid_init_to_null
- avoid_init_to_null
- cancel_subscriptions
- close_sinks
- directives_ordering
Expand Down
8 changes: 4 additions & 4 deletions packages/notus/lib/src/convert/markdown.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class _NotusMarkdownEncoder extends Converter<Delta, String> {
String _writeLine(String text, NotusStyle style) {
StringBuffer buffer = new StringBuffer();
if (style.contains(NotusAttribute.heading)) {
_writeAttribute(buffer, style.get(NotusAttribute.heading));
_writeAttribute(buffer, style.get<int>(NotusAttribute.heading));
}

// Write the text itself
Expand Down Expand Up @@ -163,11 +163,11 @@ class _NotusMarkdownEncoder extends Converter<Delta, String> {
} else if (attribute == NotusAttribute.italic) {
_writeItalicTag(buffer);
} else if (attribute.key == NotusAttribute.link.key) {
_writeLinkTag(buffer, attribute, close: close);
_writeLinkTag(buffer, attribute as NotusAttribute<String>, close: close);
} else if (attribute.key == NotusAttribute.heading.key) {
_writeHeadingTag(buffer, attribute);
_writeHeadingTag(buffer, attribute as NotusAttribute<int>);
} else if (attribute.key == NotusAttribute.block.key) {
_writeBlockTag(buffer, attribute, close: close);
_writeBlockTag(buffer, attribute as NotusAttribute<String>, close: close);
} else {
throw new ArgumentError('Cannot handle $attribute');
}
Expand Down
2 changes: 1 addition & 1 deletion packages/notus/lib/src/document.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class NotusDocument {
_loadDocument(_delta);
}

NotusDocument.fromJson(dynamic data)
NotusDocument.fromJson(List data)
: _heuristics = NotusHeuristics.fallback,
_delta = Delta.fromJson(data) {
_loadDocument(_delta);
Expand Down
18 changes: 9 additions & 9 deletions packages/notus/lib/src/document/attributes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class NotusAttribute<T> implements NotusAttributeBuilder<T> {
/// Embed style attribute.
static const embed = const EmbedAttributeBuilder._();

factory NotusAttribute._fromKeyValue(String key, T value) {
static NotusAttribute _fromKeyValue(String key, dynamic value) {
if (!_registry.containsKey(key))
throw new ArgumentError.value(
key, 'No attribute with key "$key" registered.');
Expand Down Expand Up @@ -166,7 +166,7 @@ class NotusAttribute<T> implements NotusAttributeBuilder<T> {
new NotusAttribute<T>._(key, scope, value);

@override
bool operator ==(other) {
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! NotusAttribute<T>) return false;
NotusAttribute<T> typedOther = other;
Expand All @@ -190,11 +190,11 @@ class NotusStyle {

final Map<String, NotusAttribute> _data;

static NotusStyle fromJson(Map data) {
static NotusStyle fromJson(Map<String, dynamic> data) {
if (data == null) return new NotusStyle();

final result = data.map((key, value) {
var attr = new NotusAttribute._fromKeyValue(key, value);
final result = data.map((String key, dynamic value) {
var attr = NotusAttribute._fromKeyValue(key, value);
return new MapEntry<String, NotusAttribute>(key, attr);
});
return new NotusStyle._(result);
Expand Down Expand Up @@ -228,7 +228,7 @@ class NotusStyle {
/// [attribute].
bool containsSame(NotusAttribute attribute) {
assert(attribute != null);
return get(attribute) == attribute;
return get<dynamic>(attribute) == attribute;
}

/// Returns value of specified attribute [key] in this set.
Expand Down Expand Up @@ -290,11 +290,11 @@ class NotusStyle {
/// Returns JSON-serializable representation of this style.
Map<String, dynamic> toJson() => _data.isEmpty
? null
: _data.map(
(_, value) => new MapEntry<String, dynamic>(value.key, value.value));
: _data.map<String, dynamic>((String _, NotusAttribute value) =>
new MapEntry<String, dynamic>(value.key, value.value));

@override
bool operator ==(other) {
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! NotusStyle) return false;
NotusStyle typedOther = other;
Expand Down
2 changes: 1 addition & 1 deletion packages/notus/lib/src/document/block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class BlockNode extends ContainerNode<LineNode>
while (child != line) {
child.unlink();
before.add(child);
child = this.first;
child = this.first as LineNode;
}
line.unlink();
insertBefore(line);
Expand Down
4 changes: 2 additions & 2 deletions packages/notus/lib/src/document/leaf.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ abstract class LeafNode extends Node
assert(index >= 0 && index <= length);
if (index == 0) return this;
if (index == length && isLast) return null;
if (index == length && !isLast) return next;
if (index == length && !isLast) return next as LeafNode;

String text = _value;
_value = text.substring(0, index);
Expand Down Expand Up @@ -124,7 +124,7 @@ abstract class LeafNode extends Node
}

@override
LineNode get parent => super.parent;
LineNode get parent => super.parent as LineNode;

@override
int get length => _value.length;
Expand Down
8 changes: 5 additions & 3 deletions packages/notus/lib/src/document/line.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ class LineNode extends ContainerNode<LeafNode>
if (isLast) {
if (parent is BlockNode) {
if (parent.isLast) return null;
return (parent.next is BlockNode)
LineNode line = (parent.next is BlockNode)
? (parent.next as BlockNode).first
: parent.next;
return line;
} else
return null;
} else {
return (next is BlockNode) ? (next as BlockNode).first : next;
LineNode line = (next is BlockNode) ? (next as BlockNode).first : next;
return line;
}
}

Expand Down Expand Up @@ -129,7 +131,7 @@ class LineNode extends ContainerNode<LeafNode>
result = result.mergeAll(node.style);
int pos = node.length - data.offset;
while (!node.isLast && pos < local) {
node = node.next;
node = node.next as LeafNode;
_handle(node.style);
pos += node.length;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/notus/lib/src/document/node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ abstract class ContainerNode<T extends Node> extends Node {

if (isEmpty) {
assert(index == 0);
Node node = defaultChild;
T node = defaultChild;
add(node);
node.insert(index, value, style);
} else {
Expand Down
3 changes: 2 additions & 1 deletion packages/notus/lib/src/heuristics/delete_rules.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ class PreserveLineStyleOnMergeRule extends DeleteRule {

Map<String, dynamic> _unsetAttributes(Map<String, dynamic> attributes) {
if (attributes == null) return null;
return attributes.map((key, value) => new MapEntry(key, null));
return attributes.map<String, dynamic>((String key, dynamic value) =>
new MapEntry<String, dynamic>(key, null));
}
}

Expand Down
6 changes: 3 additions & 3 deletions packages/notus/lib/src/heuristics/insert_rules.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class ResetLineFormatOnNewLineRule extends InsertRule {
final target = iter.next();

if (target.data.startsWith('\n')) {
Map<String, dynamic> resetStyle = null;
Map<String, dynamic> resetStyle;
if (target.attributes != null &&
target.attributes.containsKey(NotusAttribute.heading.key)) {
resetStyle = NotusAttribute.heading.unset.toJson();
Expand Down Expand Up @@ -290,8 +290,8 @@ class PreserveBlockStyleOnPasteRule extends InsertRule {
}
}

Map<String, dynamic> resetStyle = null;
Map<String, dynamic> blockStyle = null;
Map<String, dynamic> resetStyle;
Map<String, dynamic> blockStyle;
if (lineStyle != null) {
if (lineStyle.containsKey(NotusAttribute.heading.key)) {
resetStyle = NotusAttribute.heading.unset.toJson();
Expand Down
2 changes: 1 addition & 1 deletion packages/notus/test/convert/markdown_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void main() {

final doc =
r'[{"insert":"Zefyr"},{"insert":"\n","attributes":{"heading":1}},{"insert":"Soft and gentle rich text editing for Flutter applications.","attributes":{"i":true}},{"insert":"\nZefyr is an "},{"insert":"early preview","attributes":{"b":true}},{"insert":" open source library.\nDocumentation"},{"insert":"\n","attributes":{"heading":3}},{"insert":"Quick Start"},{"insert":"\n","attributes":{"block":"ul"}},{"insert":"Data format and Document Model"},{"insert":"\n","attributes":{"block":"ul"}},{"insert":"Style attributes"},{"insert":"\n","attributes":{"block":"ul"}},{"insert":"Heuristic rules"},{"insert":"\n","attributes":{"block":"ul"}},{"insert":"Clean and modern look"},{"insert":"\n","attributes":{"heading":2}},{"insert":"Zefyr’s rich text editor is built with simplicity and flexibility in mind. It provides clean interface for distraction-free editing. Think Medium.com-like experience.\nimport ‘package:flutter/material.dart’;"},{"insert":"\n","attributes":{"block":"code"}},{"insert":"import ‘package:notus/notus.dart’;"},{"insert":"\n\n","attributes":{"block":"code"}},{"insert":"void main() {"},{"insert":"\n","attributes":{"block":"code"}},{"insert":" print(“Hello world!”);"},{"insert":"\n","attributes":{"block":"code"}},{"insert":"}"},{"insert":"\n","attributes":{"block":"code"}}]';
final delta = Delta.fromJson(json.decode(doc));
final delta = Delta.fromJson(json.decode(doc) as List);

final expectedMarkdown = '''
# Zefyr
Expand Down
2 changes: 1 addition & 1 deletion packages/notus/test/document/attributes_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:notus/notus.dart';
void main() {
group('$NotusStyle', () {
test('get', () {
var attrs = NotusStyle.fromJson({'block': 'ul'});
var attrs = NotusStyle.fromJson(<String, dynamic>{'block': 'ul'});
var attr = attrs.get(NotusAttribute.block);
expect(attr, NotusAttribute.ul);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/notus/test/document_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void main() {
test('json serialization', () {
final original = dartconfDoc();
final jsonData = json.encode(original);
final doc = NotusDocument.fromJson(json.decode(jsonData));
final doc = NotusDocument.fromJson(json.decode(jsonData) as List);
expect(doc.toDelta(), original.toDelta());
expect(json.encode(doc), jsonData);
});
Expand Down
13 changes: 13 additions & 0 deletions packages/zefyr/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## Unreleased

* Added non-scrollable `ZefyrView` widget which allows previewing Notus documents inside
layouts using their own scrollables like ListView.
* Breaking change: renamed `EditableRichText` to `ZefyrRichText`. User code is unlikely to be
affected unless you've extended Zefyr with custom implementations of block widgets.
* Breaking change: renamed `RenderEditableParagraph` to `RenderZefyrParagraph`. User code is
unlikely to be affected unless you've extended Zefyr with custom implementations of block widgets.
* Added `ZefyrScope` class - replaces previously used scope objects `ZefyrEditableTextScope` and
`ZefyrEditorScope`. Unified all shared resources under one class.
* Breaking change: removed `ZefyrEditor.of` and `ZefyrEditableText.of` static methods.
Use `ZefyrScope.of` instead.

## 0.3.0

This version introduces new widget `ZefyrScaffold` which allows embedding Zefyr in custom
Expand Down
7 changes: 4 additions & 3 deletions packages/zefyr/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
analyzer:
language:
# enableSuperMixins: true
strong-mode:
implicit-casts: false
implicit-dynamic: false

# Lint rules and documentation, see http://dart-lang.github.io/linter/lints
linter:
rules:
# - avoid_init_to_null
- avoid_init_to_null
- cancel_subscriptions
- close_sinks
- directives_ordering
Expand Down
12 changes: 12 additions & 0 deletions packages/zefyr/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import 'package:flutter/material.dart';
import 'src/form.dart';
import 'src/full_page.dart';
import 'src/view.dart';

void main() {
runApp(new ZefyrApp());
Expand All @@ -20,6 +21,7 @@ class ZefyrApp extends StatelessWidget {
routes: {
"/fullPage": buildFullPage,
"/form": buildFormPage,
"/view": buildViewPage,
},
);
}
Expand All @@ -31,6 +33,10 @@ class ZefyrApp extends StatelessWidget {
Widget buildFormPage(BuildContext context) {
return FormEmbeddedScreen();
}

Widget buildViewPage(BuildContext context) {
return ViewScreen();
}
}

class HomePage extends StatelessWidget {
Expand Down Expand Up @@ -59,6 +65,12 @@ class HomePage extends StatelessWidget {
color: Colors.lightBlue,
textColor: Colors.white,
),
FlatButton(
onPressed: () => nav.pushNamed('/view'),
child: Text('Read-only embeddable view'),
color: Colors.lightBlue,
textColor: Colors.white,
),
Expanded(child: Container()),
],
),
Expand Down
18 changes: 17 additions & 1 deletion packages/zefyr/example/lib/src/full_page.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
Expand Down Expand Up @@ -31,14 +32,29 @@ final doc =
r'g":2}},{"insert":"Of course:\nimport ‘package:flutter/material.dart’;"},{"insert":"\n","attributes":{"block":"code"}},{"insert":"import ‘package:zefyr/zefyr.dart’;"},{"insert":"\n\n","attributes":{"block":"code"}},{"insert":"void main() {"},{"insert":"\n","attributes":{"block":"code"}},{"insert":" runApp(MyZefyrApp());"},{"insert":"\n","attributes":{"block":"code"}},{"insert":"}"},{"insert":"\n","attributes":{"block":"code"}},{"insert":"\n\n\n"}]';

Delta getDelta() {
return Delta.fromJson(json.decode(doc));
return Delta.fromJson(json.decode(doc) as List);
}

class _FullPageEditorScreenState extends State<FullPageEditorScreen> {
final ZefyrController _controller =
ZefyrController(NotusDocument.fromDelta(getDelta()));
final FocusNode _focusNode = new FocusNode();
bool _editing = false;
StreamSubscription<NotusChange> _sub;

@override
void initState() {
super.initState();
_sub = _controller.document.changes.listen((change) {
print('${change.source}: ${change.change}');
});
}

@override
void dispose() {
_sub.cancel();
super.dispose();
}

@override
Widget build(BuildContext context) {
Expand Down
Loading

0 comments on commit 8e3e786

Please sign in to comment.