mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: open next page when current page get deleted
This commit is contained in:
parent
bdf4e60b48
commit
37f85cebde
@ -9,7 +9,7 @@ import 'package:app_flowy/startup/plugin/plugin.dart';
|
|||||||
class BlankPluginBuilder extends PluginBuilder {
|
class BlankPluginBuilder extends PluginBuilder {
|
||||||
@override
|
@override
|
||||||
Plugin build(dynamic data) {
|
Plugin build(dynamic data) {
|
||||||
return BlankPagePlugin(pluginType: pluginType);
|
return BlankPagePlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -25,11 +25,6 @@ class BlankPluginConfig implements PluginConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BlankPagePlugin extends Plugin {
|
class BlankPagePlugin extends Plugin {
|
||||||
final PluginType _pluginType;
|
|
||||||
BlankPagePlugin({
|
|
||||||
required PluginType pluginType,
|
|
||||||
}) : _pluginType = pluginType;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginDisplay get display => BlankPagePluginDisplay();
|
PluginDisplay get display => BlankPagePluginDisplay();
|
||||||
|
|
||||||
@ -37,7 +32,7 @@ class BlankPagePlugin extends Plugin {
|
|||||||
PluginId get id => "BlankStack";
|
PluginId get id => "BlankStack";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginType get ty => _pluginType;
|
PluginType get ty => PluginType.blank;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BlankPagePluginDisplay extends PluginDisplay with NavigationItem {
|
class BlankPagePluginDisplay extends PluginDisplay with NavigationItem {
|
||||||
@ -46,7 +41,7 @@ class BlankPagePluginDisplay extends PluginDisplay with NavigationItem {
|
|||||||
FlowyText.medium(LocaleKeys.blankPageTitle.tr(), fontSize: 12);
|
FlowyText.medium(LocaleKeys.blankPageTitle.tr(), fontSize: 12);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildWidget() => const BlankPage();
|
Widget buildWidget(PluginContext context) => const BlankPage();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<NavigationItem> get navigationItems => [this];
|
List<NavigationItem> get navigationItems => [this];
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:app_flowy/plugins/util.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
|
import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
||||||
@ -35,34 +36,45 @@ class BoardPluginConfig implements PluginConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BoardPlugin extends Plugin {
|
class BoardPlugin extends Plugin {
|
||||||
final ViewPB _view;
|
@override
|
||||||
|
final ViewPluginNotifier notifier;
|
||||||
final PluginType _pluginType;
|
final PluginType _pluginType;
|
||||||
|
|
||||||
BoardPlugin({
|
BoardPlugin({
|
||||||
required ViewPB view,
|
required ViewPB view,
|
||||||
required PluginType pluginType,
|
required PluginType pluginType,
|
||||||
}) : _pluginType = pluginType,
|
}) : _pluginType = pluginType,
|
||||||
_view = view;
|
notifier = ViewPluginNotifier(view: view);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginDisplay get display => GridPluginDisplay(view: _view);
|
PluginDisplay get display => GridPluginDisplay(notifier: notifier);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginId get id => _view.id;
|
PluginId get id => notifier.view.id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginType get ty => _pluginType;
|
PluginType get ty => _pluginType;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridPluginDisplay extends PluginDisplay {
|
class GridPluginDisplay extends PluginDisplay {
|
||||||
final ViewPB _view;
|
final ViewPluginNotifier notifier;
|
||||||
GridPluginDisplay({required ViewPB view, Key? key}) : _view = view;
|
GridPluginDisplay({required this.notifier, Key? key});
|
||||||
|
|
||||||
|
ViewPB get view => notifier.view;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget get leftBarItem => ViewLeftBarItem(view: _view);
|
Widget get leftBarItem => ViewLeftBarItem(view: view);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildWidget() => BoardPage(view: _view);
|
Widget buildWidget(PluginContext context) {
|
||||||
|
notifier.isDeleted.addListener(() {
|
||||||
|
if (notifier.isDeleted.value) {
|
||||||
|
context.onDeleted(view);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return BoardPage(key: ValueKey(view.id), view: view);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<NavigationItem> get navigationItems => [this];
|
List<NavigationItem> get navigationItems => [this];
|
||||||
|
@ -31,7 +31,10 @@ import 'toolbar/board_toolbar.dart';
|
|||||||
|
|
||||||
class BoardPage extends StatelessWidget {
|
class BoardPage extends StatelessWidget {
|
||||||
final ViewPB view;
|
final ViewPB view;
|
||||||
BoardPage({required this.view, Key? key}) : super(key: ValueKey(view.id));
|
BoardPage({
|
||||||
|
required this.view,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: ValueKey(view.id));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
library document_plugin;
|
library document_plugin;
|
||||||
|
|
||||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:app_flowy/plugins/util.dart';
|
||||||
import 'package:app_flowy/startup/plugin/plugin.dart';
|
import 'package:app_flowy/startup/plugin/plugin.dart';
|
||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
import 'package:app_flowy/workspace/application/appearance.dart';
|
import 'package:app_flowy/workspace/application/appearance.dart';
|
||||||
import 'package:app_flowy/workspace/application/view/view_listener.dart';
|
|
||||||
import 'package:app_flowy/plugins/doc/application/share_bloc.dart';
|
import 'package:app_flowy/plugins/doc/application/share_bloc.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/home/toast.dart';
|
import 'package:app_flowy/workspace/presentation/home/toast.dart';
|
||||||
@ -14,7 +14,6 @@ import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
|
|||||||
import 'package:clipboard/clipboard.dart';
|
import 'package:clipboard/clipboard.dart';
|
||||||
import 'package:dartz/dartz.dart' as dartz;
|
import 'package:dartz/dartz.dart' as dartz;
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/notifier.dart';
|
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||||
@ -48,63 +47,51 @@ class DocumentPluginBuilder extends PluginBuilder {
|
|||||||
ViewDataTypePB get dataType => ViewDataTypePB.Text;
|
ViewDataTypePB get dataType => ViewDataTypePB.Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DocumentPlugin implements Plugin {
|
class DocumentPlugin extends Plugin<int> {
|
||||||
late ViewPB _view;
|
|
||||||
ViewListener? _listener;
|
|
||||||
late PluginType _pluginType;
|
late PluginType _pluginType;
|
||||||
|
|
||||||
DocumentPlugin(
|
@override
|
||||||
{required PluginType pluginType, required ViewPB view, Key? key})
|
final ViewPluginNotifier notifier;
|
||||||
: _view = view {
|
|
||||||
|
DocumentPlugin({
|
||||||
|
required PluginType pluginType,
|
||||||
|
required ViewPB view,
|
||||||
|
Key? key,
|
||||||
|
}) : notifier = ViewPluginNotifier(view: view) {
|
||||||
_pluginType = pluginType;
|
_pluginType = pluginType;
|
||||||
_listener = getIt<ViewListener>(param1: view);
|
|
||||||
_listener?.start(onViewUpdated: (result) {
|
|
||||||
result.fold(
|
|
||||||
(newView) {
|
|
||||||
_view = newView;
|
|
||||||
display.notifier!.value = _view.hashCode;
|
|
||||||
},
|
|
||||||
(error) {},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
PluginDisplay get display => DocumentPluginDisplay(notifier: notifier);
|
||||||
_listener?.stop();
|
|
||||||
_listener = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
PluginDisplay<int> get display => DocumentPluginDisplay(view: _view);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginType get ty => _pluginType;
|
PluginType get ty => _pluginType;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginId get id => _view.id;
|
PluginId get id => notifier.view.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DocumentPluginDisplay extends PluginDisplay<int> with NavigationItem {
|
class DocumentPluginDisplay extends PluginDisplay with NavigationItem {
|
||||||
final PublishNotifier<int> _displayNotifier = PublishNotifier<int>();
|
final ViewPluginNotifier notifier;
|
||||||
final ViewPB _view;
|
ViewPB get view => notifier.view;
|
||||||
|
|
||||||
DocumentPluginDisplay({required ViewPB view, Key? key}) : _view = view;
|
DocumentPluginDisplay({required this.notifier, Key? key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildWidget() => DocumentPage(view: _view, key: ValueKey(_view.id));
|
Widget buildWidget(PluginContext context) => DocumentPage(
|
||||||
|
view: view,
|
||||||
|
onDeleted: () => context.onDeleted(view),
|
||||||
|
key: ValueKey(view.id),
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget get leftBarItem => ViewLeftBarItem(view: _view);
|
Widget get leftBarItem => ViewLeftBarItem(view: view);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget? get rightBarItem => DocumentShareButton(view: _view);
|
Widget? get rightBarItem => DocumentShareButton(view: view);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<NavigationItem> get navigationItems => [this];
|
List<NavigationItem> get navigationItems => [this];
|
||||||
|
|
||||||
@override
|
|
||||||
PublishNotifier<int>? get notifier => _displayNotifier;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DocumentShareButton extends StatelessWidget {
|
class DocumentShareButton extends StatelessWidget {
|
||||||
|
@ -14,9 +14,14 @@ import 'application/doc_bloc.dart';
|
|||||||
import 'styles.dart';
|
import 'styles.dart';
|
||||||
|
|
||||||
class DocumentPage extends StatefulWidget {
|
class DocumentPage extends StatefulWidget {
|
||||||
|
final VoidCallback onDeleted;
|
||||||
final ViewPB view;
|
final ViewPB view;
|
||||||
|
|
||||||
DocumentPage({Key? key, required this.view}) : super(key: ValueKey(view.id));
|
DocumentPage({
|
||||||
|
required this.view,
|
||||||
|
required this.onDeleted,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: ValueKey(view.id));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DocumentPage> createState() => _DocumentPageState();
|
State<DocumentPage> createState() => _DocumentPageState();
|
||||||
@ -49,7 +54,8 @@ class _DocumentPageState extends State<DocumentPage> {
|
|||||||
finish: (result) => result.successOrFail.fold(
|
finish: (result) => result.successOrFail.fold(
|
||||||
(_) {
|
(_) {
|
||||||
if (state.forceClose) {
|
if (state.forceClose) {
|
||||||
return _renderAppPage();
|
widget.onDeleted();
|
||||||
|
return const SizedBox();
|
||||||
} else {
|
} else {
|
||||||
return _renderDocument(context, state);
|
return _renderDocument(context, state);
|
||||||
}
|
}
|
||||||
@ -134,10 +140,4 @@ class _DocumentPageState extends State<DocumentPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _renderAppPage() {
|
|
||||||
return Container(
|
|
||||||
color: Colors.black,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:app_flowy/plugins/util.dart';
|
||||||
import 'package:app_flowy/startup/plugin/plugin.dart';
|
import 'package:app_flowy/startup/plugin/plugin.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
|
import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart';
|
||||||
@ -37,34 +38,45 @@ class GridPluginConfig implements PluginConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class GridPlugin extends Plugin {
|
class GridPlugin extends Plugin {
|
||||||
final ViewPB _view;
|
@override
|
||||||
|
final ViewPluginNotifier notifier;
|
||||||
final PluginType _pluginType;
|
final PluginType _pluginType;
|
||||||
|
|
||||||
GridPlugin({
|
GridPlugin({
|
||||||
required ViewPB view,
|
required ViewPB view,
|
||||||
required PluginType pluginType,
|
required PluginType pluginType,
|
||||||
}) : _pluginType = pluginType,
|
}) : _pluginType = pluginType,
|
||||||
_view = view;
|
notifier = ViewPluginNotifier(view: view);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginDisplay get display => GridPluginDisplay(view: _view);
|
PluginDisplay get display => GridPluginDisplay(notifier: notifier);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginId get id => _view.id;
|
PluginId get id => notifier.view.id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PluginType get ty => _pluginType;
|
PluginType get ty => _pluginType;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridPluginDisplay extends PluginDisplay {
|
class GridPluginDisplay extends PluginDisplay {
|
||||||
final ViewPB _view;
|
final ViewPluginNotifier notifier;
|
||||||
GridPluginDisplay({required ViewPB view, Key? key}) : _view = view;
|
ViewPB get view => notifier.view;
|
||||||
|
|
||||||
|
GridPluginDisplay({required this.notifier, Key? key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget get leftBarItem => ViewLeftBarItem(view: _view);
|
Widget get leftBarItem => ViewLeftBarItem(view: view);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildWidget() => GridPage(view: _view);
|
Widget buildWidget(PluginContext context) {
|
||||||
|
notifier.isDeleted.addListener(() {
|
||||||
|
if (notifier.isDeleted.value) {
|
||||||
|
context.onDeleted(view);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return GridPage(key: ValueKey(view.id), view: view);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<NavigationItem> get navigationItems => [this];
|
List<NavigationItem> get navigationItems => [this];
|
||||||
|
@ -29,8 +29,13 @@ import 'widgets/toolbar/grid_toolbar.dart';
|
|||||||
|
|
||||||
class GridPage extends StatefulWidget {
|
class GridPage extends StatefulWidget {
|
||||||
final ViewPB view;
|
final ViewPB view;
|
||||||
|
final VoidCallback? onDeleted;
|
||||||
|
|
||||||
GridPage({Key? key, required this.view}) : super(key: ValueKey(view.id));
|
GridPage({
|
||||||
|
required this.view,
|
||||||
|
this.onDeleted,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: ValueKey(view.id));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GridPage> createState() => _GridPageState();
|
State<GridPage> createState() => _GridPageState();
|
||||||
|
@ -66,7 +66,9 @@ class TrashPluginDisplay extends PluginDisplay {
|
|||||||
Widget? get rightBarItem => null;
|
Widget? get rightBarItem => null;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildWidget() => const TrashPage(key: ValueKey('TrashPage'));
|
Widget buildWidget(PluginContext context) => const TrashPage(
|
||||||
|
key: ValueKey('TrashPage'),
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<NavigationItem> get navigationItems => [this];
|
List<NavigationItem> get navigationItems => [this];
|
||||||
|
44
frontend/app_flowy/lib/plugins/util.dart
Normal file
44
frontend/app_flowy/lib/plugins/util.dart
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import 'package:app_flowy/startup/plugin/plugin.dart';
|
||||||
|
import 'package:app_flowy/workspace/application/view/view_listener.dart';
|
||||||
|
import 'package:flowy_sdk/log.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ViewPluginNotifier extends PluginNotifier {
|
||||||
|
final ViewListener? _viewListener;
|
||||||
|
ViewPB view;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final ValueNotifier<bool> isDeleted = ValueNotifier(false);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final ValueNotifier<int> isDisplayChanged = ValueNotifier(0);
|
||||||
|
|
||||||
|
ViewPluginNotifier({
|
||||||
|
required this.view,
|
||||||
|
}) : _viewListener = ViewListener(view: view) {
|
||||||
|
_viewListener?.start(onViewUpdated: (result) {
|
||||||
|
result.fold(
|
||||||
|
(updatedView) {
|
||||||
|
view = updatedView;
|
||||||
|
isDisplayChanged.value = updatedView.hashCode;
|
||||||
|
},
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
}, onViewMoveToTrash: (result) {
|
||||||
|
result.fold(
|
||||||
|
(deletedView) {
|
||||||
|
isDeleted.value = true;
|
||||||
|
},
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
isDeleted.dispose();
|
||||||
|
isDisplayChanged.dispose();
|
||||||
|
_viewListener?.stop();
|
||||||
|
}
|
||||||
|
}
|
@ -120,7 +120,7 @@ void _resolveFolderDeps(GetIt getIt) {
|
|||||||
getIt.registerFactoryParam<AppBloc, AppPB, void>(
|
getIt.registerFactoryParam<AppBloc, AppPB, void>(
|
||||||
(app, _) => AppBloc(
|
(app, _) => AppBloc(
|
||||||
app: app,
|
app: app,
|
||||||
appService: AppService(appId: app.id),
|
appService: AppService(),
|
||||||
appListener: AppListener(appId: app.id),
|
appListener: AppListener(appId: app.id),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -3,7 +3,6 @@ library flowy_plugin;
|
|||||||
import 'package:app_flowy/startup/plugin/plugin.dart';
|
import 'package:app_flowy/startup/plugin/plugin.dart';
|
||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
||||||
import 'package:flowy_infra/notifier.dart';
|
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
@ -17,33 +16,29 @@ enum PluginType {
|
|||||||
board,
|
board,
|
||||||
}
|
}
|
||||||
|
|
||||||
// extension FlowyDefaultPluginExt on DefaultPlugin {
|
|
||||||
// int type() {
|
|
||||||
// switch (this) {
|
|
||||||
// case DefaultPlugin.editor:
|
|
||||||
// return 0;
|
|
||||||
// case DefaultPlugin.blank:
|
|
||||||
// return 1;
|
|
||||||
// case DefaultPlugin.trash:
|
|
||||||
// return 2;
|
|
||||||
// case DefaultPlugin.grid:
|
|
||||||
// return 3;
|
|
||||||
// case DefaultPlugin.board:
|
|
||||||
// return 4;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// typedef PluginType = int;
|
|
||||||
typedef PluginId = String;
|
typedef PluginId = String;
|
||||||
|
|
||||||
abstract class Plugin {
|
abstract class Plugin<T> {
|
||||||
PluginId get id;
|
PluginId get id;
|
||||||
|
|
||||||
PluginDisplay get display;
|
PluginDisplay get display;
|
||||||
|
|
||||||
|
PluginNotifier? get notifier => null;
|
||||||
|
|
||||||
PluginType get ty;
|
PluginType get ty;
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
notifier?.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PluginNotifier {
|
||||||
|
/// Notify if the plugin get deleted
|
||||||
|
ValueNotifier<bool> get isDeleted;
|
||||||
|
|
||||||
|
/// Notify if the [PluginDisplay]'s content was changed
|
||||||
|
ValueNotifier<int> get isDisplayChanged;
|
||||||
|
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,12 +59,17 @@ abstract class PluginConfig {
|
|||||||
bool get creatable => true;
|
bool get creatable => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class PluginDisplay<T> with NavigationItem {
|
abstract class PluginDisplay with NavigationItem {
|
||||||
List<NavigationItem> get navigationItems;
|
List<NavigationItem> get navigationItems;
|
||||||
|
|
||||||
PublishNotifier<T>? get notifier => null;
|
Widget buildWidget(PluginContext context);
|
||||||
|
}
|
||||||
|
|
||||||
Widget buildWidget();
|
class PluginContext {
|
||||||
|
// calls when widget of the plugin get deleted
|
||||||
|
final Function(ViewPB) onDeleted;
|
||||||
|
|
||||||
|
PluginContext({required this.onDeleted});
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerPlugin({required PluginBuilder builder, PluginConfig? config}) {
|
void registerPlugin({required PluginBuilder builder, PluginConfig? config}) {
|
||||||
|
@ -9,12 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
|||||||
import 'package:app_flowy/startup/plugin/plugin.dart';
|
import 'package:app_flowy/startup/plugin/plugin.dart';
|
||||||
|
|
||||||
class AppService {
|
class AppService {
|
||||||
final String appId;
|
Future<Either<AppPB, FlowyError>> readApp({required String appId}) {
|
||||||
AppService({
|
|
||||||
required this.appId,
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<Either<AppPB, FlowyError>> getAppDesc({required String appId}) {
|
|
||||||
final payload = AppIdPB.create()..value = appId;
|
final payload = AppIdPB.create()..value = appId;
|
||||||
|
|
||||||
return FolderEventReadApp(payload).send();
|
return FolderEventReadApp(payload).send();
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
|
||||||
|
|
||||||
|
class HomeService {
|
||||||
|
Future<Either<AppPB, FlowyError>> readApp({required String appId}) {
|
||||||
|
final payload = AppIdPB.create()..value = appId;
|
||||||
|
|
||||||
|
return FolderEventReadApp(payload).send();
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,7 @@ class ViewSectionBloc extends Bloc<ViewSectionEvent, ViewSectionState> {
|
|||||||
|
|
||||||
ViewSectionBloc({
|
ViewSectionBloc({
|
||||||
required AppViewDataContext appViewData,
|
required AppViewDataContext appViewData,
|
||||||
}) : _appService = AppService(appId: appViewData.appId),
|
}) : _appService = AppService(),
|
||||||
_appViewData = appViewData,
|
_appViewData = appViewData,
|
||||||
super(ViewSectionState.initial(appViewData)) {
|
super(ViewSectionState.initial(appViewData)) {
|
||||||
on<ViewSectionEvent>((event, emit) async {
|
on<ViewSectionEvent>((event, emit) async {
|
||||||
@ -59,7 +59,8 @@ class ViewSectionBloc extends Bloc<ViewSectionEvent, ViewSectionState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _moveView(_MoveView value, Emitter<ViewSectionState> emit) async {
|
Future<void> _moveView(
|
||||||
|
_MoveView value, Emitter<ViewSectionState> emit) async {
|
||||||
if (value.fromIndex < state.views.length) {
|
if (value.fromIndex < state.views.length) {
|
||||||
final viewId = state.views[value.fromIndex].id;
|
final viewId = state.views[value.fromIndex].id;
|
||||||
final views = List<ViewPB>.from(state.views);
|
final views = List<ViewPB>.from(state.views);
|
||||||
@ -92,9 +93,12 @@ class ViewSectionBloc extends Bloc<ViewSectionEvent, ViewSectionState> {
|
|||||||
@freezed
|
@freezed
|
||||||
class ViewSectionEvent with _$ViewSectionEvent {
|
class ViewSectionEvent with _$ViewSectionEvent {
|
||||||
const factory ViewSectionEvent.initial() = _Initial;
|
const factory ViewSectionEvent.initial() = _Initial;
|
||||||
const factory ViewSectionEvent.setSelectedView(ViewPB? view) = _SetSelectedView;
|
const factory ViewSectionEvent.setSelectedView(ViewPB? view) =
|
||||||
const factory ViewSectionEvent.moveView(int fromIndex, int toIndex) = _MoveView;
|
_SetSelectedView;
|
||||||
const factory ViewSectionEvent.didReceiveViewUpdated(List<ViewPB> views) = _DidReceiveViewUpdated;
|
const factory ViewSectionEvent.moveView(int fromIndex, int toIndex) =
|
||||||
|
_MoveView;
|
||||||
|
const factory ViewSectionEvent.didReceiveViewUpdated(List<ViewPB> views) =
|
||||||
|
_DidReceiveViewUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@ -104,7 +108,8 @@ class ViewSectionState with _$ViewSectionState {
|
|||||||
ViewPB? selectedView,
|
ViewPB? selectedView,
|
||||||
}) = _ViewSectionState;
|
}) = _ViewSectionState;
|
||||||
|
|
||||||
factory ViewSectionState.initial(AppViewDataContext appViewData) => ViewSectionState(
|
factory ViewSectionState.initial(AppViewDataContext appViewData) =>
|
||||||
|
ViewSectionState(
|
||||||
views: appViewData.views,
|
views: appViewData.views,
|
||||||
selectedView: appViewData.selectedView,
|
selectedView: appViewData.selectedView,
|
||||||
);
|
);
|
||||||
|
@ -9,15 +9,21 @@ import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
|
|||||||
import 'package:flowy_sdk/rust_stream.dart';
|
import 'package:flowy_sdk/rust_stream.dart';
|
||||||
import 'package:flowy_infra/notifier.dart';
|
import 'package:flowy_infra/notifier.dart';
|
||||||
|
|
||||||
|
// Delete the view from trash, which means the view was deleted permanently
|
||||||
typedef DeleteViewNotifyValue = Either<ViewPB, FlowyError>;
|
typedef DeleteViewNotifyValue = Either<ViewPB, FlowyError>;
|
||||||
|
// The view get updated
|
||||||
typedef UpdateViewNotifiedValue = Either<ViewPB, FlowyError>;
|
typedef UpdateViewNotifiedValue = Either<ViewPB, FlowyError>;
|
||||||
|
// Restore the view from trash
|
||||||
typedef RestoreViewNotifiedValue = Either<ViewPB, FlowyError>;
|
typedef RestoreViewNotifiedValue = Either<ViewPB, FlowyError>;
|
||||||
|
// Move the view to trash
|
||||||
|
typedef MoveToTrashNotifiedValue = Either<ViewIdPB, FlowyError>;
|
||||||
|
|
||||||
class ViewListener {
|
class ViewListener {
|
||||||
StreamSubscription<SubscribeObject>? _subscription;
|
StreamSubscription<SubscribeObject>? _subscription;
|
||||||
final PublishNotifier<UpdateViewNotifiedValue> _updatedViewNotifier = PublishNotifier();
|
final _updatedViewNotifier = PublishNotifier<UpdateViewNotifiedValue>();
|
||||||
final PublishNotifier<DeleteViewNotifyValue> _deletedNotifier = PublishNotifier();
|
final _deletedNotifier = PublishNotifier<DeleteViewNotifyValue>();
|
||||||
final PublishNotifier<RestoreViewNotifiedValue> _restoredNotifier = PublishNotifier();
|
final _restoredNotifier = PublishNotifier<RestoreViewNotifiedValue>();
|
||||||
|
final _moveToTrashNotifier = PublishNotifier<MoveToTrashNotifiedValue>();
|
||||||
FolderNotificationParser? _parser;
|
FolderNotificationParser? _parser;
|
||||||
ViewPB view;
|
ViewPB view;
|
||||||
|
|
||||||
@ -29,6 +35,7 @@ class ViewListener {
|
|||||||
void Function(UpdateViewNotifiedValue)? onViewUpdated,
|
void Function(UpdateViewNotifiedValue)? onViewUpdated,
|
||||||
void Function(DeleteViewNotifyValue)? onViewDeleted,
|
void Function(DeleteViewNotifyValue)? onViewDeleted,
|
||||||
void Function(RestoreViewNotifiedValue)? onViewRestored,
|
void Function(RestoreViewNotifiedValue)? onViewRestored,
|
||||||
|
void Function(MoveToTrashNotifiedValue)? onViewMoveToTrash,
|
||||||
}) {
|
}) {
|
||||||
if (onViewUpdated != null) {
|
if (onViewUpdated != null) {
|
||||||
_updatedViewNotifier.addListener(() {
|
_updatedViewNotifier.addListener(() {
|
||||||
@ -48,6 +55,12 @@ class ViewListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (onViewMoveToTrash != null) {
|
||||||
|
_moveToTrashNotifier.addListener(() {
|
||||||
|
onViewMoveToTrash(_moveToTrashNotifier.currentValue!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_parser = FolderNotificationParser(
|
_parser = FolderNotificationParser(
|
||||||
id: view.id,
|
id: view.id,
|
||||||
callback: (ty, result) {
|
callback: (ty, result) {
|
||||||
@ -55,29 +68,41 @@ class ViewListener {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
|
_subscription =
|
||||||
|
RustStreamReceiver.listen((observable) => _parser?.parse(observable));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleObservableType(FolderNotification ty, Either<Uint8List, FlowyError> result) {
|
void _handleObservableType(
|
||||||
|
FolderNotification ty, Either<Uint8List, FlowyError> result) {
|
||||||
switch (ty) {
|
switch (ty) {
|
||||||
case FolderNotification.ViewUpdated:
|
case FolderNotification.ViewUpdated:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => _updatedViewNotifier.value = left(ViewPB.fromBuffer(payload)),
|
(payload) =>
|
||||||
|
_updatedViewNotifier.value = left(ViewPB.fromBuffer(payload)),
|
||||||
(error) => _updatedViewNotifier.value = right(error),
|
(error) => _updatedViewNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case FolderNotification.ViewDeleted:
|
case FolderNotification.ViewDeleted:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => _deletedNotifier.value = left(ViewPB.fromBuffer(payload)),
|
(payload) =>
|
||||||
|
_deletedNotifier.value = left(ViewPB.fromBuffer(payload)),
|
||||||
(error) => _deletedNotifier.value = right(error),
|
(error) => _deletedNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case FolderNotification.ViewRestored:
|
case FolderNotification.ViewRestored:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => _restoredNotifier.value = left(ViewPB.fromBuffer(payload)),
|
(payload) =>
|
||||||
|
_restoredNotifier.value = left(ViewPB.fromBuffer(payload)),
|
||||||
(error) => _restoredNotifier.value = right(error),
|
(error) => _restoredNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case FolderNotification.ViewMoveToTrash:
|
||||||
|
result.fold(
|
||||||
|
(payload) =>
|
||||||
|
_moveToTrashNotifier.value = left(ViewIdPB.fromBuffer(payload)),
|
||||||
|
(error) => _moveToTrashNotifier.value = right(error),
|
||||||
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,8 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart' show MoveFolderItemPayloadPB, MoveFolderItemType;
|
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'
|
||||||
|
show MoveFolderItemPayloadPB, MoveFolderItemType;
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder/workspace.pb.dart';
|
||||||
|
|
||||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||||
@ -15,7 +16,8 @@ class WorkspaceService {
|
|||||||
WorkspaceService({
|
WorkspaceService({
|
||||||
required this.workspaceId,
|
required this.workspaceId,
|
||||||
});
|
});
|
||||||
Future<Either<AppPB, FlowyError>> createApp({required String name, required String desc}) {
|
Future<Either<AppPB, FlowyError>> createApp(
|
||||||
|
{required String name, required String desc}) {
|
||||||
final payload = CreateAppPayloadPB.create()
|
final payload = CreateAppPayloadPB.create()
|
||||||
..name = name
|
..name = name
|
||||||
..workspaceId = workspaceId
|
..workspaceId = workspaceId
|
||||||
@ -31,7 +33,8 @@ class WorkspaceService {
|
|||||||
assert(workspaces.items.length == 1);
|
assert(workspaces.items.length == 1);
|
||||||
|
|
||||||
if (workspaces.items.isEmpty) {
|
if (workspaces.items.isEmpty) {
|
||||||
return right(FlowyError.create()..msg = LocaleKeys.workspace_notFoundError.tr());
|
return right(FlowyError.create()
|
||||||
|
..msg = LocaleKeys.workspace_notFoundError.tr());
|
||||||
} else {
|
} else {
|
||||||
return left(workspaces.items[0]);
|
return left(workspaces.items[0]);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
import 'package:app_flowy/plugins/blank/blank.dart';
|
||||||
import 'package:app_flowy/startup/plugin/plugin.dart';
|
import 'package:app_flowy/startup/plugin/plugin.dart';
|
||||||
import 'package:app_flowy/workspace/application/home/home_bloc.dart';
|
import 'package:app_flowy/workspace/application/home/home_bloc.dart';
|
||||||
|
import 'package:app_flowy/workspace/application/home/home_service.dart';
|
||||||
|
|
||||||
import 'package:app_flowy/workspace/presentation/home/hotkeys.dart';
|
import 'package:app_flowy/workspace/presentation/home/hotkeys.dart';
|
||||||
import 'package:app_flowy/workspace/application/view/view_ext.dart';
|
import 'package:app_flowy/workspace/application/view/view_ext.dart';
|
||||||
@ -78,7 +80,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
return FlowyContainer(
|
return FlowyContainer(
|
||||||
Theme.of(context).colorScheme.surface,
|
Theme.of(context).colorScheme.surface,
|
||||||
// Colors.white,
|
// Colors.white,
|
||||||
child: _buildBody(state),
|
child: _buildBody(context, state),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -87,12 +89,16 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBody(HomeState state) {
|
Widget _buildBody(BuildContext context, HomeState state) {
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (BuildContext context, BoxConstraints constraints) {
|
builder: (BuildContext context, BoxConstraints constraints) {
|
||||||
final layout = HomeLayout(context, constraints, state.forceCollapse);
|
final layout = HomeLayout(context, constraints, state.forceCollapse);
|
||||||
final homeStack = HomeStack(
|
final homeStack = HomeStack(
|
||||||
layout: layout,
|
layout: layout,
|
||||||
|
delegate: HomeScreenStackAdaptor(
|
||||||
|
buildContext: context,
|
||||||
|
homeState: state,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
final menu = _buildHomeMenu(
|
final menu = _buildHomeMenu(
|
||||||
layout: layout,
|
layout: layout,
|
||||||
@ -132,7 +138,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
getIt<HomeStackManager>().setPlugin(plugin);
|
getIt<HomeStackManager>().setPlugin(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
HomeMenu homeMenu = HomeMenu(
|
final homeMenu = HomeMenu(
|
||||||
user: widget.user,
|
user: widget.user,
|
||||||
workspaceSetting: workspaceSetting,
|
workspaceSetting: workspaceSetting,
|
||||||
collapsedNotifier: getIt<HomeStackManager>().collapsedNotifier,
|
collapsedNotifier: getIt<HomeStackManager>().collapsedNotifier,
|
||||||
@ -148,7 +154,6 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu));
|
return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Widget _buildEditPanel(
|
Widget _buildEditPanel(
|
||||||
{required HomeState homeState,
|
{required HomeState homeState,
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
@ -245,3 +250,38 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HomeScreenStackAdaptor extends HomeStackDelegate {
|
||||||
|
final BuildContext buildContext;
|
||||||
|
final HomeState homeState;
|
||||||
|
|
||||||
|
HomeScreenStackAdaptor({
|
||||||
|
required this.buildContext,
|
||||||
|
required this.homeState,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didDeleteStackWidget(ViewPB view) {
|
||||||
|
final homeService = HomeService();
|
||||||
|
homeService.readApp(appId: view.appId).then((result) {
|
||||||
|
result.fold(
|
||||||
|
(appPB) {
|
||||||
|
final List<ViewPB> views = appPB.belongings.items;
|
||||||
|
if (views.isNotEmpty) {
|
||||||
|
final lastView = views.last;
|
||||||
|
final plugin = makePlugin(
|
||||||
|
pluginType: lastView.pluginType,
|
||||||
|
data: lastView,
|
||||||
|
);
|
||||||
|
getIt<MenuSharedState>().latestOpenView = lastView;
|
||||||
|
getIt<HomeStackManager>().setPlugin(plugin);
|
||||||
|
} else {
|
||||||
|
getIt<MenuSharedState>().latestOpenView = null;
|
||||||
|
getIt<HomeStackManager>().setPlugin(BlankPagePlugin());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ import 'package:app_flowy/startup/startup.dart';
|
|||||||
import 'package:app_flowy/plugins/blank/blank.dart';
|
import 'package:app_flowy/plugins/blank/blank.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/home/toast.dart';
|
import 'package:app_flowy/workspace/presentation/home/toast.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:time/time.dart';
|
import 'package:time/time.dart';
|
||||||
@ -17,14 +17,21 @@ import 'home_layout.dart';
|
|||||||
|
|
||||||
typedef NavigationCallback = void Function(String id);
|
typedef NavigationCallback = void Function(String id);
|
||||||
|
|
||||||
class HomeStack extends StatelessWidget {
|
abstract class HomeStackDelegate {
|
||||||
const HomeStack({Key? key, required this.layout}) : super(key: key);
|
void didDeleteStackWidget(ViewPB view);
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeStack extends StatelessWidget {
|
||||||
|
final HomeStackDelegate delegate;
|
||||||
final HomeLayout layout;
|
final HomeLayout layout;
|
||||||
|
const HomeStack({
|
||||||
|
required this.delegate,
|
||||||
|
required this.layout,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Log.info('HomePage build');
|
|
||||||
final theme = context.watch<AppTheme>();
|
final theme = context.watch<AppTheme>();
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
@ -34,7 +41,9 @@ class HomeStack extends StatelessWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
color: theme.surface,
|
color: theme.surface,
|
||||||
child: FocusTraversalGroup(
|
child: FocusTraversalGroup(
|
||||||
child: getIt<HomeStackManager>().stackWidget(),
|
child: getIt<HomeStackManager>().stackWidget(onDeleted: (view) {
|
||||||
|
delegate.didDeleteStackWidget(view);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -114,18 +123,18 @@ class HomeStackNotifier extends ChangeNotifier {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_plugin.display.notifier?.removeListener(notifyListeners);
|
_plugin.notifier?.isDisplayChanged.addListener(notifyListeners);
|
||||||
_plugin.dispose();
|
_plugin.dispose();
|
||||||
|
|
||||||
_plugin = newPlugin;
|
_plugin = newPlugin;
|
||||||
_plugin.display.notifier?.addListener(notifyListeners);
|
_plugin.notifier?.isDisplayChanged.removeListener(notifyListeners);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin get plugin => _plugin;
|
Plugin get plugin => _plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HomeStack is initialized as singleton to controll the page stack.
|
// HomeStack is initialized as singleton to control the page stack.
|
||||||
class HomeStackManager {
|
class HomeStackManager {
|
||||||
final HomeStackNotifier _notifier = HomeStackNotifier();
|
final HomeStackNotifier _notifier = HomeStackNotifier();
|
||||||
HomeStackManager();
|
HomeStackManager();
|
||||||
@ -140,7 +149,9 @@ class HomeStackManager {
|
|||||||
_notifier.plugin = newPlugin;
|
_notifier.plugin = newPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStackWithId(String id) {}
|
void setStackWithId(String id) {
|
||||||
|
// Navigate to the page with id
|
||||||
|
}
|
||||||
|
|
||||||
Widget stackTopBar({required HomeLayout layout}) {
|
Widget stackTopBar({required HomeLayout layout}) {
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
@ -156,18 +167,16 @@ class HomeStackManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget stackWidget() {
|
Widget stackWidget({required Function(ViewPB) onDeleted}) {
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [ChangeNotifierProvider.value(value: _notifier)],
|
||||||
ChangeNotifierProvider.value(value: _notifier),
|
|
||||||
],
|
|
||||||
child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) {
|
child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) {
|
||||||
return FadingIndexedStack(
|
return FadingIndexedStack(
|
||||||
index: getIt<PluginSandbox>().indexOf(notifier.plugin.ty),
|
index: getIt<PluginSandbox>().indexOf(notifier.plugin.ty),
|
||||||
children: getIt<PluginSandbox>().supportPluginTypes.map((pluginType) {
|
children: getIt<PluginSandbox>().supportPluginTypes.map((pluginType) {
|
||||||
if (pluginType == notifier.plugin.ty) {
|
if (pluginType == notifier.plugin.ty) {
|
||||||
return notifier.plugin.display
|
return notifier.plugin.display
|
||||||
.buildWidget()
|
.buildWidget(PluginContext(onDeleted: onDeleted))
|
||||||
.padding(horizontal: 40, vertical: 28);
|
.padding(horizontal: 40, vertical: 28);
|
||||||
} else {
|
} else {
|
||||||
return const BlankPage();
|
return const BlankPage();
|
||||||
|
@ -42,7 +42,12 @@ class _MenuAppState extends State<MenuApp> {
|
|||||||
listeners: [
|
listeners: [
|
||||||
BlocListener<AppBloc, AppState>(
|
BlocListener<AppBloc, AppState>(
|
||||||
listenWhen: (p, c) => p.latestCreatedView != c.latestCreatedView,
|
listenWhen: (p, c) => p.latestCreatedView != c.latestCreatedView,
|
||||||
listener: (context, state) => getIt<MenuSharedState>().latestOpenView = state.latestCreatedView,
|
listener: (context, state) {
|
||||||
|
if (state.latestCreatedView != null) {
|
||||||
|
getIt<MenuSharedState>().latestOpenView =
|
||||||
|
state.latestCreatedView;
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
BlocListener<AppBloc, AppState>(
|
BlocListener<AppBloc, AppState>(
|
||||||
listenWhen: (p, c) => p.views != c.views,
|
listenWhen: (p, c) => p.views != c.views,
|
||||||
@ -65,7 +70,8 @@ class _MenuAppState extends State<MenuApp> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpandableNotifier expandableWrapper(BuildContext context, AppViewDataContext viewDataContext) {
|
ExpandableNotifier expandableWrapper(
|
||||||
|
BuildContext context, AppViewDataContext viewDataContext) {
|
||||||
return ExpandableNotifier(
|
return ExpandableNotifier(
|
||||||
controller: viewDataContext.expandController,
|
controller: viewDataContext.expandController,
|
||||||
child: ScrollOnExpand(
|
child: ScrollOnExpand(
|
||||||
@ -83,7 +89,8 @@ class _MenuAppState extends State<MenuApp> {
|
|||||||
hasIcon: false,
|
hasIcon: false,
|
||||||
),
|
),
|
||||||
header: ChangeNotifierProvider.value(
|
header: ChangeNotifierProvider.value(
|
||||||
value: Provider.of<AppearanceSettingModel>(context, listen: true),
|
value:
|
||||||
|
Provider.of<AppearanceSettingModel>(context, listen: true),
|
||||||
child: MenuAppHeader(widget.app),
|
child: MenuAppHeader(widget.app),
|
||||||
),
|
),
|
||||||
expanded: ViewSection(appViewData: viewDataContext),
|
expanded: ViewSection(appViewData: viewDataContext),
|
||||||
|
@ -16,6 +16,7 @@ pub(crate) enum FolderNotification {
|
|||||||
ViewUpdated = 31,
|
ViewUpdated = 31,
|
||||||
ViewDeleted = 32,
|
ViewDeleted = 32,
|
||||||
ViewRestored = 33,
|
ViewRestored = 33,
|
||||||
|
ViewMoveToTrash = 34,
|
||||||
UserUnauthorized = 100,
|
UserUnauthorized = 100,
|
||||||
TrashUpdated = 1000,
|
TrashUpdated = 1000,
|
||||||
}
|
}
|
||||||
|
@ -251,8 +251,6 @@ pub trait ViewDataProcessor {
|
|||||||
|
|
||||||
fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError>;
|
fn create_container(&self, user_id: &str, view_id: &str, delta_data: Bytes) -> FutureResult<(), FlowyError>;
|
||||||
|
|
||||||
fn delete_container(&self, view_id: &str) -> FutureResult<(), FlowyError>;
|
|
||||||
|
|
||||||
fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError>;
|
fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError>;
|
||||||
|
|
||||||
fn get_delta_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError>;
|
fn get_delta_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError>;
|
||||||
|
@ -125,7 +125,7 @@ impl ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, view_id), fields(view_id = %view_id.value), err)]
|
#[tracing::instrument(level = "debug", skip(self, view_id), fields(view_id = %view_id.value), err)]
|
||||||
pub(crate) async fn read_view_info(&self, view_id: ViewIdPB) -> Result<ViewInfoPB, FlowyError> {
|
pub(crate) async fn read_view_pb(&self, view_id: ViewIdPB) -> Result<ViewInfoPB, FlowyError> {
|
||||||
let view_info = self
|
let view_info = self
|
||||||
.persistence
|
.persistence
|
||||||
.begin_transaction(|transaction| {
|
.begin_transaction(|transaction| {
|
||||||
@ -179,14 +179,20 @@ impl ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self,params), fields(doc_id = %params.value), err)]
|
#[tracing::instrument(level = "debug", skip(self,params), fields(doc_id = %params.value), err)]
|
||||||
pub(crate) async fn delete_view(&self, params: TextBlockIdPB) -> Result<(), FlowyError> {
|
pub(crate) async fn move_view_to_trash(&self, params: TextBlockIdPB) -> Result<(), FlowyError> {
|
||||||
if let Some(view_id) = KV::get_str(LATEST_VIEW_ID) {
|
let view_id = params.value;
|
||||||
if view_id == params.value {
|
if let Some(latest_view_id) = KV::get_str(LATEST_VIEW_ID) {
|
||||||
|
if latest_view_id == view_id {
|
||||||
let _ = KV::remove(LATEST_VIEW_ID);
|
let _ = KV::remove(LATEST_VIEW_ID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let processor = self.get_data_processor_from_view_id(¶ms.value).await?;
|
let view_id_pb = ViewIdPB::from(view_id.as_str());
|
||||||
let _ = processor.delete_container(¶ms.value).await?;
|
send_dart_notification(&view_id, FolderNotification::ViewMoveToTrash)
|
||||||
|
.payload(view_id_pb)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
let processor = self.get_data_processor_from_view_id(&view_id).await?;
|
||||||
|
let _ = processor.close_container(&view_id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ pub(crate) async fn read_view_info_handler(
|
|||||||
controller: AppData<Arc<ViewController>>,
|
controller: AppData<Arc<ViewController>>,
|
||||||
) -> DataResult<ViewInfoPB, FlowyError> {
|
) -> DataResult<ViewInfoPB, FlowyError> {
|
||||||
let view_id: ViewIdPB = data.into_inner();
|
let view_id: ViewIdPB = data.into_inner();
|
||||||
let view_info = controller.read_view_info(view_id.clone()).await?;
|
let view_info = controller.read_view_pb(view_id.clone()).await?;
|
||||||
data_result(view_info)
|
data_result(view_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ pub(crate) async fn delete_view_handler(
|
|||||||
) -> Result<(), FlowyError> {
|
) -> Result<(), FlowyError> {
|
||||||
let params: RepeatedViewIdPB = data.into_inner();
|
let params: RepeatedViewIdPB = data.into_inner();
|
||||||
for view_id in ¶ms.items {
|
for view_id in ¶ms.items {
|
||||||
let _ = view_controller.delete_view(view_id.into()).await;
|
let _ = view_controller.move_view_to_trash(view_id.into()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let trash = view_controller
|
let trash = view_controller
|
||||||
|
@ -109,17 +109,6 @@ impl GridManager {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, grid_id), fields(doc_id), err)]
|
|
||||||
pub async fn delete_grid<T: AsRef<str>>(&self, grid_id: T) -> FlowyResult<()> {
|
|
||||||
let grid_id = grid_id.as_ref();
|
|
||||||
tracing::Span::current().record("grid_id", &grid_id);
|
|
||||||
self.grid_editors.remove(grid_id);
|
|
||||||
self.task_scheduler.write().await.unregister_handler(grid_id);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub fn update_grid_info()
|
|
||||||
|
|
||||||
// #[tracing::instrument(level = "debug", skip(self), err)]
|
// #[tracing::instrument(level = "debug", skip(self), err)]
|
||||||
pub fn get_grid_editor(&self, grid_id: &str) -> FlowyResult<Arc<GridRevisionEditor>> {
|
pub fn get_grid_editor(&self, grid_id: &str) -> FlowyResult<Arc<GridRevisionEditor>> {
|
||||||
match self.grid_editors.get(grid_id) {
|
match self.grid_editors.get(grid_id) {
|
||||||
|
@ -152,15 +152,6 @@ impl ViewDataProcessor for TextBlockViewDataProcessor {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
|
|
||||||
let manager = self.0.clone();
|
|
||||||
let view_id = view_id.to_string();
|
|
||||||
FutureResult::new(async move {
|
|
||||||
let _ = manager.close_text_editor(view_id)?;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
|
fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
|
||||||
let manager = self.0.clone();
|
let manager = self.0.clone();
|
||||||
let view_id = view_id.to_string();
|
let view_id = view_id.to_string();
|
||||||
@ -230,15 +221,6 @@ impl ViewDataProcessor for GridViewDataProcessor {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
|
|
||||||
let grid_manager = self.0.clone();
|
|
||||||
let view_id = view_id.to_string();
|
|
||||||
FutureResult::new(async move {
|
|
||||||
let _ = grid_manager.delete_grid(view_id).await?;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
|
fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError> {
|
||||||
let grid_manager = self.0.clone();
|
let grid_manager = self.0.clone();
|
||||||
let view_id = view_id.to_string();
|
let view_id = view_id.to_string();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user