mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: open latest after deleting current view
This commit is contained in:
parent
81ecbd8ae2
commit
e3a1384f7f
@ -68,9 +68,11 @@ class GridPluginDisplay extends PluginDisplay {
|
|||||||
@override
|
@override
|
||||||
Widget buildWidget(PluginContext context) {
|
Widget buildWidget(PluginContext context) {
|
||||||
notifier.isDeleted.addListener(() {
|
notifier.isDeleted.addListener(() {
|
||||||
if (notifier.isDeleted.value) {
|
notifier.isDeleted.value.fold(() => null, (deletedView) {
|
||||||
context.onDeleted(view);
|
if (deletedView.hasIndex()) {
|
||||||
}
|
context.onDeleted(view, deletedView.index);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return BoardPage(key: ValueKey(view.id), view: view);
|
return BoardPage(key: ValueKey(view.id), view: view);
|
||||||
|
@ -74,15 +74,26 @@ class DocumentPlugin extends Plugin<int> {
|
|||||||
class DocumentPluginDisplay extends PluginDisplay with NavigationItem {
|
class DocumentPluginDisplay extends PluginDisplay with NavigationItem {
|
||||||
final ViewPluginNotifier notifier;
|
final ViewPluginNotifier notifier;
|
||||||
ViewPB get view => notifier.view;
|
ViewPB get view => notifier.view;
|
||||||
|
int? deletedViewIndex;
|
||||||
|
|
||||||
DocumentPluginDisplay({required this.notifier, Key? key});
|
DocumentPluginDisplay({required this.notifier, Key? key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildWidget(PluginContext context) => DocumentPage(
|
Widget buildWidget(PluginContext context) {
|
||||||
view: view,
|
notifier.isDeleted.addListener(() {
|
||||||
onDeleted: () => context.onDeleted(view),
|
notifier.isDeleted.value.fold(() => null, (deletedView) {
|
||||||
key: ValueKey(view.id),
|
if (deletedView.hasIndex()) {
|
||||||
);
|
deletedViewIndex = deletedView.index;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return DocumentPage(
|
||||||
|
view: view,
|
||||||
|
onDeleted: () => context.onDeleted(view, deletedViewIndex),
|
||||||
|
key: ValueKey(view.id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget get leftBarItem => ViewLeftBarItem(view: view);
|
Widget get leftBarItem => ViewLeftBarItem(view: view);
|
||||||
|
@ -70,9 +70,11 @@ class GridPluginDisplay extends PluginDisplay {
|
|||||||
@override
|
@override
|
||||||
Widget buildWidget(PluginContext context) {
|
Widget buildWidget(PluginContext context) {
|
||||||
notifier.isDeleted.addListener(() {
|
notifier.isDeleted.addListener(() {
|
||||||
if (notifier.isDeleted.value) {
|
notifier.isDeleted.value.fold(() => null, (deletedView) {
|
||||||
context.onDeleted(view);
|
if (deletedView.hasIndex()) {
|
||||||
}
|
context.onDeleted(view, deletedView.index);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return GridPage(key: ValueKey(view.id), view: view);
|
return GridPage(key: ValueKey(view.id), view: view);
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import 'package:app_flowy/startup/plugin/plugin.dart';
|
import 'package:app_flowy/startup/plugin/plugin.dart';
|
||||||
import 'package:app_flowy/workspace/application/view/view_listener.dart';
|
import 'package:app_flowy/workspace/application/view/view_listener.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ViewPluginNotifier extends PluginNotifier {
|
class ViewPluginNotifier extends PluginNotifier<Option<DeletedViewPB>> {
|
||||||
final ViewListener? _viewListener;
|
final ViewListener? _viewListener;
|
||||||
ViewPB view;
|
ViewPB view;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final ValueNotifier<bool> isDeleted = ValueNotifier(false);
|
final ValueNotifier<Option<DeletedViewPB>> isDeleted = ValueNotifier(none());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final ValueNotifier<int> isDisplayChanged = ValueNotifier(0);
|
final ValueNotifier<int> isDisplayChanged = ValueNotifier(0);
|
||||||
@ -27,9 +28,7 @@ class ViewPluginNotifier extends PluginNotifier {
|
|||||||
);
|
);
|
||||||
}, onViewMoveToTrash: (result) {
|
}, onViewMoveToTrash: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(deletedView) {
|
(deletedView) => isDeleted.value = some(deletedView),
|
||||||
isDeleted.value = true;
|
|
||||||
},
|
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -32,9 +32,9 @@ abstract class Plugin<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class PluginNotifier {
|
abstract class PluginNotifier<T> {
|
||||||
/// Notify if the plugin get deleted
|
/// Notify if the plugin get deleted
|
||||||
ValueNotifier<bool> get isDeleted;
|
ValueNotifier<T> get isDeleted;
|
||||||
|
|
||||||
/// Notify if the [PluginDisplay]'s content was changed
|
/// Notify if the [PluginDisplay]'s content was changed
|
||||||
ValueNotifier<int> get isDisplayChanged;
|
ValueNotifier<int> get isDisplayChanged;
|
||||||
@ -67,7 +67,7 @@ abstract class PluginDisplay with NavigationItem {
|
|||||||
|
|
||||||
class PluginContext {
|
class PluginContext {
|
||||||
// calls when widget of the plugin get deleted
|
// calls when widget of the plugin get deleted
|
||||||
final Function(ViewPB) onDeleted;
|
final Function(ViewPB, int?) onDeleted;
|
||||||
|
|
||||||
PluginContext({required this.onDeleted});
|
PluginContext({required this.onDeleted});
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ typedef UpdateViewNotifiedValue = Either<ViewPB, FlowyError>;
|
|||||||
// Restore the view from trash
|
// Restore the view from trash
|
||||||
typedef RestoreViewNotifiedValue = Either<ViewPB, FlowyError>;
|
typedef RestoreViewNotifiedValue = Either<ViewPB, FlowyError>;
|
||||||
// Move the view to trash
|
// Move the view to trash
|
||||||
typedef MoveToTrashNotifiedValue = Either<ViewIdPB, FlowyError>;
|
typedef MoveToTrashNotifiedValue = Either<DeletedViewPB, FlowyError>;
|
||||||
|
|
||||||
class ViewListener {
|
class ViewListener {
|
||||||
StreamSubscription<SubscribeObject>? _subscription;
|
StreamSubscription<SubscribeObject>? _subscription;
|
||||||
@ -98,8 +98,8 @@ class ViewListener {
|
|||||||
break;
|
break;
|
||||||
case FolderNotification.ViewMoveToTrash:
|
case FolderNotification.ViewMoveToTrash:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) =>
|
(payload) => _moveToTrashNotifier.value =
|
||||||
_moveToTrashNotifier.value = left(ViewIdPB.fromBuffer(payload)),
|
left(DeletedViewPB.fromBuffer(payload)),
|
||||||
(error) => _moveToTrashNotifier.value = right(error),
|
(error) => _moveToTrashNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -251,14 +251,18 @@ class HomeScreenStackAdaptor extends HomeStackDelegate {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didDeleteStackWidget(ViewPB view) {
|
void didDeleteStackWidget(ViewPB view, int? index) {
|
||||||
final homeService = HomeService();
|
final homeService = HomeService();
|
||||||
homeService.readApp(appId: view.appId).then((result) {
|
homeService.readApp(appId: view.appId).then((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(appPB) {
|
(appPB) {
|
||||||
final List<ViewPB> views = appPB.belongings.items;
|
final List<ViewPB> views = appPB.belongings.items;
|
||||||
if (views.isNotEmpty) {
|
if (views.isNotEmpty) {
|
||||||
final lastView = views.last;
|
var lastView = views.last;
|
||||||
|
if (index != null && index != 0 && views.length > index - 1) {
|
||||||
|
lastView = views[index - 1];
|
||||||
|
}
|
||||||
|
|
||||||
final plugin = makePlugin(
|
final plugin = makePlugin(
|
||||||
pluginType: lastView.pluginType,
|
pluginType: lastView.pluginType,
|
||||||
data: lastView,
|
data: lastView,
|
||||||
|
@ -18,7 +18,7 @@ import 'home_layout.dart';
|
|||||||
typedef NavigationCallback = void Function(String id);
|
typedef NavigationCallback = void Function(String id);
|
||||||
|
|
||||||
abstract class HomeStackDelegate {
|
abstract class HomeStackDelegate {
|
||||||
void didDeleteStackWidget(ViewPB view);
|
void didDeleteStackWidget(ViewPB view, int? index);
|
||||||
}
|
}
|
||||||
|
|
||||||
class HomeStack extends StatelessWidget {
|
class HomeStack extends StatelessWidget {
|
||||||
@ -41,9 +41,11 @@ class HomeStack extends StatelessWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
color: theme.surface,
|
color: theme.surface,
|
||||||
child: FocusTraversalGroup(
|
child: FocusTraversalGroup(
|
||||||
child: getIt<HomeStackManager>().stackWidget(onDeleted: (view) {
|
child: getIt<HomeStackManager>().stackWidget(
|
||||||
delegate.didDeleteStackWidget(view);
|
onDeleted: (view, index) {
|
||||||
}),
|
delegate.didDeleteStackWidget(view, index);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -168,7 +170,7 @@ class HomeStackManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget stackWidget({required Function(ViewPB) onDeleted}) {
|
Widget stackWidget({required Function(ViewPB, int?) onDeleted}) {
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [ChangeNotifierProvider.value(value: _notifier)],
|
providers: [ChangeNotifierProvider.value(value: _notifier)],
|
||||||
child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) {
|
child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) {
|
||||||
|
@ -206,6 +206,15 @@ impl std::convert::From<&str> for ViewIdPB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, ProtoBuf, Clone, Debug)]
|
||||||
|
pub struct DeletedViewPB {
|
||||||
|
#[pb(index = 1)]
|
||||||
|
pub view_id: String,
|
||||||
|
|
||||||
|
#[pb(index = 2, one_of)]
|
||||||
|
pub index: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for ViewIdPB {
|
impl std::ops::Deref for ViewIdPB {
|
||||||
type Target = str;
|
type Target = str;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
pub use crate::entities::view::ViewDataTypePB;
|
pub use crate::entities::view::ViewDataTypePB;
|
||||||
use crate::entities::{ViewInfoPB, ViewLayoutTypePB};
|
use crate::entities::{DeletedViewPB, ViewInfoPB, ViewLayoutTypePB};
|
||||||
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
||||||
use crate::{
|
use crate::{
|
||||||
dart_notification::{send_dart_notification, FolderNotification},
|
dart_notification::{send_dart_notification, FolderNotification},
|
||||||
@ -122,12 +122,12 @@ impl ViewController {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, view_id), fields(view_id = %view_id.value), err)]
|
#[tracing::instrument(level = "debug", skip(self, view_id), err)]
|
||||||
pub(crate) async fn read_view(&self, view_id: ViewIdPB) -> Result<ViewRevision, FlowyError> {
|
pub(crate) async fn read_view(&self, view_id: &str) -> Result<ViewRevision, FlowyError> {
|
||||||
let view_rev = self
|
let view_rev = self
|
||||||
.persistence
|
.persistence
|
||||||
.begin_transaction(|transaction| {
|
.begin_transaction(|transaction| {
|
||||||
let view = transaction.read_view(&view_id.value)?;
|
let view = transaction.read_view(view_id)?;
|
||||||
let trash_ids = self.trash_controller.read_trash_ids(&transaction)?;
|
let trash_ids = self.trash_controller.read_trash_ids(&transaction)?;
|
||||||
if trash_ids.contains(&view.id) {
|
if trash_ids.contains(&view.id) {
|
||||||
return Err(FlowyError::record_not_found());
|
return Err(FlowyError::record_not_found());
|
||||||
@ -135,7 +135,6 @@ impl ViewController {
|
|||||||
Ok(view)
|
Ok(view)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
let _ = self.read_view_on_server(view_id);
|
|
||||||
Ok(view_rev)
|
Ok(view_rev)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,9 +200,26 @@ impl ViewController {
|
|||||||
let _ = KV::remove(LATEST_VIEW_ID);
|
let _ = KV::remove(LATEST_VIEW_ID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let view_id_pb = ViewIdPB::from(view_id.as_str());
|
|
||||||
|
let deleted_view = self
|
||||||
|
.persistence
|
||||||
|
.begin_transaction(|transaction| {
|
||||||
|
let view = transaction.read_view(&view_id)?;
|
||||||
|
let views = read_belonging_views_on_local(&view.app_id, self.trash_controller.clone(), &transaction)?;
|
||||||
|
|
||||||
|
let index = views
|
||||||
|
.iter()
|
||||||
|
.position(|view| view.id == view_id)
|
||||||
|
.and_then(|index| Some(index as i32));
|
||||||
|
Ok(DeletedViewPB {
|
||||||
|
view_id: view_id.clone(),
|
||||||
|
index,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
send_dart_notification(&view_id, FolderNotification::ViewMoveToTrash)
|
send_dart_notification(&view_id, FolderNotification::ViewMoveToTrash)
|
||||||
.payload(view_id_pb)
|
.payload(deleted_view)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
let processor = self.get_data_processor_from_view_id(&view_id).await?;
|
let processor = self.get_data_processor_from_view_id(&view_id).await?;
|
||||||
|
@ -31,7 +31,7 @@ pub(crate) async fn read_view_handler(
|
|||||||
controller: AppData<Arc<ViewController>>,
|
controller: AppData<Arc<ViewController>>,
|
||||||
) -> DataResult<ViewPB, FlowyError> {
|
) -> DataResult<ViewPB, FlowyError> {
|
||||||
let view_id: ViewIdPB = data.into_inner();
|
let view_id: ViewIdPB = data.into_inner();
|
||||||
let view_rev = controller.read_view(view_id.clone()).await?;
|
let view_rev = controller.read_view(&view_id.value).await?;
|
||||||
data_result(view_rev.into())
|
data_result(view_rev.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user