[flutter]: restore the doc page from banner

This commit is contained in:
appflowy 2021-10-31 19:48:20 +08:00
parent 0606cd4ce9
commit ddfe985065
5 changed files with 346 additions and 14 deletions

View File

@ -1,6 +1,8 @@
import 'dart:convert';
import 'package:app_flowy/workspace/domain/i_trash.dart';
import 'package:app_flowy/workspace/domain/i_view.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
@ -12,12 +14,19 @@ import 'dart:async';
part 'doc_bloc.freezed.dart';
class DocBloc extends Bloc<DocEvent, DocState> {
final View view;
final IDoc docManager;
final IViewListener listener;
final ITrash trasnManager;
late Document document;
late StreamSubscription _subscription;
DocBloc({required this.docManager, required this.listener}) : super(DocState.initial());
DocBloc({
required this.view,
required this.docManager,
required this.listener,
required this.trasnManager,
}) : super(DocState.initial());
@override
Stream<DocState> mapEventToState(DocEvent event) async* {
@ -29,6 +38,17 @@ class DocBloc extends Bloc<DocEvent, DocState> {
restore: (Restore value) async* {
yield state.copyWith(isDeleted: false);
},
deletePermanently: (DeletePermanently value) async* {
// final result = await trasnManager.deleteViews([e.trash]);
// yield* _handleResult(result);
yield state;
},
restorePage: (RestorePage value) async* {
final result = await trasnManager.putback(view.id);
yield result.fold((l) => state.copyWith(isDeleted: false), (r) {
return state;
});
},
);
}
@ -107,6 +127,8 @@ class DocEvent with _$DocEvent {
const factory DocEvent.initial() = Initial;
const factory DocEvent.deleted() = Deleted;
const factory DocEvent.restore() = Restore;
const factory DocEvent.restorePage() = RestorePage;
const factory DocEvent.deletePermanently() = DeletePermanently;
}
@freezed

View File

@ -27,6 +27,14 @@ class _$DocEventTearOff {
Restore restore() {
return const Restore();
}
RestorePage restorePage() {
return const RestorePage();
}
DeletePermanently deletePermanently() {
return const DeletePermanently();
}
}
/// @nodoc
@ -39,6 +47,8 @@ mixin _$DocEvent {
required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
required TResult Function() restorePage,
required TResult Function() deletePermanently,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
@ -46,6 +56,8 @@ mixin _$DocEvent {
TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
TResult Function()? restorePage,
TResult Function()? deletePermanently,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@ -54,6 +66,8 @@ mixin _$DocEvent {
required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
required TResult Function(RestorePage value) restorePage,
required TResult Function(DeletePermanently value) deletePermanently,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
@ -61,6 +75,8 @@ mixin _$DocEvent {
TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
TResult Function(RestorePage value)? restorePage,
TResult Function(DeletePermanently value)? deletePermanently,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@ -121,6 +137,8 @@ class _$Initial implements Initial {
required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
required TResult Function() restorePage,
required TResult Function() deletePermanently,
}) {
return initial();
}
@ -131,6 +149,8 @@ class _$Initial implements Initial {
TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
TResult Function()? restorePage,
TResult Function()? deletePermanently,
required TResult orElse(),
}) {
if (initial != null) {
@ -145,6 +165,8 @@ class _$Initial implements Initial {
required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
required TResult Function(RestorePage value) restorePage,
required TResult Function(DeletePermanently value) deletePermanently,
}) {
return initial(this);
}
@ -155,6 +177,8 @@ class _$Initial implements Initial {
TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
TResult Function(RestorePage value)? restorePage,
TResult Function(DeletePermanently value)? deletePermanently,
required TResult orElse(),
}) {
if (initial != null) {
@ -208,6 +232,8 @@ class _$Deleted implements Deleted {
required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
required TResult Function() restorePage,
required TResult Function() deletePermanently,
}) {
return deleted();
}
@ -218,6 +244,8 @@ class _$Deleted implements Deleted {
TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
TResult Function()? restorePage,
TResult Function()? deletePermanently,
required TResult orElse(),
}) {
if (deleted != null) {
@ -232,6 +260,8 @@ class _$Deleted implements Deleted {
required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
required TResult Function(RestorePage value) restorePage,
required TResult Function(DeletePermanently value) deletePermanently,
}) {
return deleted(this);
}
@ -242,6 +272,8 @@ class _$Deleted implements Deleted {
TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
TResult Function(RestorePage value)? restorePage,
TResult Function(DeletePermanently value)? deletePermanently,
required TResult orElse(),
}) {
if (deleted != null) {
@ -295,6 +327,8 @@ class _$Restore implements Restore {
required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
required TResult Function() restorePage,
required TResult Function() deletePermanently,
}) {
return restore();
}
@ -305,6 +339,8 @@ class _$Restore implements Restore {
TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
TResult Function()? restorePage,
TResult Function()? deletePermanently,
required TResult orElse(),
}) {
if (restore != null) {
@ -319,6 +355,8 @@ class _$Restore implements Restore {
required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
required TResult Function(RestorePage value) restorePage,
required TResult Function(DeletePermanently value) deletePermanently,
}) {
return restore(this);
}
@ -329,6 +367,8 @@ class _$Restore implements Restore {
TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
TResult Function(RestorePage value)? restorePage,
TResult Function(DeletePermanently value)? deletePermanently,
required TResult orElse(),
}) {
if (restore != null) {
@ -342,6 +382,200 @@ abstract class Restore implements DocEvent {
const factory Restore() = _$Restore;
}
/// @nodoc
abstract class $RestorePageCopyWith<$Res> {
factory $RestorePageCopyWith(
RestorePage value, $Res Function(RestorePage) then) =
_$RestorePageCopyWithImpl<$Res>;
}
/// @nodoc
class _$RestorePageCopyWithImpl<$Res> extends _$DocEventCopyWithImpl<$Res>
implements $RestorePageCopyWith<$Res> {
_$RestorePageCopyWithImpl(
RestorePage _value, $Res Function(RestorePage) _then)
: super(_value, (v) => _then(v as RestorePage));
@override
RestorePage get _value => super._value as RestorePage;
}
/// @nodoc
class _$RestorePage implements RestorePage {
const _$RestorePage();
@override
String toString() {
return 'DocEvent.restorePage()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is RestorePage);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
required TResult Function() restorePage,
required TResult Function() deletePermanently,
}) {
return restorePage();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
TResult Function()? restorePage,
TResult Function()? deletePermanently,
required TResult orElse(),
}) {
if (restorePage != null) {
return restorePage();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
required TResult Function(RestorePage value) restorePage,
required TResult Function(DeletePermanently value) deletePermanently,
}) {
return restorePage(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
TResult Function(RestorePage value)? restorePage,
TResult Function(DeletePermanently value)? deletePermanently,
required TResult orElse(),
}) {
if (restorePage != null) {
return restorePage(this);
}
return orElse();
}
}
abstract class RestorePage implements DocEvent {
const factory RestorePage() = _$RestorePage;
}
/// @nodoc
abstract class $DeletePermanentlyCopyWith<$Res> {
factory $DeletePermanentlyCopyWith(
DeletePermanently value, $Res Function(DeletePermanently) then) =
_$DeletePermanentlyCopyWithImpl<$Res>;
}
/// @nodoc
class _$DeletePermanentlyCopyWithImpl<$Res> extends _$DocEventCopyWithImpl<$Res>
implements $DeletePermanentlyCopyWith<$Res> {
_$DeletePermanentlyCopyWithImpl(
DeletePermanently _value, $Res Function(DeletePermanently) _then)
: super(_value, (v) => _then(v as DeletePermanently));
@override
DeletePermanently get _value => super._value as DeletePermanently;
}
/// @nodoc
class _$DeletePermanently implements DeletePermanently {
const _$DeletePermanently();
@override
String toString() {
return 'DocEvent.deletePermanently()';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) || (other is DeletePermanently);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() deleted,
required TResult Function() restore,
required TResult Function() restorePage,
required TResult Function() deletePermanently,
}) {
return deletePermanently();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? deleted,
TResult Function()? restore,
TResult Function()? restorePage,
TResult Function()? deletePermanently,
required TResult orElse(),
}) {
if (deletePermanently != null) {
return deletePermanently();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Initial value) initial,
required TResult Function(Deleted value) deleted,
required TResult Function(Restore value) restore,
required TResult Function(RestorePage value) restorePage,
required TResult Function(DeletePermanently value) deletePermanently,
}) {
return deletePermanently(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Initial value)? initial,
TResult Function(Deleted value)? deleted,
TResult Function(Restore value)? restore,
TResult Function(RestorePage value)? restorePage,
TResult Function(DeletePermanently value)? deletePermanently,
required TResult orElse(),
}) {
if (deletePermanently != null) {
return deletePermanently(this);
}
return orElse();
}
}
abstract class DeletePermanently implements DocEvent {
const factory DeletePermanently() = _$DeletePermanently;
}
/// @nodoc
class _$DocStateTearOff {
const _$DocStateTearOff();

View File

@ -89,8 +89,10 @@ class HomeDepsResolver {
// Doc
getIt.registerFactoryParam<DocBloc, View, void>(
(view, _) => DocBloc(
view: view,
docManager: getIt<IDoc>(param1: view.id),
listener: getIt<IViewListener>(param1: view),
trasnManager: getIt<ITrash>(),
),
);

View File

@ -2,7 +2,7 @@ import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/doc/doc_bloc.dart';
import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill/flutter_quill.dart' as quill;
import 'package:flowy_infra_ui/style_widget/progress_indicator.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:styled_widget/styled_widget.dart';
import 'styles.dart';
import 'widget/banner.dart';
import 'widget/toolbar/tool_bar.dart';
class DocPage extends StatefulWidget {
@ -42,7 +43,7 @@ class _DocPageState extends State<DocPage> {
return state.loadState.map(
loading: (_) => const FlowyProgressIndicator(),
finish: (result) => result.successOrFail.fold(
(_) => _renderDoc(context),
(_) => _renderDoc(context, state),
(err) => FlowyErrorPage(err.toString()),
),
);
@ -56,12 +57,16 @@ class _DocPageState extends State<DocPage> {
super.dispose();
}
Widget _renderDoc(BuildContext context) {
QuillController controller = QuillController(
Widget _renderDoc(BuildContext context, DocState state) {
quill.QuillController controller = quill.QuillController(
document: context.read<DocBloc>().document,
selection: const TextSelection.collapsed(offset: 0),
);
return Column(
children: [
if (state.isDeleted) _renderBanner(context),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_renderEditor(controller),
@ -69,11 +74,25 @@ class _DocPageState extends State<DocPage> {
_renderToolbar(controller),
const VSpace(10),
],
).padding(horizontal: 40, top: 28);
).padding(horizontal: 40, top: 28),
),
],
);
}
Widget _renderEditor(QuillController controller) {
final editor = QuillEditor(
Widget _renderBanner(BuildContext context) {
return DocBanner(
onRestore: () {
context.read<DocBloc>().add(const DocEvent.restorePage());
},
onDelete: () {
context.read<DocBloc>().add(const DocEvent.deletePermanently());
},
);
}
Widget _renderEditor(quill.QuillController controller) {
final editor = quill.QuillEditor(
controller: controller,
focusNode: _focusNode,
scrollable: true,
@ -96,7 +115,7 @@ class _DocPageState extends State<DocPage> {
);
}
Widget _renderToolbar(QuillController controller) {
Widget _renderToolbar(quill.QuillController controller) {
return EditorToolbar.basic(
controller: controller,
);

View File

@ -0,0 +1,55 @@
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/buttons/base_styled_button.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class DocBanner extends StatelessWidget {
final void Function() onRestore;
final void Function() onDelete;
const DocBanner({required this.onRestore, required this.onDelete, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
// [[Row]] CrossAxisAlignment vs mainAxisAlignment
// https://stackoverflow.com/questions/53850149/flutter-crossaxisalignment-vs-mainaxisalignment
return Container(
color: theme.main1,
height: 60,
child: Row(
children: [
const FlowyText.medium('This page is in Trash', color: Colors.white),
const HSpace(20),
BaseStyledButton(
minWidth: 160,
minHeight: 40,
contentPadding: EdgeInsets.zero,
bgColor: Colors.transparent,
hoverColor: theme.main2,
downColor: theme.main1,
outlineColor: Colors.white,
borderRadius: Corners.s8Border,
child: const FlowyText.medium('Restore page', color: Colors.white, fontSize: 14),
onPressed: onRestore),
const HSpace(20),
BaseStyledButton(
minWidth: 220,
minHeight: 40,
contentPadding: EdgeInsets.zero,
bgColor: Colors.transparent,
hoverColor: theme.main2,
downColor: theme.main1,
outlineColor: Colors.white,
borderRadius: Corners.s8Border,
child: const FlowyText.medium('Delete permanently', color: Colors.white, fontSize: 14),
onPressed: onDelete),
],
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
),
);
}
}