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

Zefyr video #516

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
996a440
Changed constraints in imageS
devakrishna33 May 30, 2020
a294b6a
Changed the position of image icon
devakrishna33 Jun 13, 2020
4ccf388
Changed link button styles
devakrishna33 Jun 13, 2020
fa643e7
Changed link button styles
devakrishna33 Jun 13, 2020
4f7fafa
Resolved issue with empty links
devakrishna33 Jun 13, 2020
9b9dc7e
Added underline feature
devakrishna33 Jun 25, 2020
0f0fcc8
Added underline to toolbar
devakrishna33 Jun 25, 2020
d71e916
Added buildbutton function for underline
devakrishna33 Jun 25, 2020
d1be4f8
Updated notus document for alignment options
devakrishna33 Jun 25, 2020
2ae781c
Completed the align items function
devakrishna33 Jun 25, 2020
4af87d8
Changed default alignment
devakrishna33 Jun 25, 2020
3c2df56
Resolved issue with textalign
devakrishna33 Jun 25, 2020
9d71e9f
Changed align to a block scoped style instead of a line scoped style
devakrishna33 Jun 25, 2020
8ccd772
Refactored align into block level styles
devakrishna33 Jun 25, 2020
98770e0
Refactored align into list
devakrishna33 Jun 25, 2020
475e304
Resolved issue with ui not updating on button click
devakrishna33 Jun 25, 2020
f45745b
Resolved issue with alignment not changing
devakrishna33 Jun 26, 2020
aba9499
Resolved issue with unique key
devakrishna33 Jun 26, 2020
f599e01
Added undo, redo functionality
devakrishna33 Jul 29, 2020
9b3d5df
Added scrollable parameter
devakrishna33 Jul 30, 2020
4f22623
Added scrollable parameter
devakrishna33 Jul 30, 2020
902d68b
Reverted to previous state
devakrishna33 Jul 30, 2020
a0e88e5
Changed font size of heading
devakrishna33 Jul 30, 2020
06708b8
Changed styles of heading 1 and heading 2
devakrishna33 Jul 30, 2020
fdc8b2e
Resolved issue with padding
devakrishna33 Jul 30, 2020
a3b4437
Made it compatbile with flutter latest version
devakrishna33 Aug 8, 2020
ebd0bd8
Resolved issue with flutter version
devakrishna33 Aug 12, 2020
83bda5f
Added showing paste option on long press
devakrishna33 Sep 7, 2020
ab48082
Resolved issue with scrolling
devakrishna33 Sep 11, 2020
6b70662
Adding Video Widget
msavanan Jul 19, 2021
8846370
added example
msavanan Jul 19, 2021
d1b2a9f
Added Youtube link dialog & button
msavanan Jul 23, 2021
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 packages/notus/lib/notus.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export 'src/heuristics.dart';
export 'src/heuristics/delete_rules.dart';
export 'src/heuristics/format_rules.dart';
export 'src/heuristics/insert_rules.dart';
export 'src/history.dart';
28 changes: 26 additions & 2 deletions packages/notus/lib/src/document.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import 'dart:async';

import 'package:quill_delta/quill_delta.dart';
import 'package:notus/notus.dart';

import 'document/attributes.dart';
import 'document/block.dart';
Expand Down Expand Up @@ -40,25 +41,37 @@ class NotusDocument {
/// Creates new empty Notus document.
NotusDocument()
: _heuristics = NotusHeuristics.fallback,
_history = NotusHistory(),
_delta = Delta()..insert('\n') {
_loadDocument(_delta);
}

NotusDocument.fromJson(List data)
: _heuristics = NotusHeuristics.fallback,
_history = NotusHistory(),
_delta = Delta.fromJson(data) {
_loadDocument(_delta);
}

NotusDocument.fromDelta(Delta delta)
: assert(delta != null),
_heuristics = NotusHeuristics.fallback,
_history = NotusHistory(),
_delta = delta {
_loadDocument(_delta);
}

final NotusHeuristics _heuristics;

NotusHistory _history;

set history(NotusHistory value) {
_history?.clear();
_history = value;
}

NotusHistory get history => _history;

/// The root node of this document tree.
RootNode get root => _root;
final RootNode _root = RootNode();
Expand Down Expand Up @@ -92,6 +105,7 @@ class NotusDocument {
/// Closes [changes] stream.
void close() {
_controller.close();
_history.clear();
}

/// Inserts [text] in this document at specified [index].
Expand Down Expand Up @@ -216,7 +230,7 @@ class NotusDocument {
/// of this document.
///
/// In case the [change] is invalid, behavior of this method is unspecified.
void compose(Delta change, ChangeSource source) {
void compose(Delta change, ChangeSource source, {bool history}) {
_checkMutable();
change.trim();
assert(change.isNotEmpty);
Expand All @@ -241,7 +255,9 @@ class NotusDocument {
throw StateError('Compose produced inconsistent results. '
'This is likely due to a bug in the library. Tried to compose change $change from $source.');
}
_controller.add(NotusChange(before, change, source));
final notusChange = NotusChange(before, change, source);
_controller.add(notusChange);
if (history != true) _history?.handleDocChange(notusChange);
}

//
Expand Down Expand Up @@ -293,4 +309,12 @@ class NotusDocument {
_root.remove(node);
}
}

void undo() {
_history?.undo(this);
}

void redo() {
_history?.redo(this);
}
}
54 changes: 53 additions & 1 deletion packages/notus/lib/src/document/attributes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,32 @@ abstract class NotusAttributeBuilder<T> implements NotusAttributeKey<T> {
/// document.format(0, 5, NotusAttribute.bold);
/// // Similarly for italic
/// document.format(0, 5, NotusAttribute.italic);
/// // Similarly for underline
/// document.format(0, 5, NotusAttribute.underline)
/// // Format first line as a heading (h1)
/// // Note that there is no need to specify character range of the whole
/// // line. Simply set index position to anywhere within the line and
/// // length to 0.
/// document.format(0, 0, NotusAttribute.h1);
/// // Note that there is no need to specify character range of the whole
/// // line. Simply set index position to anywhere within the line and
/// // length to 0.
/// document.format(0, 0, NotusAttribute.left);
/// }
///
/// List of supported attributes:
///
/// * [NotusAttribute.bold]
/// * [NotusAttribute.italic]
/// * [NotusAttribute.underline]
/// * [NotusAttribute.link]
/// * [NotusAttribute.heading]
/// * [NotusAttribute.block]
class NotusAttribute<T> implements NotusAttributeBuilder<T> {
static final Map<String, NotusAttributeBuilder> _registry = {
NotusAttribute.bold.key: NotusAttribute.bold,
NotusAttribute.italic.key: NotusAttribute.italic,
NotusAttribute.underline.key: NotusAttribute.underline,
NotusAttribute.link.key: NotusAttribute.link,
NotusAttribute.heading.key: NotusAttribute.heading,
NotusAttribute.block.key: NotusAttribute.block,
Expand All @@ -88,6 +96,9 @@ class NotusAttribute<T> implements NotusAttributeBuilder<T> {
/// Italic style attribute.
static const italic = _ItalicAttribute();

/// Underline style attribure.
static const underline = _UnderlineAttribute();

/// Link style attribute.
// ignore: const_eval_throws_exception
static const link = LinkAttributeBuilder._();
Expand Down Expand Up @@ -120,6 +131,18 @@ class NotusAttribute<T> implements NotusAttributeBuilder<T> {
/// Alias for [NotusAttribute.block.quote].
static NotusAttribute<String> get bq => block.quote;

/// Alias for [NotusAttribute.block.alignLeft].
static NotusAttribute<String> get alignLeft => block.alignLeft;

/// Alias for [NotusAttribute.block.alignRight].
static NotusAttribute<String> get alignRight => block.alignRight;

/// Alias for [NotusAttribute.block.alignCenter].
static NotusAttribute<String> get alignCenter => block.alignCenter;

/// Alias for [NotusAttribute.block.alignJustify].
static NotusAttribute<String> get alignJustify => block.alignJustify;

/// Alias for [NotusAttribute.block.code].
static NotusAttribute<String> get code => block.code;

Expand Down Expand Up @@ -332,6 +355,11 @@ class _ItalicAttribute extends NotusAttribute<bool> {
const _ItalicAttribute() : super._('i', NotusAttributeScope.inline, true);
}

/// Applies underline style to a text segment.
class _UnderlineAttribute extends NotusAttribute<bool> {
const _UnderlineAttribute() : super._('u', NotusAttributeScope.inline, true);
}

/// Builder for link attribute values.
///
/// There is no need to use this class directly, consider using
Expand Down Expand Up @@ -387,6 +415,22 @@ class BlockAttributeBuilder extends NotusAttributeBuilder<String> {
/// Formats a block of lines as a quote.
NotusAttribute<String> get quote =>
NotusAttribute<String>._(key, scope, 'quote');

/// Formats a block of lines into align left.
NotusAttribute<String> get alignLeft =>
NotusAttribute<String>._(key, scope, 'alignLeft');

/// Formats a block of lines into align right.
NotusAttribute<String> get alignRight =>
NotusAttribute<String>._(key, scope, 'alignRight');

/// Formats a block of lines into align center.
NotusAttribute<String> get alignCenter =>
NotusAttribute<String>._(key, scope, 'alignCenter');

/// Formats a block of lines into align justify.
NotusAttribute<String> get alignJustify =>
NotusAttribute<String>._(key, scope, 'alignJustify');
}

class EmbedAttributeBuilder
Expand All @@ -399,6 +443,9 @@ class EmbedAttributeBuilder

NotusAttribute<Map<String, dynamic>> image(String source) =>
EmbedAttribute.image(source);

NotusAttribute<Map<String, dynamic>> video(String source) =>
EmbedAttribute.video(source);

@override
NotusAttribute<Map<String, dynamic>> get unset => EmbedAttribute._(null);
Expand All @@ -409,13 +456,14 @@ class EmbedAttributeBuilder
}

/// Type of embedded content.
enum EmbedType { horizontalRule, image }
enum EmbedType { horizontalRule, image, video }

class EmbedAttribute extends NotusAttribute<Map<String, dynamic>> {
static const _kValueEquality = MapEquality<String, dynamic>();
static const _kEmbed = 'embed';
static const _kHorizontalRuleEmbed = 'hr';
static const _kImageEmbed = 'image';
static const _KVideoEmbed = 'video';

EmbedAttribute._(Map<String, dynamic> value)
: super._(_kEmbed, NotusAttributeScope.inline, value);
Expand All @@ -426,10 +474,14 @@ class EmbedAttribute extends NotusAttribute<Map<String, dynamic>> {
EmbedAttribute.image(String source)
: this._(<String, dynamic>{'type': _kImageEmbed, 'source': source});

EmbedAttribute.video(String source)
: this._(<String, dynamic>{'type': _KVideoEmbed, 'source': source});

/// Type of this embed.
EmbedType get type {
if (value['type'] == _kHorizontalRuleEmbed) return EmbedType.horizontalRule;
if (value['type'] == _kImageEmbed) return EmbedType.image;
if (value['type'] == _KVideoEmbed) return EmbedType.video;
assert(false, 'Unknown embed attribute value $value.');
return null;
}
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 @@ -10,7 +10,7 @@ import 'node.dart';
/// A block represents a group of adjacent [LineNode]s with the same block
/// style.
///
/// Block examples: lists, quotes, code snippets.
/// Block examples: lists, quotes, code snippets, alignment.
class BlockNode extends ContainerNode<LineNode>
with StyledNodeMixin
implements StyledNode {
Expand Down
119 changes: 119 additions & 0 deletions packages/notus/lib/src/history.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import 'package:notus/notus.dart';
import 'package:notus/src/document.dart';
import 'package:quill_delta/quill_delta.dart';

///
/// record users operation or api change(Collaborative editing)
/// used for redo or undo function
///
class NotusHistory {
final NotusHistoryStack stack = NotusHistoryStack.empty();

/// used for disable redo or undo function
bool ignoreChange;

int lastRecorded;

///Collaborative editing's conditions should be true
final bool userOnly;

///max operation count for undo
final int maxStack;

///record delay
final int interval;

NotusHistory(
{this.ignoreChange = false,
this.interval = 400,
this.maxStack = 100,
this.userOnly = false,
this.lastRecorded = 0});

void handleDocChange(NotusChange event) {
if (ignoreChange) return;
if (!userOnly || event.source == ChangeSource.local) {
record(event.change, event.before);
} else {
transform(event.change);
}
}

void clear() {
stack.clear();
}

void record(Delta change, Delta before) {
if (change.isEmpty) return;
stack.redo.clear();
Delta undoDelta = change.invert(before);
final timeStamp = DateTime.now().millisecondsSinceEpoch;

if (lastRecorded + interval > timeStamp && stack.undo.isNotEmpty) {
final lastDelta = stack.undo.removeLast();
undoDelta = undoDelta.compose(lastDelta);
} else {
lastRecorded = timeStamp;
}

if (undoDelta.isEmpty) return;
stack.undo.add(undoDelta);

if (stack.undo.length > maxStack) {
stack.undo.removeAt(0);
}
}

///
///It will override pre local undo delta,replaced by remote change
///
void transform(Delta delta) {
transformStack(this.stack.undo, delta);
transformStack(this.stack.redo, delta);
}

void transformStack(List<Delta> stack, Delta delta) {
for (int i = stack.length - 1; i >= 0; i -= 1) {
final oldDelta = stack[i];
stack[i] = delta.transform(oldDelta, true);
delta = oldDelta.transform(delta, false);
if (stack[i].length == 0) {
stack.removeAt(i);
}
}
}

void _change(NotusDocument doc, List<Delta> source, List<Delta> dest) {
if (source.length == 0) return;
Delta delta = source.removeLast();
Delta base = doc.toDelta();
Delta inverseDelta = delta.invert(base);
dest.add(inverseDelta);
this.lastRecorded = 0;
this.ignoreChange = true;
doc.compose(delta, ChangeSource.local, history: true);
this.ignoreChange = false;
}

void undo(NotusDocument doc) {
_change(doc, stack.undo, stack.redo);
}

void redo(NotusDocument doc) {
_change(doc, stack.redo, stack.undo);
}
}

class NotusHistoryStack {
final List<Delta> undo;
final List<Delta> redo;

NotusHistoryStack.empty()
: undo = [],
redo = [];

void clear() {
undo.clear();
redo.clear();
}
}
2 changes: 1 addition & 1 deletion packages/notus/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ author: Anatoly Pulyaevskiy <anatoly.pulyaevskiy@gmail.com>
homepage: https://github.com/memspace/zefyr

environment:
sdk: '>=2.2.0 <3.0.0'
sdk: ">=2.2.0 <3.0.0"

dependencies:
collection: ^1.14.6
Expand Down
1 change: 1 addition & 0 deletions packages/zefyr/example/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
14 changes: 14 additions & 0 deletions packages/zefyr/example/lib/generated_plugin_registrant.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Generated file. Do not edit.
//

import 'package:flutter_web_plugins/flutter_web_plugins.dart';
// ignore_for_file: lines_longer_than_80_chars

import 'package:url_launcher_web/url_launcher_web.dart';

// ignore: public_member_api_docs
void registerPlugins(Registrar registrar) {
UrlLauncherPlugin.registerWith(registrar);
registrar.messenger; //registerMessageHandler();
}
2 changes: 1 addition & 1 deletion packages/zefyr/example/lib/src/form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class _FormEmbeddedScreenState extends State<FormEmbeddedScreen> {
);

final result = Scaffold(
resizeToAvoidBottomPadding: true,
resizeToAvoidBottomInset: true,
appBar: AppBar(
title: ZefyrLogo(),
actions: [
Expand Down
Loading