[flutter]: delete view

This commit is contained in:
appflowy 2021-10-12 14:55:54 +08:00
parent 9898b8bd24
commit 50172e3fd4
16 changed files with 528 additions and 293 deletions

View File

@ -18,6 +18,7 @@ class AppListenBloc extends Bloc<AppListenEvent, AppListenState> {
yield* event.map(started: (_) async* {
listener.start(
addViewCallback: (viewsOrFail) => _handleViewsOrFail(viewsOrFail),
deleteViewCallback: (viewsOrFail) => _handleViewsOrFail(viewsOrFail),
);
}, didReceiveViews: (ViewsReceived value) async* {
yield value.viewsOrFail.fold(

View File

@ -1,4 +1,3 @@
import 'package:app_flowy/workspace/domain/view_edit.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
@ -10,49 +9,71 @@ part 'view_bloc.freezed.dart';
class ViewBloc extends Bloc<ViewEvent, ViewState> {
final IView iViewImpl;
final IViewListener listener;
ViewBloc({
required this.iViewImpl,
}) : super(ViewState.initial(iViewImpl.view));
required this.listener,
}) : super(ViewState.init(iViewImpl.view));
@override
Stream<ViewState> mapEventToState(ViewEvent event) async* {
yield* event.map(
setIsSelected: (e) async* {
yield state.copyWith(isSelected: e.isSelected);
},
setIsEditing: (e) async* {
yield state.copyWith(isEditing: e.isEditing);
},
setAction: (e) async* {
yield state.copyWith(action: e.action);
},
yield* event.map(initial: (e) async* {
listener.start(updatedCallback: (result) => add(ViewEvent.viewDidUpdate(result)));
yield state;
}, setIsEditing: (e) async* {
yield state.copyWith(isEditing: e.isEditing);
}, viewDidUpdate: (e) async* {
yield* _handleViewDidUpdate(e.result);
}, rename: (e) async* {
final result = await iViewImpl.rename(e.newName);
yield result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
);
}, delete: (e) async* {
final result = await iViewImpl.pushIntoTrash();
yield result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
);
});
}
Stream<ViewState> _handleViewDidUpdate(Either<View, WorkspaceError> result) async* {
yield result.fold(
(view) => state.copyWith(view: view, successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
);
}
@override
Future<void> close() async {
await listener.stop();
return super.close();
}
}
@freezed
class ViewEvent with _$ViewEvent {
const factory ViewEvent.setIsSelected(bool isSelected) = SetSelected;
const factory ViewEvent.initial() = Initial;
const factory ViewEvent.setIsEditing(bool isEditing) = SetEditing;
const factory ViewEvent.setAction(Option<ViewAction> action) = SetAction;
const factory ViewEvent.rename(String newName) = Rename;
const factory ViewEvent.delete() = Delete;
const factory ViewEvent.viewDidUpdate(Either<View, WorkspaceError> result) = ViewDidUpdate;
}
@freezed
class ViewState with _$ViewState {
const factory ViewState({
required View view,
required bool isSelected,
required bool isEditing,
required Option<ViewAction> action,
required Either<Unit, WorkspaceError> successOrFailure,
}) = _ViewState;
factory ViewState.initial(View view) => ViewState(
factory ViewState.init(View view) => ViewState(
view: view,
isSelected: false,
isEditing: false,
action: none(),
successOrFailure: left(unit),
);
}

View File

@ -16,10 +16,8 @@ final _privateConstructorUsedError = UnsupportedError(
class _$ViewEventTearOff {
const _$ViewEventTearOff();
SetSelected setIsSelected(bool isSelected) {
return SetSelected(
isSelected,
);
Initial initial() {
return const Initial();
}
SetEditing setIsEditing(bool isEditing) {
@ -28,9 +26,19 @@ class _$ViewEventTearOff {
);
}
SetAction setAction(Option<ViewAction> action) {
return SetAction(
action,
Rename rename(String newName) {
return Rename(
newName,
);
}
Delete delete() {
return const Delete();
}
ViewDidUpdate viewDidUpdate(Either<View, WorkspaceError> result) {
return ViewDidUpdate(
result,
);
}
}
@ -42,31 +50,40 @@ const $ViewEvent = _$ViewEventTearOff();
mixin _$ViewEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(bool isSelected) setIsSelected,
required TResult Function() initial,
required TResult Function(bool isEditing) setIsEditing,
required TResult Function(Option<ViewAction> action) setAction,
required TResult Function(String newName) rename,
required TResult Function() delete,
required TResult Function(Either<View, WorkspaceError> result)
viewDidUpdate,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(bool isSelected)? setIsSelected,
TResult Function()? initial,
TResult Function(bool isEditing)? setIsEditing,
TResult Function(Option<ViewAction> action)? setAction,
TResult Function(String newName)? rename,
TResult Function()? delete,
TResult Function(Either<View, WorkspaceError> result)? viewDidUpdate,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(SetSelected value) setIsSelected,
required TResult Function(Initial value) initial,
required TResult Function(SetEditing value) setIsEditing,
required TResult Function(SetAction value) setAction,
required TResult Function(Rename value) rename,
required TResult Function(Delete value) delete,
required TResult Function(ViewDidUpdate value) viewDidUpdate,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(SetSelected value)? setIsSelected,
TResult Function(Initial value)? initial,
TResult Function(SetEditing value)? setIsEditing,
TResult Function(SetAction value)? setAction,
TResult Function(Rename value)? rename,
TResult Function(Delete value)? delete,
TResult Function(ViewDidUpdate value)? viewDidUpdate,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@ -88,87 +105,64 @@ class _$ViewEventCopyWithImpl<$Res> implements $ViewEventCopyWith<$Res> {
}
/// @nodoc
abstract class $SetSelectedCopyWith<$Res> {
factory $SetSelectedCopyWith(
SetSelected value, $Res Function(SetSelected) then) =
_$SetSelectedCopyWithImpl<$Res>;
$Res call({bool isSelected});
abstract class $InitialCopyWith<$Res> {
factory $InitialCopyWith(Initial value, $Res Function(Initial) then) =
_$InitialCopyWithImpl<$Res>;
}
/// @nodoc
class _$SetSelectedCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res>
implements $SetSelectedCopyWith<$Res> {
_$SetSelectedCopyWithImpl(
SetSelected _value, $Res Function(SetSelected) _then)
: super(_value, (v) => _then(v as SetSelected));
class _$InitialCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res>
implements $InitialCopyWith<$Res> {
_$InitialCopyWithImpl(Initial _value, $Res Function(Initial) _then)
: super(_value, (v) => _then(v as Initial));
@override
SetSelected get _value => super._value as SetSelected;
@override
$Res call({
Object? isSelected = freezed,
}) {
return _then(SetSelected(
isSelected == freezed
? _value.isSelected
: isSelected // ignore: cast_nullable_to_non_nullable
as bool,
));
}
Initial get _value => super._value as Initial;
}
/// @nodoc
class _$SetSelected implements SetSelected {
const _$SetSelected(this.isSelected);
@override
final bool isSelected;
class _$Initial implements Initial {
const _$Initial();
@override
String toString() {
return 'ViewEvent.setIsSelected(isSelected: $isSelected)';
return 'ViewEvent.initial()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is SetSelected &&
(identical(other.isSelected, isSelected) ||
const DeepCollectionEquality()
.equals(other.isSelected, isSelected)));
return identical(this, other) || (other is Initial);
}
@override
int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(isSelected);
@JsonKey(ignore: true)
@override
$SetSelectedCopyWith<SetSelected> get copyWith =>
_$SetSelectedCopyWithImpl<SetSelected>(this, _$identity);
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(bool isSelected) setIsSelected,
required TResult Function() initial,
required TResult Function(bool isEditing) setIsEditing,
required TResult Function(Option<ViewAction> action) setAction,
required TResult Function(String newName) rename,
required TResult Function() delete,
required TResult Function(Either<View, WorkspaceError> result)
viewDidUpdate,
}) {
return setIsSelected(isSelected);
return initial();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(bool isSelected)? setIsSelected,
TResult Function()? initial,
TResult Function(bool isEditing)? setIsEditing,
TResult Function(Option<ViewAction> action)? setAction,
TResult Function(String newName)? rename,
TResult Function()? delete,
TResult Function(Either<View, WorkspaceError> result)? viewDidUpdate,
required TResult orElse(),
}) {
if (setIsSelected != null) {
return setIsSelected(isSelected);
if (initial != null) {
return initial();
}
return orElse();
}
@ -176,35 +170,34 @@ class _$SetSelected implements SetSelected {
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(SetSelected value) setIsSelected,
required TResult Function(Initial value) initial,
required TResult Function(SetEditing value) setIsEditing,
required TResult Function(SetAction value) setAction,
required TResult Function(Rename value) rename,
required TResult Function(Delete value) delete,
required TResult Function(ViewDidUpdate value) viewDidUpdate,
}) {
return setIsSelected(this);
return initial(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(SetSelected value)? setIsSelected,
TResult Function(Initial value)? initial,
TResult Function(SetEditing value)? setIsEditing,
TResult Function(SetAction value)? setAction,
TResult Function(Rename value)? rename,
TResult Function(Delete value)? delete,
TResult Function(ViewDidUpdate value)? viewDidUpdate,
required TResult orElse(),
}) {
if (setIsSelected != null) {
return setIsSelected(this);
if (initial != null) {
return initial(this);
}
return orElse();
}
}
abstract class SetSelected implements ViewEvent {
const factory SetSelected(bool isSelected) = _$SetSelected;
bool get isSelected => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$SetSelectedCopyWith<SetSelected> get copyWith =>
throw _privateConstructorUsedError;
abstract class Initial implements ViewEvent {
const factory Initial() = _$Initial;
}
/// @nodoc
@ -271,9 +264,12 @@ class _$SetEditing implements SetEditing {
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(bool isSelected) setIsSelected,
required TResult Function() initial,
required TResult Function(bool isEditing) setIsEditing,
required TResult Function(Option<ViewAction> action) setAction,
required TResult Function(String newName) rename,
required TResult Function() delete,
required TResult Function(Either<View, WorkspaceError> result)
viewDidUpdate,
}) {
return setIsEditing(isEditing);
}
@ -281,9 +277,11 @@ class _$SetEditing implements SetEditing {
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(bool isSelected)? setIsSelected,
TResult Function()? initial,
TResult Function(bool isEditing)? setIsEditing,
TResult Function(Option<ViewAction> action)? setAction,
TResult Function(String newName)? rename,
TResult Function()? delete,
TResult Function(Either<View, WorkspaceError> result)? viewDidUpdate,
required TResult orElse(),
}) {
if (setIsEditing != null) {
@ -295,9 +293,11 @@ class _$SetEditing implements SetEditing {
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(SetSelected value) setIsSelected,
required TResult Function(Initial value) initial,
required TResult Function(SetEditing value) setIsEditing,
required TResult Function(SetAction value) setAction,
required TResult Function(Rename value) rename,
required TResult Function(Delete value) delete,
required TResult Function(ViewDidUpdate value) viewDidUpdate,
}) {
return setIsEditing(this);
}
@ -305,9 +305,11 @@ class _$SetEditing implements SetEditing {
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(SetSelected value)? setIsSelected,
TResult Function(Initial value)? initial,
TResult Function(SetEditing value)? setIsEditing,
TResult Function(SetAction value)? setAction,
TResult Function(Rename value)? rename,
TResult Function(Delete value)? delete,
TResult Function(ViewDidUpdate value)? viewDidUpdate,
required TResult orElse(),
}) {
if (setIsEditing != null) {
@ -327,84 +329,89 @@ abstract class SetEditing implements ViewEvent {
}
/// @nodoc
abstract class $SetActionCopyWith<$Res> {
factory $SetActionCopyWith(SetAction value, $Res Function(SetAction) then) =
_$SetActionCopyWithImpl<$Res>;
$Res call({Option<ViewAction> action});
abstract class $RenameCopyWith<$Res> {
factory $RenameCopyWith(Rename value, $Res Function(Rename) then) =
_$RenameCopyWithImpl<$Res>;
$Res call({String newName});
}
/// @nodoc
class _$SetActionCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res>
implements $SetActionCopyWith<$Res> {
_$SetActionCopyWithImpl(SetAction _value, $Res Function(SetAction) _then)
: super(_value, (v) => _then(v as SetAction));
class _$RenameCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res>
implements $RenameCopyWith<$Res> {
_$RenameCopyWithImpl(Rename _value, $Res Function(Rename) _then)
: super(_value, (v) => _then(v as Rename));
@override
SetAction get _value => super._value as SetAction;
Rename get _value => super._value as Rename;
@override
$Res call({
Object? action = freezed,
Object? newName = freezed,
}) {
return _then(SetAction(
action == freezed
? _value.action
: action // ignore: cast_nullable_to_non_nullable
as Option<ViewAction>,
return _then(Rename(
newName == freezed
? _value.newName
: newName // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$SetAction implements SetAction {
const _$SetAction(this.action);
class _$Rename implements Rename {
const _$Rename(this.newName);
@override
final Option<ViewAction> action;
final String newName;
@override
String toString() {
return 'ViewEvent.setAction(action: $action)';
return 'ViewEvent.rename(newName: $newName)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is SetAction &&
(identical(other.action, action) ||
const DeepCollectionEquality().equals(other.action, action)));
(other is Rename &&
(identical(other.newName, newName) ||
const DeepCollectionEquality().equals(other.newName, newName)));
}
@override
int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(action);
runtimeType.hashCode ^ const DeepCollectionEquality().hash(newName);
@JsonKey(ignore: true)
@override
$SetActionCopyWith<SetAction> get copyWith =>
_$SetActionCopyWithImpl<SetAction>(this, _$identity);
$RenameCopyWith<Rename> get copyWith =>
_$RenameCopyWithImpl<Rename>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(bool isSelected) setIsSelected,
required TResult Function() initial,
required TResult Function(bool isEditing) setIsEditing,
required TResult Function(Option<ViewAction> action) setAction,
required TResult Function(String newName) rename,
required TResult Function() delete,
required TResult Function(Either<View, WorkspaceError> result)
viewDidUpdate,
}) {
return setAction(action);
return rename(newName);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(bool isSelected)? setIsSelected,
TResult Function()? initial,
TResult Function(bool isEditing)? setIsEditing,
TResult Function(Option<ViewAction> action)? setAction,
TResult Function(String newName)? rename,
TResult Function()? delete,
TResult Function(Either<View, WorkspaceError> result)? viewDidUpdate,
required TResult orElse(),
}) {
if (setAction != null) {
return setAction(action);
if (rename != null) {
return rename(newName);
}
return orElse();
}
@ -412,34 +419,262 @@ class _$SetAction implements SetAction {
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(SetSelected value) setIsSelected,
required TResult Function(Initial value) initial,
required TResult Function(SetEditing value) setIsEditing,
required TResult Function(SetAction value) setAction,
required TResult Function(Rename value) rename,
required TResult Function(Delete value) delete,
required TResult Function(ViewDidUpdate value) viewDidUpdate,
}) {
return setAction(this);
return rename(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(SetSelected value)? setIsSelected,
TResult Function(Initial value)? initial,
TResult Function(SetEditing value)? setIsEditing,
TResult Function(SetAction value)? setAction,
TResult Function(Rename value)? rename,
TResult Function(Delete value)? delete,
TResult Function(ViewDidUpdate value)? viewDidUpdate,
required TResult orElse(),
}) {
if (setAction != null) {
return setAction(this);
if (rename != null) {
return rename(this);
}
return orElse();
}
}
abstract class SetAction implements ViewEvent {
const factory SetAction(Option<ViewAction> action) = _$SetAction;
abstract class Rename implements ViewEvent {
const factory Rename(String newName) = _$Rename;
Option<ViewAction> get action => throw _privateConstructorUsedError;
String get newName => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$SetActionCopyWith<SetAction> get copyWith =>
$RenameCopyWith<Rename> get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $DeleteCopyWith<$Res> {
factory $DeleteCopyWith(Delete value, $Res Function(Delete) then) =
_$DeleteCopyWithImpl<$Res>;
}
/// @nodoc
class _$DeleteCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res>
implements $DeleteCopyWith<$Res> {
_$DeleteCopyWithImpl(Delete _value, $Res Function(Delete) _then)
: super(_value, (v) => _then(v as Delete));
@override
Delete get _value => super._value as Delete;
}
/// @nodoc
class _$Delete implements Delete {
const _$Delete();
@override
String toString() {
return 'ViewEvent.delete()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is Delete);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function(bool isEditing) setIsEditing,
required TResult Function(String newName) rename,
required TResult Function() delete,
required TResult Function(Either<View, WorkspaceError> result)
viewDidUpdate,
}) {
return delete();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function(bool isEditing)? setIsEditing,
TResult Function(String newName)? rename,
TResult Function()? delete,
TResult Function(Either<View, WorkspaceError> result)? viewDidUpdate,
required TResult orElse(),
}) {
if (delete != null) {
return delete();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Initial value) initial,
required TResult Function(SetEditing value) setIsEditing,
required TResult Function(Rename value) rename,
required TResult Function(Delete value) delete,
required TResult Function(ViewDidUpdate value) viewDidUpdate,
}) {
return delete(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Initial value)? initial,
TResult Function(SetEditing value)? setIsEditing,
TResult Function(Rename value)? rename,
TResult Function(Delete value)? delete,
TResult Function(ViewDidUpdate value)? viewDidUpdate,
required TResult orElse(),
}) {
if (delete != null) {
return delete(this);
}
return orElse();
}
}
abstract class Delete implements ViewEvent {
const factory Delete() = _$Delete;
}
/// @nodoc
abstract class $ViewDidUpdateCopyWith<$Res> {
factory $ViewDidUpdateCopyWith(
ViewDidUpdate value, $Res Function(ViewDidUpdate) then) =
_$ViewDidUpdateCopyWithImpl<$Res>;
$Res call({Either<View, WorkspaceError> result});
}
/// @nodoc
class _$ViewDidUpdateCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res>
implements $ViewDidUpdateCopyWith<$Res> {
_$ViewDidUpdateCopyWithImpl(
ViewDidUpdate _value, $Res Function(ViewDidUpdate) _then)
: super(_value, (v) => _then(v as ViewDidUpdate));
@override
ViewDidUpdate get _value => super._value as ViewDidUpdate;
@override
$Res call({
Object? result = freezed,
}) {
return _then(ViewDidUpdate(
result == freezed
? _value.result
: result // ignore: cast_nullable_to_non_nullable
as Either<View, WorkspaceError>,
));
}
}
/// @nodoc
class _$ViewDidUpdate implements ViewDidUpdate {
const _$ViewDidUpdate(this.result);
@override
final Either<View, WorkspaceError> result;
@override
String toString() {
return 'ViewEvent.viewDidUpdate(result: $result)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other is ViewDidUpdate &&
(identical(other.result, result) ||
const DeepCollectionEquality().equals(other.result, result)));
}
@override
int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(result);
@JsonKey(ignore: true)
@override
$ViewDidUpdateCopyWith<ViewDidUpdate> get copyWith =>
_$ViewDidUpdateCopyWithImpl<ViewDidUpdate>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function(bool isEditing) setIsEditing,
required TResult Function(String newName) rename,
required TResult Function() delete,
required TResult Function(Either<View, WorkspaceError> result)
viewDidUpdate,
}) {
return viewDidUpdate(result);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function(bool isEditing)? setIsEditing,
TResult Function(String newName)? rename,
TResult Function()? delete,
TResult Function(Either<View, WorkspaceError> result)? viewDidUpdate,
required TResult orElse(),
}) {
if (viewDidUpdate != null) {
return viewDidUpdate(result);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Initial value) initial,
required TResult Function(SetEditing value) setIsEditing,
required TResult Function(Rename value) rename,
required TResult Function(Delete value) delete,
required TResult Function(ViewDidUpdate value) viewDidUpdate,
}) {
return viewDidUpdate(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Initial value)? initial,
TResult Function(SetEditing value)? setIsEditing,
TResult Function(Rename value)? rename,
TResult Function(Delete value)? delete,
TResult Function(ViewDidUpdate value)? viewDidUpdate,
required TResult orElse(),
}) {
if (viewDidUpdate != null) {
return viewDidUpdate(this);
}
return orElse();
}
}
abstract class ViewDidUpdate implements ViewEvent {
const factory ViewDidUpdate(Either<View, WorkspaceError> result) =
_$ViewDidUpdate;
Either<View, WorkspaceError> get result => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ViewDidUpdateCopyWith<ViewDidUpdate> get copyWith =>
throw _privateConstructorUsedError;
}
@ -449,15 +684,11 @@ class _$ViewStateTearOff {
_ViewState call(
{required View view,
required bool isSelected,
required bool isEditing,
required Option<ViewAction> action,
required Either<Unit, WorkspaceError> successOrFailure}) {
return _ViewState(
view: view,
isSelected: isSelected,
isEditing: isEditing,
action: action,
successOrFailure: successOrFailure,
);
}
@ -469,9 +700,7 @@ const $ViewState = _$ViewStateTearOff();
/// @nodoc
mixin _$ViewState {
View get view => throw _privateConstructorUsedError;
bool get isSelected => throw _privateConstructorUsedError;
bool get isEditing => throw _privateConstructorUsedError;
Option<ViewAction> get action => throw _privateConstructorUsedError;
Either<Unit, WorkspaceError> get successOrFailure =>
throw _privateConstructorUsedError;
@ -486,9 +715,7 @@ abstract class $ViewStateCopyWith<$Res> {
_$ViewStateCopyWithImpl<$Res>;
$Res call(
{View view,
bool isSelected,
bool isEditing,
Option<ViewAction> action,
Either<Unit, WorkspaceError> successOrFailure});
}
@ -503,9 +730,7 @@ class _$ViewStateCopyWithImpl<$Res> implements $ViewStateCopyWith<$Res> {
@override
$Res call({
Object? view = freezed,
Object? isSelected = freezed,
Object? isEditing = freezed,
Object? action = freezed,
Object? successOrFailure = freezed,
}) {
return _then(_value.copyWith(
@ -513,18 +738,10 @@ class _$ViewStateCopyWithImpl<$Res> implements $ViewStateCopyWith<$Res> {
? _value.view
: view // ignore: cast_nullable_to_non_nullable
as View,
isSelected: isSelected == freezed
? _value.isSelected
: isSelected // ignore: cast_nullable_to_non_nullable
as bool,
isEditing: isEditing == freezed
? _value.isEditing
: isEditing // ignore: cast_nullable_to_non_nullable
as bool,
action: action == freezed
? _value.action
: action // ignore: cast_nullable_to_non_nullable
as Option<ViewAction>,
successOrFailure: successOrFailure == freezed
? _value.successOrFailure
: successOrFailure // ignore: cast_nullable_to_non_nullable
@ -541,9 +758,7 @@ abstract class _$ViewStateCopyWith<$Res> implements $ViewStateCopyWith<$Res> {
@override
$Res call(
{View view,
bool isSelected,
bool isEditing,
Option<ViewAction> action,
Either<Unit, WorkspaceError> successOrFailure});
}
@ -559,9 +774,7 @@ class __$ViewStateCopyWithImpl<$Res> extends _$ViewStateCopyWithImpl<$Res>
@override
$Res call({
Object? view = freezed,
Object? isSelected = freezed,
Object? isEditing = freezed,
Object? action = freezed,
Object? successOrFailure = freezed,
}) {
return _then(_ViewState(
@ -569,18 +782,10 @@ class __$ViewStateCopyWithImpl<$Res> extends _$ViewStateCopyWithImpl<$Res>
? _value.view
: view // ignore: cast_nullable_to_non_nullable
as View,
isSelected: isSelected == freezed
? _value.isSelected
: isSelected // ignore: cast_nullable_to_non_nullable
as bool,
isEditing: isEditing == freezed
? _value.isEditing
: isEditing // ignore: cast_nullable_to_non_nullable
as bool,
action: action == freezed
? _value.action
: action // ignore: cast_nullable_to_non_nullable
as Option<ViewAction>,
successOrFailure: successOrFailure == freezed
? _value.successOrFailure
: successOrFailure // ignore: cast_nullable_to_non_nullable
@ -594,25 +799,19 @@ class __$ViewStateCopyWithImpl<$Res> extends _$ViewStateCopyWithImpl<$Res>
class _$_ViewState implements _ViewState {
const _$_ViewState(
{required this.view,
required this.isSelected,
required this.isEditing,
required this.action,
required this.successOrFailure});
@override
final View view;
@override
final bool isSelected;
@override
final bool isEditing;
@override
final Option<ViewAction> action;
@override
final Either<Unit, WorkspaceError> successOrFailure;
@override
String toString() {
return 'ViewState(view: $view, isSelected: $isSelected, isEditing: $isEditing, action: $action, successOrFailure: $successOrFailure)';
return 'ViewState(view: $view, isEditing: $isEditing, successOrFailure: $successOrFailure)';
}
@override
@ -621,14 +820,9 @@ class _$_ViewState implements _ViewState {
(other is _ViewState &&
(identical(other.view, view) ||
const DeepCollectionEquality().equals(other.view, view)) &&
(identical(other.isSelected, isSelected) ||
const DeepCollectionEquality()
.equals(other.isSelected, isSelected)) &&
(identical(other.isEditing, isEditing) ||
const DeepCollectionEquality()
.equals(other.isEditing, isEditing)) &&
(identical(other.action, action) ||
const DeepCollectionEquality().equals(other.action, action)) &&
(identical(other.successOrFailure, successOrFailure) ||
const DeepCollectionEquality()
.equals(other.successOrFailure, successOrFailure)));
@ -638,9 +832,7 @@ class _$_ViewState implements _ViewState {
int get hashCode =>
runtimeType.hashCode ^
const DeepCollectionEquality().hash(view) ^
const DeepCollectionEquality().hash(isSelected) ^
const DeepCollectionEquality().hash(isEditing) ^
const DeepCollectionEquality().hash(action) ^
const DeepCollectionEquality().hash(successOrFailure);
@JsonKey(ignore: true)
@ -652,20 +844,14 @@ class _$_ViewState implements _ViewState {
abstract class _ViewState implements ViewState {
const factory _ViewState(
{required View view,
required bool isSelected,
required bool isEditing,
required Option<ViewAction> action,
required Either<Unit, WorkspaceError> successOrFailure}) = _$_ViewState;
@override
View get view => throw _privateConstructorUsedError;
@override
bool get isSelected => throw _privateConstructorUsedError;
@override
bool get isEditing => throw _privateConstructorUsedError;
@override
Option<ViewAction> get action => throw _privateConstructorUsedError;
@override
Either<Unit, WorkspaceError> get successOrFailure =>
throw _privateConstructorUsedError;
@override

View File

@ -13,7 +13,10 @@ abstract class IApp {
}
abstract class IAppListenr {
void start({AppCreateViewCallback? addViewCallback, AppUpdatedCallback? updatedCallback});
void start(
{AppCreateViewCallback? addViewCallback,
AppDeleteViewCallback? deleteViewCallback,
AppUpdatedCallback? updatedCallback});
Future<void> stop();
}

View File

@ -9,7 +9,7 @@ abstract class IView {
Future<Either<Unit, WorkspaceError>> pushIntoTrash();
Future<Either<Unit, WorkspaceError>> rename(String newName);
Future<Either<View, WorkspaceError>> rename(String newName);
}
abstract class IViewListener {

View File

@ -67,7 +67,12 @@ class HomeDepsResolver {
getIt.registerFactoryParam<AppListenBloc, String, void>(
(appId, _) => AppListenBloc(getIt<IAppListenr>(param1: appId)));
getIt.registerFactoryParam<ViewBloc, View, void>((view, _) => ViewBloc(iViewImpl: getIt<IView>(param1: view)));
getIt.registerFactoryParam<ViewBloc, View, void>(
(view, _) => ViewBloc(
iViewImpl: getIt<IView>(param1: view),
listener: getIt<IViewListener>(param1: view),
),
);
getIt.registerFactoryParam<DocBloc, String, void>((docId, _) => DocBloc(iDocImpl: getIt<IDoc>(param1: docId)));

View File

@ -34,13 +34,16 @@ class IAppListenerhImpl extends IAppListenr {
required this.repo,
});
@override
void start({AppCreateViewCallback? addViewCallback, AppUpdatedCallback? updatedCallback}) {
repo.startListen(createView: addViewCallback, update: updatedCallback);
}
@override
Future<void> stop() async {
await repo.close();
}
@override
void start(
{AppCreateViewCallback? addViewCallback,
AppDeleteViewCallback? deleteViewCallback,
AppUpdatedCallback? updatedCallback}) {
repo.startListen(createView: addViewCallback, deleteView: deleteViewCallback, update: updatedCallback);
}
}

View File

@ -14,11 +14,16 @@ class IViewImpl extends IView {
@override
Future<Either<Unit, WorkspaceError>> pushIntoTrash() {
return repo.updateView(isTrash: true);
return repo.updateView(isTrash: true).then((result) {
return result.fold(
(_) => left(unit),
(error) => right(error),
);
});
}
@override
Future<Either<Unit, WorkspaceError>> rename(String newName) {
Future<Either<View, WorkspaceError>> rename(String newName) {
return repo.updateView(name: newName);
}
}

View File

@ -34,12 +34,10 @@ import 'package:dartz/dartz.dart';
// }
// }
typedef UserObservableCallback = void Function(
UserObservable, Either<Uint8List, UserError>);
typedef UserObservableCallback = void Function(UserObservable, Either<Uint8List, UserError>);
class UserObservableParser extends ObservableParser<UserObservable, UserError> {
UserObservableParser(
{required String id, required UserObservableCallback callback})
UserObservableParser({required String id, required UserObservableCallback callback})
: super(
id: id,
callback: callback,
@ -48,13 +46,10 @@ class UserObservableParser extends ObservableParser<UserObservable, UserError> {
);
}
typedef WorkspaceObservableCallback = void Function(
WorkspaceObservable, Either<Uint8List, WorkspaceError>);
typedef WorkspaceObservableCallback = void Function(WorkspaceObservable, Either<Uint8List, WorkspaceError>);
class WorkspaceObservableParser
extends ObservableParser<WorkspaceObservable, WorkspaceError> {
WorkspaceObservableParser(
{required String id, required WorkspaceObservableCallback callback})
class WorkspaceObservableParser extends ObservableParser<WorkspaceObservable, WorkspaceError> {
WorkspaceObservableParser({required String id, required WorkspaceObservableCallback callback})
: super(
id: id,
callback: callback,
@ -70,11 +65,7 @@ class ObservableParser<T, E> {
T? Function(int) tyParser;
E Function(Uint8List) errorParser;
ObservableParser(
{required this.id,
required this.callback,
required this.errorParser,
required this.tyParser});
ObservableParser({required this.id, required this.callback, required this.errorParser, required this.tyParser});
void parse(ObservableSubject subject) {
if (subject.id != id) {
return;

View File

@ -26,7 +26,7 @@ class ViewRepository {
return WorkspaceEventReadView(request).send();
}
Future<Either<Unit, WorkspaceError>> updateView({String? name, String? desc, bool? isTrash}) {
Future<Either<View, WorkspaceError>> updateView({String? name, String? desc, bool? isTrash}) {
final request = UpdateViewRequest.create()..viewId = view.id;
if (name != null) {

View File

@ -9,7 +9,6 @@ import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -22,50 +21,43 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/menu_ap
// ignore: must_be_immutable
class ViewSectionItem extends StatelessWidget {
final ViewBloc bloc;
final bool isSelected;
final View view;
final void Function(View) onSelected;
ViewSectionItem({
Key? key,
required View view,
required bool isSelected,
required this.view,
required this.isSelected,
required this.onSelected,
}) : bloc = getIt<ViewBloc>(param1: view),
super(key: ValueKey(view.id)) {
bloc.add(ViewEvent.setIsSelected(isSelected));
}
}) : super(key: ValueKey('$view.id/$isSelected'));
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return BlocProvider.value(
value: bloc,
child: BlocListener<ViewBloc, ViewState>(
listenWhen: (p, c) => p.action != c.action,
listener: (context, state) {
state.action.fold(() => null, (action) {
Log.info('$action');
});
return MultiBlocProvider(
providers: [
BlocProvider(create: (ctx) => getIt<ViewBloc>(param1: view)..add(const ViewEvent.initial())),
],
child: BlocBuilder<ViewBloc, ViewState>(
builder: (context, state) {
return InkWell(
onTap: () {
onSelected(context.read<ViewBloc>().state.view);
getIt<HomeStackManager>().setStack(state.view.intoStackContext());
},
child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.bg3),
builder: (context, onHover) => _render(context, onHover, state),
isOnSelected: () => state.isEditing || isSelected,
),
);
},
child: BlocBuilder<ViewBloc, ViewState>(
builder: (context, state) {
return InkWell(
onTap: () => onSelected(context.read<ViewBloc>().state.view),
child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.bg3),
builder: (context, onHover) => _render(context, onHover),
isOnSelected: () => state.isEditing || state.isSelected,
),
);
},
),
),
);
}
Widget _render(BuildContext context, bool onHover) {
final state = context.read<ViewBloc>().state;
Widget _render(BuildContext context, bool onHover, ViewState state) {
List<Widget> children = [
SizedBox(width: 16, height: 16, child: state.view.thumbnail()),
const HSpace(6),
@ -75,13 +67,10 @@ class ViewSectionItem extends StatelessWidget {
if (onHover || state.isEditing) {
children.add(const Spacer());
children.add(ViewDisclosureButton(
onTap: () {
context.read<ViewBloc>().add(const ViewEvent.setIsEditing(true));
getIt<HomeStackManager>().setStack(state.view.intoStackContext());
},
onTap: () => context.read<ViewBloc>().add(const ViewEvent.setIsEditing(true)),
onSelected: (action) {
context.read<ViewBloc>().add(const ViewEvent.setIsEditing(false));
context.read<ViewBloc>().add(ViewEvent.setAction(action));
_handleAction(context, action);
},
));
}
@ -94,6 +83,20 @@ class ViewSectionItem extends StatelessWidget {
),
);
}
void _handleAction(BuildContext context, dartz.Option<ViewAction> action) {
action.foldRight({}, (action, previous) {
switch (action) {
case ViewAction.rename:
// TODO: Handle this case.
break;
case ViewAction.delete:
context.read<ViewBloc>().add(const ViewEvent.delete());
break;
}
});
}
}
// [[Widget: LifeCycle]]

View File

@ -207,14 +207,14 @@ class WorkspaceEventUpdateView {
UpdateViewRequest request;
WorkspaceEventUpdateView(this.request);
Future<Either<Unit, WorkspaceError>> send() {
Future<Either<View, WorkspaceError>> send() {
final request = FFIRequest.create()
..event = WorkspaceEvent.UpdateView.toString()
..payload = requestToBytes(this.request);
return Dispatch.asyncRequest(request)
.then((bytesResult) => bytesResult.fold(
(bytes) => left(unit),
(okBytes) => left(View.fromBuffer(okBytes)),
(errBytes) => right(WorkspaceError.fromBuffer(errBytes)),
));
}

View File

@ -72,7 +72,6 @@ impl DartNotifyBuilder {
error,
};
log::debug!("Notify {}", subject);
match DartStreamSender::post(subject) {
Ok(_) => {},
Err(error) => log::error!("Send observable subject failed: {}", error),

View File

@ -40,7 +40,7 @@ pub enum WorkspaceEvent {
#[event(input = "QueryViewRequest", output = "View")]
ReadView = 202,
#[event(input = "UpdateViewRequest")]
#[event(input = "UpdateViewRequest", output = "View")]
UpdateView = 203,
#[event(input = "DeleteViewRequest")]

View File

@ -58,7 +58,7 @@ impl ViewController {
let _ = self.save_view(view.clone(), conn)?;
self.document.create(CreateDocParams::new(&view.id, params.data))?;
let repeated_view = self.read_local_views_belong_to(&view.belong_to_id, conn)?;
let repeated_view = self.sql.read_views_belong_to(&view.belong_to_id, Some(false), conn)?;
dart_notify(&view.belong_to_id, WorkspaceObservable::AppCreateView)
.payload(repeated_view)
.send();
@ -96,7 +96,10 @@ impl ViewController {
let view_table = self.sql.delete_view(&params.view_id, conn)?;
let _ = self.document.delete(params.into())?;
let repeated_view = self.read_local_views_belong_to(&view_table.belong_to_id, conn)?;
let repeated_view = self
.sql
.read_views_belong_to(&view_table.belong_to_id, Some(false), conn)?;
dart_notify(&view_table.belong_to_id, WorkspaceObservable::AppDeleteView)
.payload(repeated_view)
.send();
@ -111,26 +114,45 @@ impl ViewController {
pub(crate) async fn read_views_belong_to(&self, belong_to_id: &str) -> Result<RepeatedView, WorkspaceError> {
// TODO: read from server
let conn = self.database.db_connection()?;
let repeated_view = self.read_local_views_belong_to(belong_to_id, &*conn)?;
let repeated_view = self.sql.read_views_belong_to(belong_to_id, Some(false), &*conn)?;
Ok(repeated_view)
}
pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result<(), WorkspaceError> {
#[tracing::instrument(level = "debug", skip(self, params), fields(dart_notify) err)]
pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result<View, WorkspaceError> {
let conn = &*self.database.db_connection()?;
let changeset = ViewTableChangeset::new(params.clone());
let view_id = changeset.id.clone();
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let updated_view = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = self.sql.update_view(changeset, conn)?;
let view: View = self.sql.read_view(&view_id, None, conn)?.into();
dart_notify(&view_id, WorkspaceObservable::ViewUpdated)
.payload(view)
.send();
Ok(())
if params.is_trash.is_some() {
let repeated_view = self.sql.read_views_belong_to(&view.belong_to_id, Some(false), conn)?;
tracing::Span::current().record(
"dart_notify",
&format!("{:?}: {}", WorkspaceObservable::AppDeleteView, &view.belong_to_id).as_str(),
);
dart_notify(&view.belong_to_id, WorkspaceObservable::AppDeleteView)
.payload(repeated_view)
.send();
} else {
tracing::Span::current().record(
"dart_notify",
&format!("{:?}: {}", WorkspaceObservable::ViewUpdated, &view_id).as_str(),
);
dart_notify(&view_id, WorkspaceObservable::ViewUpdated)
.payload(view.clone())
.send();
}
Ok(view)
})?;
let _ = self.update_view_on_server(params);
Ok(())
Ok(updated_view)
}
pub(crate) async fn apply_doc_delta(&self, params: DocDelta) -> Result<DocDelta, WorkspaceError> {
@ -197,20 +219,4 @@ impl ViewController {
});
Ok(())
}
// belong_to_id will be the app_id or view_id.
fn read_local_views_belong_to(
&self,
belong_to_id: &str,
conn: &SqliteConnection,
) -> Result<RepeatedView, WorkspaceError> {
let views = self
.sql
.read_views_belong_to(belong_to_id, conn)?
.into_iter()
.map(|view_table| view_table.into())
.collect::<Vec<View>>();
Ok(RepeatedView { items: views })
}
}

View File

@ -1,4 +1,5 @@
use crate::{
entities::view::{RepeatedView, View},
errors::WorkspaceError,
sql_tables::view::{ViewTable, ViewTableChangeset},
};
@ -37,16 +38,27 @@ impl ViewTableSql {
Ok(view_table)
}
// belong_to_id will be the app_id or view_id.
pub(crate) fn read_views_belong_to(
&self,
belong_to_id: &str,
is_trash: Option<bool>,
conn: &SqliteConnection,
) -> Result<Vec<ViewTable>, WorkspaceError> {
let view_tables = dsl::view_table
) -> Result<RepeatedView, WorkspaceError> {
let mut filter = dsl::view_table
.filter(view_table::belong_to_id.eq(belong_to_id))
.load::<ViewTable>(conn)?;
.into_boxed();
if let Some(is_trash) = is_trash {
filter = filter.filter(view_table::is_trash.eq(is_trash));
}
let view_tables = filter.load::<ViewTable>(conn)?;
Ok(view_tables)
let views = view_tables
.into_iter()
.map(|view_table| view_table.into())
.collect::<Vec<View>>();
Ok(RepeatedView { items: views })
}
pub(crate) fn update_view(