add flowy icon

This commit is contained in:
appflowy 2021-09-12 22:19:59 +08:00
parent a4338652e0
commit 54136c1018
34 changed files with 168 additions and 280 deletions

View File

@ -2,7 +2,7 @@ import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/welcome/presentation/splash_screen.dart';
import 'package:flutter/material.dart';
class FlowyAppFactory implements AppFactory {
class FlowyApp implements EntryPoint {
@override
Widget create() {
return const SplashScreen();
@ -10,5 +10,5 @@ class FlowyAppFactory implements AppFactory {
}
void main() {
Application.run(FlowyAppFactory());
System.run(FlowyApp());
}

View File

@ -10,17 +10,17 @@ enum IntegrationEnv {
pro,
}
abstract class AppFactory {
abstract class EntryPoint {
Widget create();
}
class Application {
static void run(AppFactory f) {
class System {
static void run(EntryPoint f) {
// Specify the evn
const env = IntegrationEnv.dev;
// Config the deps graph
getIt.registerFactory<AppFactory>(() => f);
getIt.registerFactory<EntryPoint>(() => f);
resolveDependencies(env);

View File

@ -12,7 +12,7 @@ class AppWidgetTask extends LaunchTask {
@override
Future<void> initialize(LaunchContext context) {
final widget = context.getIt<AppFactory>().create();
final widget = context.getIt<EntryPoint>().create();
final app = ApplicationWidget(child: widget);
runApp(app);

View File

@ -1,2 +1,2 @@
export 'application_task.dart';
export 'rust_sdk_init_task.dart';
export 'sdk_task.dart';

View File

@ -16,7 +16,7 @@ class DocBloc extends Bloc<DocEvent, DocState> {
@override
Stream<DocState> mapEventToState(DocEvent event) async* {
yield* event.map(
started: (_) async* {
loadDoc: (_) async* {
yield* _readDoc();
},
);
@ -44,12 +44,12 @@ class DocBloc extends Bloc<DocEvent, DocState> {
@freezed
class DocEvent with _$DocEvent {
const factory DocEvent.started() = Started;
const factory DocEvent.loadDoc() = LoadDoc;
}
@freezed
class DocState with _$DocState {
const factory DocState.loading() = Loading;
const factory DocState.loadDoc(FlowyDoc doc) = LoadDoc;
const factory DocState.loadDoc(FlowyDoc doc) = LoadedDoc;
const factory DocState.loadFail(WorkspaceError error) = LoadFail;
}

View File

@ -16,8 +16,8 @@ final _privateConstructorUsedError = UnsupportedError(
class _$DocEventTearOff {
const _$DocEventTearOff();
Started started() {
return const Started();
LoadDoc loadDoc() {
return const LoadDoc();
}
}
@ -28,23 +28,23 @@ const $DocEvent = _$DocEventTearOff();
mixin _$DocEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() started,
required TResult Function() loadDoc,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? started,
TResult Function()? loadDoc,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Started value) started,
required TResult Function(LoadDoc value) loadDoc,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Started value)? started,
TResult Function(LoadDoc value)? loadDoc,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@ -66,34 +66,34 @@ class _$DocEventCopyWithImpl<$Res> implements $DocEventCopyWith<$Res> {
}
/// @nodoc
abstract class $StartedCopyWith<$Res> {
factory $StartedCopyWith(Started value, $Res Function(Started) then) =
_$StartedCopyWithImpl<$Res>;
abstract class $LoadDocCopyWith<$Res> {
factory $LoadDocCopyWith(LoadDoc value, $Res Function(LoadDoc) then) =
_$LoadDocCopyWithImpl<$Res>;
}
/// @nodoc
class _$StartedCopyWithImpl<$Res> extends _$DocEventCopyWithImpl<$Res>
implements $StartedCopyWith<$Res> {
_$StartedCopyWithImpl(Started _value, $Res Function(Started) _then)
: super(_value, (v) => _then(v as Started));
class _$LoadDocCopyWithImpl<$Res> extends _$DocEventCopyWithImpl<$Res>
implements $LoadDocCopyWith<$Res> {
_$LoadDocCopyWithImpl(LoadDoc _value, $Res Function(LoadDoc) _then)
: super(_value, (v) => _then(v as LoadDoc));
@override
Started get _value => super._value as Started;
LoadDoc get _value => super._value as LoadDoc;
}
/// @nodoc
class _$Started implements Started {
const _$Started();
class _$LoadDoc implements LoadDoc {
const _$LoadDoc();
@override
String toString() {
return 'DocEvent.started()';
return 'DocEvent.loadDoc()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is Started);
return identical(this, other) || (other is LoadDoc);
}
@override
@ -102,19 +102,19 @@ class _$Started implements Started {
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() started,
required TResult Function() loadDoc,
}) {
return started();
return loadDoc();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? started,
TResult Function()? loadDoc,
required TResult orElse(),
}) {
if (started != null) {
return started();
if (loadDoc != null) {
return loadDoc();
}
return orElse();
}
@ -122,26 +122,26 @@ class _$Started implements Started {
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Started value) started,
required TResult Function(LoadDoc value) loadDoc,
}) {
return started(this);
return loadDoc(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Started value)? started,
TResult Function(LoadDoc value)? loadDoc,
required TResult orElse(),
}) {
if (started != null) {
return started(this);
if (loadDoc != null) {
return loadDoc(this);
}
return orElse();
}
}
abstract class Started implements DocEvent {
const factory Started() = _$Started;
abstract class LoadDoc implements DocEvent {
const factory LoadDoc() = _$LoadDoc;
}
/// @nodoc
@ -152,8 +152,8 @@ class _$DocStateTearOff {
return const Loading();
}
LoadDoc loadDoc(FlowyDoc doc) {
return LoadDoc(
LoadedDoc loadDoc(FlowyDoc doc) {
return LoadedDoc(
doc,
);
}
@ -188,14 +188,14 @@ mixin _$DocState {
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Loading value) loading,
required TResult Function(LoadDoc value) loadDoc,
required TResult Function(LoadedDoc value) loadDoc,
required TResult Function(LoadFail value) loadFail,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Loading value)? loading,
TResult Function(LoadDoc value)? loadDoc,
TResult Function(LoadedDoc value)? loadDoc,
TResult Function(LoadFail value)? loadFail,
required TResult orElse(),
}) =>
@ -279,7 +279,7 @@ class _$Loading implements Loading {
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Loading value) loading,
required TResult Function(LoadDoc value) loadDoc,
required TResult Function(LoadedDoc value) loadDoc,
required TResult Function(LoadFail value) loadFail,
}) {
return loading(this);
@ -289,7 +289,7 @@ class _$Loading implements Loading {
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Loading value)? loading,
TResult Function(LoadDoc value)? loadDoc,
TResult Function(LoadedDoc value)? loadDoc,
TResult Function(LoadFail value)? loadFail,
required TResult orElse(),
}) {
@ -305,26 +305,26 @@ abstract class Loading implements DocState {
}
/// @nodoc
abstract class $LoadDocCopyWith<$Res> {
factory $LoadDocCopyWith(LoadDoc value, $Res Function(LoadDoc) then) =
_$LoadDocCopyWithImpl<$Res>;
abstract class $LoadedDocCopyWith<$Res> {
factory $LoadedDocCopyWith(LoadedDoc value, $Res Function(LoadedDoc) then) =
_$LoadedDocCopyWithImpl<$Res>;
$Res call({FlowyDoc doc});
}
/// @nodoc
class _$LoadDocCopyWithImpl<$Res> extends _$DocStateCopyWithImpl<$Res>
implements $LoadDocCopyWith<$Res> {
_$LoadDocCopyWithImpl(LoadDoc _value, $Res Function(LoadDoc) _then)
: super(_value, (v) => _then(v as LoadDoc));
class _$LoadedDocCopyWithImpl<$Res> extends _$DocStateCopyWithImpl<$Res>
implements $LoadedDocCopyWith<$Res> {
_$LoadedDocCopyWithImpl(LoadedDoc _value, $Res Function(LoadedDoc) _then)
: super(_value, (v) => _then(v as LoadedDoc));
@override
LoadDoc get _value => super._value as LoadDoc;
LoadedDoc get _value => super._value as LoadedDoc;
@override
$Res call({
Object? doc = freezed,
}) {
return _then(LoadDoc(
return _then(LoadedDoc(
doc == freezed
? _value.doc
: doc // ignore: cast_nullable_to_non_nullable
@ -335,8 +335,8 @@ class _$LoadDocCopyWithImpl<$Res> extends _$DocStateCopyWithImpl<$Res>
/// @nodoc
class _$LoadDoc implements LoadDoc {
const _$LoadDoc(this.doc);
class _$LoadedDoc implements LoadedDoc {
const _$LoadedDoc(this.doc);
@override
final FlowyDoc doc;
@ -349,7 +349,7 @@ class _$LoadDoc implements LoadDoc {
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is LoadDoc &&
(other is LoadedDoc &&
(identical(other.doc, doc) ||
const DeepCollectionEquality().equals(other.doc, doc)));
}
@ -360,8 +360,8 @@ class _$LoadDoc implements LoadDoc {
@JsonKey(ignore: true)
@override
$LoadDocCopyWith<LoadDoc> get copyWith =>
_$LoadDocCopyWithImpl<LoadDoc>(this, _$identity);
$LoadedDocCopyWith<LoadedDoc> get copyWith =>
_$LoadedDocCopyWithImpl<LoadedDoc>(this, _$identity);
@override
@optionalTypeArgs
@ -391,7 +391,7 @@ class _$LoadDoc implements LoadDoc {
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Loading value) loading,
required TResult Function(LoadDoc value) loadDoc,
required TResult Function(LoadedDoc value) loadDoc,
required TResult Function(LoadFail value) loadFail,
}) {
return loadDoc(this);
@ -401,7 +401,7 @@ class _$LoadDoc implements LoadDoc {
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Loading value)? loading,
TResult Function(LoadDoc value)? loadDoc,
TResult Function(LoadedDoc value)? loadDoc,
TResult Function(LoadFail value)? loadFail,
required TResult orElse(),
}) {
@ -412,12 +412,13 @@ class _$LoadDoc implements LoadDoc {
}
}
abstract class LoadDoc implements DocState {
const factory LoadDoc(FlowyDoc doc) = _$LoadDoc;
abstract class LoadedDoc implements DocState {
const factory LoadedDoc(FlowyDoc doc) = _$LoadedDoc;
FlowyDoc get doc => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$LoadDocCopyWith<LoadDoc> get copyWith => throw _privateConstructorUsedError;
$LoadedDocCopyWith<LoadedDoc> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
@ -507,7 +508,7 @@ class _$LoadFail implements LoadFail {
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Loading value) loading,
required TResult Function(LoadDoc value) loadDoc,
required TResult Function(LoadedDoc value) loadDoc,
required TResult Function(LoadFail value) loadFail,
}) {
return loadFail(this);
@ -517,7 +518,7 @@ class _$LoadFail implements LoadFail {
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Loading value)? loading,
TResult Function(LoadDoc value)? loadDoc,
TResult Function(LoadedDoc value)? loadDoc,
TResult Function(LoadFail value)? loadFail,
required TResult orElse(),
}) {

View File

@ -2,7 +2,7 @@ import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:app_flowy/workspace/presentation/doc/doc_page.dart';
import 'package:app_flowy/workspace/presentation/doc/doc_stack_page.dart';
import 'package:app_flowy/workspace/presentation/widgets/blank_page.dart';
import 'package:app_flowy/workspace/presentation/widgets/fading_index_stack.dart';
import 'package:app_flowy/workspace/presentation/widgets/prelude.dart';
@ -78,17 +78,18 @@ List<Widget> _buildStackWidget(HomeStackView stackView) {
if (viewType == stackView.type) {
switch (stackView.type) {
case ViewType.Blank:
return AnnouncementPage(
return AnnouncementStackPage(
stackView: stackView as AnnouncementStackView);
case ViewType.Doc:
final docView = stackView as DocPageStackView;
return DocPage(key: ValueKey(docView.view.id), stackView: docView);
return DocStackPage(
key: ValueKey(docView.view.id), stackView: docView);
default:
return AnnouncementPage(
return AnnouncementStackPage(
stackView: stackView as AnnouncementStackView);
}
} else {
return const AnnouncementPage(stackView: AnnouncementStackView());
return const AnnouncementStackPage(stackView: AnnouncementStackView());
}
}).toList();
}

View File

@ -8,12 +8,12 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// ignore: must_be_immutable
class EditorPage extends StatelessWidget {
class DocPage extends StatelessWidget {
final FocusNode _focusNode = FocusNode();
late EditorController controller;
final FlowyDoc doc;
EditorPage({Key? key, required this.doc}) : super(key: key) {
DocPage({Key? key, required this.doc}) : super(key: key) {
controller = EditorController(
document: doc.data,
selection: const TextSelection.collapsed(offset: 0),

View File

@ -1,7 +1,7 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/view/doc_watch_bloc.dart';
import 'package:app_flowy/workspace/application/doc/doc_bloc.dart';
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
import 'package:app_flowy/workspace/presentation/doc/editor_page.dart';
import 'package:app_flowy/workspace/presentation/doc/doc_page.dart';
import 'package:flowy_infra/flowy_logger.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
@ -9,30 +9,29 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flowy_infra_ui/style_widget/progress_indicator.dart';
class DocPage extends HomeStackWidget {
const DocPage({Key? key, required DocPageStackView stackView})
class DocStackPage extends HomeStackWidget {
const DocStackPage({Key? key, required DocPageStackView stackView})
: super(key: key, stackView: stackView);
@override
_DocPageState createState() => _DocPageState();
_DocStackPageState createState() => _DocStackPageState();
}
class _DocPageState extends State<DocPage> {
class _DocStackPageState extends State<DocStackPage> {
@override
Widget build(BuildContext context) {
final stackView = widget.stackView as DocPageStackView;
return MultiBlocProvider(
providers: [
BlocProvider<DocWatchBloc>(
create: (context) => getIt<DocWatchBloc>(param1: stackView.view.id)
..add(const DocWatchEvent.started())),
BlocProvider<DocBloc>(
create: (context) => getIt<DocBloc>(param1: stackView.view.id)
..add(const DocEvent.loadDoc())),
],
child:
BlocBuilder<DocWatchBloc, DocWatchState>(builder: (context, state) {
child: BlocBuilder<DocBloc, DocState>(builder: (context, state) {
assert(widget.stackView is DocPageStackView);
return state.map(
loading: (_) => const FlowyProgressIndicator(),
loadDoc: (s) => EditorPage(doc: s.doc),
loadDoc: (s) => DocPage(doc: s.doc),
loadFail: (s) {
Log.error("$s");
return FlowyErrorPage(s.error.toString());
@ -53,7 +52,7 @@ class _DocPageState extends State<DocPage> {
}
@override
void didUpdateWidget(covariant DocPage oldWidget) {
void didUpdateWidget(covariant DocStackPage oldWidget) {
super.didUpdateWidget(oldWidget);
}
}

View File

@ -3,21 +3,23 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
import 'package:flutter/material.dart';
class AnnouncementStackView extends HomeStackView {
const AnnouncementStackView() : super(type: ViewType.Blank, title: 'Blank', identifier: "Announcement");
const AnnouncementStackView()
: super(type: ViewType.Blank, title: 'Blank', identifier: "Announcement");
@override
List<Object> get props => [];
}
class AnnouncementPage extends HomeStackWidget {
const AnnouncementPage({Key? key, required AnnouncementStackView stackView})
class AnnouncementStackPage extends HomeStackWidget {
const AnnouncementStackPage(
{Key? key, required AnnouncementStackView stackView})
: super(key: key, stackView: stackView);
@override
State<StatefulWidget> createState() => _AnnouncementPage();
}
class _AnnouncementPage extends State<AnnouncementPage> {
class _AnnouncementPage extends State<AnnouncementStackPage> {
@override
Widget build(BuildContext context) {
return SizedBox.expand(

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,68 +1 @@
{
"images" : [
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "app_icon_16.png",
"scale" : "1x"
},
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "app_icon_32.png",
"scale" : "2x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "app_icon_32.png",
"scale" : "1x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "app_icon_64.png",
"scale" : "2x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "app_icon_128.png",
"scale" : "1x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "app_icon_256.png",
"scale" : "2x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "app_icon_256.png",
"scale" : "1x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "app_icon_512.png",
"scale" : "2x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "app_icon_512.png",
"scale" : "1x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "app_icon_1024.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
{"images":[{"size":"128x128","expected-size":"128","filename":"128.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -19,7 +19,9 @@ class Block extends Container<Line?> {
/// Creates new unmounted [Block].
@override
Node newInstance() => Block();
Node newInstance() {
return Block();
}
@override
Delta toDelta() {

View File

@ -67,6 +67,7 @@ class EditorController extends ChangeNotifier {
void save() {
if (persistence != null) {
final a = document.toPlainText();
persistence!.save(document.toDelta().toJson());
}
}
@ -93,8 +94,9 @@ class EditorController extends ChangeNotifier {
toggledStyle = toggledStyle.put(attribute);
}
final change =
document.format(index, length, LinkAttribute("www.baidu.com"));
// final change =
// document.format(index, length, LinkAttribute("www.baidu.com"));
final change = document.format(index, length, attribute);
final adjustedSelection = selection.copyWith(
baseOffset: change.transformPosition(selection.baseOffset),
extentOffset: change.transformPosition(selection.extentOffset),

View File

@ -32,6 +32,13 @@ impl Document {
}
}
pub fn from_json(json: &str) -> Result<Self, OTError> {
let delta = Delta::from_json(json)?;
Ok(Self::from_delta(delta))
}
pub fn to_json(&self) -> String { self.delta.to_json() }
pub fn insert<T: DocumentData>(&mut self, index: usize, data: T) -> Result<Delta, OTError> {
let interval = Interval::new(index, index);
let _ = validate_interval(&self.delta, &interval)?;
@ -57,21 +64,14 @@ impl Document {
pub fn format(&mut self, interval: Interval, attribute: Attribute) -> Result<(), OTError> {
let _ = validate_interval(&self.delta, &interval)?;
log::debug!("format with {} at {}", attribute, interval);
let format_delta = self
.view
.format(&self.delta, attribute.clone(), interval)
.unwrap();
let format_delta = self.view.format(&self.delta, attribute.clone(), interval).unwrap();
log::debug!("👉 receive change: {}", format_delta);
self.add_delta(&format_delta)?;
Ok(())
}
pub fn replace<T: DocumentData>(
&mut self,
interval: Interval,
data: T,
) -> Result<Delta, OTError> {
pub fn replace<T: DocumentData>(&mut self, interval: Interval, data: T) -> Result<Delta, OTError> {
let _ = validate_interval(&self.delta, &interval)?;
let mut delta = Delta::default();
let text = data.into_string()?;
@ -95,9 +95,7 @@ impl Document {
pub fn undo(&mut self) -> Result<UndoResult, OTError> {
match self.history.undo() {
None => Err(ErrorBuilder::new(UndoFail)
.msg("Undo stack is empty")
.build()),
None => Err(ErrorBuilder::new(UndoFail).msg("Undo stack is empty").build()),
Some(undo_delta) => {
let (new_delta, inverted_delta) = self.invert_change(&undo_delta)?;
let result = UndoResult::success(new_delta.target_len as usize);
@ -123,8 +121,6 @@ impl Document {
}
}
pub fn to_json(&self) -> String { self.delta.to_json() }
pub fn to_string(&self) -> String { self.delta.apply("").unwrap() }
pub fn data(&self) -> &Delta { &self.delta }
@ -176,11 +172,7 @@ impl Document {
fn validate_interval(delta: &Delta, interval: &Interval) -> Result<(), OTError> {
if delta.target_len < interval.end {
log::error!(
"{:?} out of bounds. should 0..{}",
interval,
delta.target_len
);
log::error!("{:?} out of bounds. should 0..{}", interval, delta.target_len);
return Err(ErrorBuilder::new(OTErrorCode::IntervalOutOfBound).build());
}
Ok(())

View File

@ -1,5 +1,6 @@
mod data;
mod document;
mod selection;
pub use data::*;
pub use document::*;

View File

@ -66,6 +66,13 @@ impl FromIterator<Operation> for Delta {
impl Delta {
pub fn new() -> Self { Self::default() }
pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap_or("".to_owned()) }
pub fn from_json(json: &str) -> Result<Self, OTError> {
let delta: Delta = serde_json::from_str(json)?;
Ok(delta)
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
@ -136,8 +143,7 @@ impl Delta {
self.ops.push(new_op);
}
} else {
self.ops
.push(OpBuilder::retain(n).attributes(attrs).build());
self.ops.push(OpBuilder::retain(n).attributes(attrs).build());
}
}
@ -167,39 +173,21 @@ impl Delta {
other_iter.next_op_len().unwrap_or(MAX_IV_LEN),
);
let op = iter
.next_op_with_len(length)
.unwrap_or(OpBuilder::retain(length).build());
let op = iter.next_op_with_len(length).unwrap_or(OpBuilder::retain(length).build());
let other_op = other_iter
.next_op_with_len(length)
.unwrap_or(OpBuilder::retain(length).build());
let other_op = other_iter.next_op_with_len(length).unwrap_or(OpBuilder::retain(length).build());
debug_assert_eq!(op.len(), other_op.len());
match (&op, &other_op) {
(Operation::Retain(retain), Operation::Retain(other_retain)) => {
let composed_attrs = compose_attributes(
retain.attributes.clone(),
other_retain.attributes.clone(),
);
new_delta.add(
OpBuilder::retain(retain.n)
.attributes(composed_attrs)
.build(),
)
let composed_attrs = compose_attributes(retain.attributes.clone(), other_retain.attributes.clone());
new_delta.add(OpBuilder::retain(retain.n).attributes(composed_attrs).build())
},
(Operation::Insert(insert), Operation::Retain(other_retain)) => {
let mut composed_attrs = compose_attributes(
insert.attributes.clone(),
other_retain.attributes.clone(),
);
let mut composed_attrs = compose_attributes(insert.attributes.clone(), other_retain.attributes.clone());
composed_attrs.remove_empty();
new_delta.add(
OpBuilder::insert(op.get_data())
.attributes(composed_attrs)
.build(),
)
new_delta.add(OpBuilder::insert(op.get_data()).attributes(composed_attrs).build())
},
(Operation::Retain(_), Operation::Delete(_)) => {
new_delta.add(other_op);
@ -215,9 +203,7 @@ impl Delta {
Ok(new_delta)
}
#[deprecated(
note = "The same as compose except it requires the target_len of self must equal to other's base_len"
)]
#[deprecated(note = "The same as compose except it requires the target_len of self must equal to other's base_len")]
pub fn compose2(&self, other: &Self) -> Result<Self, OTError> {
if self.target_len != other.base_len {
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
@ -245,12 +231,7 @@ impl Delta {
},
(Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => {
let composed_attrs = compose_operation(&next_op1, &next_op2);
log::debug!(
"[retain:{} - retain:{}]: {:?}",
retain.n,
o_retain.n,
composed_attrs
);
log::debug!("[retain:{} - retain:{}]: {:?}", retain.n, o_retain.n, composed_attrs);
match retain.cmp(&o_retain) {
Ordering::Less => {
new_delta.retain(retain.n, composed_attrs);
@ -288,12 +269,7 @@ impl Delta {
next_op2 = ops2.next();
},
Ordering::Greater => {
next_op1 = Some(
OpBuilder::insert(
&insert.chars().skip(*o_num as usize).collect::<String>(),
)
.build(),
);
next_op1 = Some(OpBuilder::insert(&insert.chars().skip(*o_num as usize).collect::<String>()).build());
next_op2 = ops2.next();
},
}
@ -302,12 +278,7 @@ impl Delta {
let mut composed_attrs = compose_operation(&next_op1, &next_op2);
composed_attrs.remove_empty();
log::debug!(
"compose: [{} - {}], composed_attrs: {}",
insert,
o_retain,
composed_attrs
);
log::debug!("compose: [{} - {}], composed_attrs: {}", insert, o_retain, composed_attrs);
match (insert.num_chars()).cmp(o_retain) {
Ordering::Less => {
new_delta.insert(&insert.s, composed_attrs.clone());
@ -325,33 +296,28 @@ impl Delta {
},
Ordering::Greater => {
let chars = &mut insert.chars();
new_delta.insert(
&chars.take(o_retain.n as usize).collect::<String>(),
composed_attrs,
);
new_delta.insert(&chars.take(o_retain.n as usize).collect::<String>(), composed_attrs);
next_op1 = Some(OpBuilder::insert(&chars.collect::<String>()).build());
next_op2 = ops2.next();
},
}
},
(Some(Operation::Retain(retain)), Some(Operation::Delete(o_num))) => {
match retain.cmp(&o_num) {
Ordering::Less => {
new_delta.delete(retain.n);
next_op2 = Some(OpBuilder::delete(*o_num - retain.n).build());
next_op1 = ops1.next();
},
Ordering::Equal => {
new_delta.delete(*o_num);
next_op2 = ops2.next();
next_op1 = ops1.next();
},
Ordering::Greater => {
new_delta.delete(*o_num);
next_op1 = Some(OpBuilder::retain(retain.n - *o_num).build());
next_op2 = ops2.next();
},
}
(Some(Operation::Retain(retain)), Some(Operation::Delete(o_num))) => match retain.cmp(&o_num) {
Ordering::Less => {
new_delta.delete(retain.n);
next_op2 = Some(OpBuilder::delete(*o_num - retain.n).build());
next_op1 = ops1.next();
},
Ordering::Equal => {
new_delta.delete(*o_num);
next_op2 = ops2.next();
next_op1 = ops1.next();
},
Ordering::Greater => {
new_delta.delete(*o_num);
next_op1 = Some(OpBuilder::retain(retain.n - *o_num).build());
next_op2 = ops2.next();
},
},
};
}
@ -534,10 +500,7 @@ impl Delta {
inverted.delete(insert.num_chars());
},
Operation::Delete(delete) => {
inverted.insert(
&chars.take(*delete as usize).collect::<String>(),
op.get_attributes(),
);
inverted.insert(&chars.take(*delete as usize).collect::<String>(), op.get_attributes());
},
}
}
@ -564,12 +527,7 @@ impl Delta {
match op.has_attribute() {
true => invert_from_other(&mut inverted, other, op, index, index + len),
false => {
log::debug!(
"invert retain: {} by retain {} {}",
op,
len,
op.get_attributes()
);
log::debug!("invert retain: {} by retain {} {}", op, len, op.get_attributes());
inverted.retain(len as usize, op.get_attributes())
},
}
@ -598,18 +556,10 @@ impl Delta {
pub fn is_empty(&self) -> bool { self.ops.is_empty() }
pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap_or("".to_owned()) }
pub fn extend(&mut self, other: Self) { other.ops.into_iter().for_each(|op| self.add(op)); }
}
fn invert_from_other(
base: &mut Delta,
other: &Delta,
operation: &Operation,
start: usize,
end: usize,
) {
fn invert_from_other(base: &mut Delta, other: &Delta, operation: &Operation, start: usize, end: usize) {
log::debug!("invert op: {} [{}:{}]", operation, start, end);
let other_ops = DeltaIter::from_interval(other, Interval::new(start, end)).ops();
other_ops.into_iter().for_each(|other_op| match operation {
@ -623,15 +573,9 @@ fn invert_from_other(
operation.get_attributes(),
other_op.get_attributes()
);
let inverted_attrs =
invert_attributes(operation.get_attributes(), other_op.get_attributes());
let inverted_attrs = invert_attributes(operation.get_attributes(), other_op.get_attributes());
log::debug!("invert attributes result: {:?}", inverted_attrs);
log::debug!(
"invert retain: {} by retain len: {}, {}",
retain,
other_op.len(),
inverted_attrs
);
log::debug!("invert retain: {} by retain len: {}, {}", retain, other_op.len(), inverted_attrs);
base.retain(other_op.len(), inverted_attrs);
},
Operation::Insert(_) => {

View File

@ -1,4 +1,4 @@
use flowy_ot::core::*;
use flowy_ot::{client::Document, core::*};
#[test]
fn operation_insert_serialize_test() {
@ -42,6 +42,16 @@ fn delta_serialize_test() {
let json = serde_json::to_string(&delta).unwrap();
eprintln!("{}", json);
let delta_from_json: Delta = serde_json::from_str(&json).unwrap();
let delta_from_json = Delta::from_json(&json).unwrap();
assert_eq!(delta_from_json, delta);
}
#[test]
fn document_insert_serde_test() {
let mut document = Document::new();
document.insert(0, "\n");
document.insert(0, "123");
let json = document.to_json();
assert_eq!(r#"[{"insert":"123\n"}]"#, json);
assert_eq!(r#"[{"insert":"123\n"}]"#, Document::from_json(&json).unwrap().to_json());
}

View File

@ -95,6 +95,7 @@ impl TryInto<CreateViewParams> for CreateViewRequest {
desc: self.desc,
thumbnail,
view_type: self.view_type,
// TODO: replace the placeholder
data: "[{\"insert\":\"\\n\"}]".to_owned(),
})
}