fix: open row as full page launch review issues (#5254)

* perf: improve getting database speed

* fix: navigate to incorrect origin database view from full-width row

* fix: import row detail page action placement
This commit is contained in:
Richard Shiue
2024-05-02 22:00:35 +08:00
committed by GitHub
parent 813d024810
commit 2eb88821ca
6 changed files with 131 additions and 113 deletions

View File

@ -68,9 +68,8 @@ class DatabaseCallbacks {
} }
class DatabaseController { class DatabaseController {
DatabaseController({required ViewPB view}) DatabaseController({required this.view})
: viewId = view.id, : _databaseViewBackendSvc = DatabaseViewBackendService(viewId: view.id),
_databaseViewBackendSvc = DatabaseViewBackendService(viewId: view.id),
fieldController = FieldController(viewId: view.id), fieldController = FieldController(viewId: view.id),
_groupListener = DatabaseGroupListener(view.id), _groupListener = DatabaseGroupListener(view.id),
databaseLayout = databaseLayoutFromViewLayout(view.layout), databaseLayout = databaseLayoutFromViewLayout(view.layout),
@ -86,7 +85,7 @@ class DatabaseController {
_listenOnLayoutChanged(); _listenOnLayoutChanged();
} }
final String viewId; final ViewPB view;
final DatabaseViewBackendService _databaseViewBackendSvc; final DatabaseViewBackendService _databaseViewBackendSvc;
final FieldController fieldController; final FieldController fieldController;
DatabaseLayoutPB databaseLayout; DatabaseLayoutPB databaseLayout;
@ -100,6 +99,7 @@ class DatabaseController {
// Getters // Getters
RowCache get rowCache => _viewCache.rowCache; RowCache get rowCache => _viewCache.rowCache;
String get viewId => view.id;
// Listener // Listener
final DatabaseGroupListener _groupListener; final DatabaseGroupListener _groupListener;

View File

@ -3,7 +3,6 @@ import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_result/appflowy_result.dart'; import 'package:appflowy_result/appflowy_result.dart';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:collection/collection.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import '../database_controller.dart'; import '../database_controller.dart';
@ -67,13 +66,10 @@ class RelatedRowDetailPageBloc
/// 2. use the `inline_view_id` to instantiate a `DatabaseController`. /// 2. use the `inline_view_id` to instantiate a `DatabaseController`.
/// 3. use the `row_id` with the DatabaseController` to create `RowController` /// 3. use the `row_id` with the DatabaseController` to create `RowController`
void _init(String databaseId, String initialRowId) async { void _init(String databaseId, String initialRowId) async {
final databaseMeta = await DatabaseEventGetDatabases() final databaseMeta =
.send() await DatabaseEventGetDatabaseMeta(DatabaseIdPB(value: databaseId))
.fold<DatabaseMetaPB?>( .send()
(s) => s.items .fold<DatabaseMetaPB?>((s) => s, (f) => null);
.firstWhereOrNull((metaPB) => metaPB.databaseId == databaseId),
(f) => null,
);
if (databaseMeta == null) { if (databaseMeta == null) {
return; return;
} }

View File

@ -1,26 +1,19 @@
import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart'; import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'; import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/field/field_controller.dart'; import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/application/row/row_banner_bloc.dart'; import 'package:appflowy/plugins/database/application/row/row_banner_bloc.dart';
import 'package:appflowy/plugins/database/application/row/row_controller.dart'; import 'package:appflowy/plugins/database/application/row/row_controller.dart';
import 'package:appflowy/plugins/database/domain/database_view_service.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart'; import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_skeleton/text.dart'; import 'package:appflowy/plugins/database/widgets/cell/editable_cell_skeleton/text.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart'; import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/row_action.dart'; import 'package:appflowy/plugins/database/widgets/row/row_action.dart';
import 'package:appflowy/plugins/database_document/database_document_plugin.dart';
import 'package:appflowy/startup/plugin/plugin.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart'; import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart';
import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
const _kBannerActionHeight = 40.0; const _kBannerActionHeight = 40.0;
@ -28,13 +21,13 @@ const _kBannerActionHeight = 40.0;
class RowBanner extends StatefulWidget { class RowBanner extends StatefulWidget {
const RowBanner({ const RowBanner({
super.key, super.key,
required this.fieldController, required this.databaseController,
required this.rowController, required this.rowController,
required this.cellBuilder, required this.cellBuilder,
this.allowOpenAsFullPage = true, this.allowOpenAsFullPage = true,
}); });
final FieldController fieldController; final DatabaseController databaseController;
final RowController rowController; final RowController rowController;
final EditableCellBuilder cellBuilder; final EditableCellBuilder cellBuilder;
final bool allowOpenAsFullPage; final bool allowOpenAsFullPage;
@ -58,77 +51,32 @@ class _RowBannerState extends State<RowBanner> {
return BlocProvider<RowBannerBloc>( return BlocProvider<RowBannerBloc>(
create: (context) => RowBannerBloc( create: (context) => RowBannerBloc(
viewId: widget.rowController.viewId, viewId: widget.rowController.viewId,
fieldController: widget.fieldController, fieldController: widget.databaseController.fieldController,
rowMeta: widget.rowController.rowMeta, rowMeta: widget.rowController.rowMeta,
)..add(const RowBannerEvent.initial()), )..add(const RowBannerEvent.initial()),
child: MouseRegion( child: MouseRegion(
onEnter: (event) => _isHovering.value = true, onEnter: (event) => _isHovering.value = true,
onExit: (event) => _isHovering.value = false, onExit: (event) => _isHovering.value = false,
child: Stack( child: Padding(
children: [ padding: const EdgeInsets.fromLTRB(60, 34, 60, 0),
Padding( child: Column(
padding: const EdgeInsets.fromLTRB(60, 34, 60, 0), crossAxisAlignment: CrossAxisAlignment.start,
child: Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, SizedBox(
children: [ height: 30,
SizedBox( child: _BannerAction(
height: 30, isHovering: _isHovering,
child: _BannerAction( popoverController: popoverController,
isHovering: _isHovering,
popoverController: popoverController,
),
),
const VSpace(4),
_BannerTitle(
cellBuilder: widget.cellBuilder,
popoverController: popoverController,
rowController: widget.rowController,
),
],
),
),
Positioned(
top: 12,
right: 12,
child: RowActionButton(rowController: widget.rowController),
),
if (widget.allowOpenAsFullPage)
Positioned(
top: 12,
left: 12,
child: FlowyIconButton(
width: 20,
height: 20,
icon: const FlowySvg(FlowySvgs.full_view_s),
onPressed: () async {
Navigator.of(context).pop();
final viewBloc = context.read<ViewBloc>();
final databaseId = await DatabaseViewBackendService(
viewId: widget.cellBuilder.databaseController.viewId,
)
.getDatabaseId()
.then((value) => value.fold((s) => s, (f) => null));
final documentId = widget.rowController.rowMeta.documentId;
if (databaseId != null) {
getIt<TabsBloc>().add(
TabsEvent.openPlugin(
plugin: DatabaseDocumentPlugin(
data: DatabaseDocumentContext(
view: viewBloc.state.view,
databaseId: databaseId,
rowId: widget.rowController.rowId,
documentId: documentId,
),
pluginType: PluginType.databaseDocument,
),
setLatest: false,
),
);
}
},
), ),
), ),
], const VSpace(4),
_BannerTitle(
cellBuilder: widget.cellBuilder,
popoverController: popoverController,
rowController: widget.rowController,
),
],
),
), ),
), ),
); );

View File

@ -1,12 +1,16 @@
import 'package:flutter/material.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart'; import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/application/row/row_controller.dart'; import 'package:appflowy/plugins/database/application/row/row_controller.dart';
import 'package:appflowy/plugins/database/domain/database_view_service.dart';
import 'package:appflowy/plugins/database/grid/application/row/row_detail_bloc.dart'; import 'package:appflowy/plugins/database/grid/application/row/row_detail_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/row_document.dart'; import 'package:appflowy/plugins/database/widgets/row/row_document.dart';
import 'package:appflowy/plugins/database_document/database_document_plugin.dart';
import 'package:appflowy/startup/plugin/plugin.dart';
import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/reminder/reminder_bloc.dart'; import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../cell/editable_cell_builder.dart'; import '../cell/editable_cell_builder.dart';
@ -55,37 +59,87 @@ class _RowDetailPageState extends State<RowDetailPage> {
), ),
BlocProvider.value(value: getIt<ReminderBloc>()), BlocProvider.value(value: getIt<ReminderBloc>()),
], ],
child: ListView( child: Stack(
controller: scrollController,
children: [ children: [
RowBanner( ListView(
fieldController: widget.databaseController.fieldController, controller: scrollController,
rowController: widget.rowController, children: [
cellBuilder: cellBuilder, RowBanner(
allowOpenAsFullPage: widget.allowOpenAsFullPage, databaseController: widget.databaseController,
rowController: widget.rowController,
cellBuilder: cellBuilder,
allowOpenAsFullPage: widget.allowOpenAsFullPage,
),
const VSpace(16),
Padding(
padding: const EdgeInsets.only(left: 40, right: 60),
child: RowPropertyList(
cellBuilder: cellBuilder,
viewId: widget.databaseController.viewId,
fieldController: widget.databaseController.fieldController,
),
),
const VSpace(20),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 60),
child: Divider(height: 1.0),
),
const VSpace(20),
RowDocument(
viewId: widget.rowController.viewId,
rowId: widget.rowController.rowId,
),
],
), ),
const VSpace(16), Positioned(
Padding( top: 12,
padding: const EdgeInsets.only(left: 40, right: 60), right: 12,
child: RowPropertyList( child: Row(
cellBuilder: cellBuilder, children: _actions(context),
viewId: widget.databaseController.viewId,
fieldController: widget.databaseController.fieldController,
), ),
), ),
const VSpace(20),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 60),
child: Divider(height: 1.0),
),
const VSpace(20),
RowDocument(
viewId: widget.rowController.viewId,
rowId: widget.rowController.rowId,
),
], ],
), ),
), ),
); );
} }
List<Widget> _actions(BuildContext context) {
return [
if (widget.allowOpenAsFullPage) ...[
FlowyIconButton(
width: 20,
height: 20,
icon: const FlowySvg(FlowySvgs.full_view_s),
onPressed: () async {
Navigator.of(context).pop();
final databaseId = await DatabaseViewBackendService(
viewId: widget.databaseController.viewId,
)
.getDatabaseId()
.then((value) => value.fold((s) => s, (f) => null));
final documentId = widget.rowController.rowMeta.documentId;
if (databaseId != null) {
getIt<TabsBloc>().add(
TabsEvent.openPlugin(
plugin: DatabaseDocumentPlugin(
data: DatabaseDocumentContext(
view: widget.databaseController.view,
databaseId: databaseId,
rowId: widget.rowController.rowId,
documentId: documentId,
),
pluginType: PluginType.databaseDocument,
),
setLatest: false,
),
);
}
},
),
const HSpace(4),
],
RowActionButton(rowController: widget.rowController),
];
}
} }

View File

@ -738,6 +738,22 @@ pub(crate) async fn delete_group_handler(
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(manager), err)]
pub(crate) async fn get_database_meta_handler(
data: AFPluginData<DatabaseIdPB>,
manager: AFPluginState<Weak<DatabaseManager>>,
) -> DataResult<DatabaseMetaPB, FlowyError> {
let manager = upgrade_manager(manager)?;
let database_id = data.into_inner().value;
let inline_view_id = manager.get_database_inline_view_id(&database_id).await?;
let data = DatabaseMetaPB {
database_id,
inline_view_id,
};
data_result_ok(data)
}
#[tracing::instrument(level = "debug", skip(manager), err)] #[tracing::instrument(level = "debug", skip(manager), err)]
pub(crate) async fn get_databases_handler( pub(crate) async fn get_databases_handler(
manager: AFPluginState<Weak<DatabaseManager>>, manager: AFPluginState<Weak<DatabaseManager>>,

View File

@ -62,6 +62,7 @@ pub fn init(database_manager: Weak<DatabaseManager>) -> AFPlugin {
.event(DatabaseEvent::CreateGroup, create_group_handler) .event(DatabaseEvent::CreateGroup, create_group_handler)
.event(DatabaseEvent::DeleteGroup, delete_group_handler) .event(DatabaseEvent::DeleteGroup, delete_group_handler)
// Database // Database
.event(DatabaseEvent::GetDatabaseMeta, get_database_meta_handler)
.event(DatabaseEvent::GetDatabases, get_databases_handler) .event(DatabaseEvent::GetDatabases, get_databases_handler)
// Calendar // Calendar
.event(DatabaseEvent::GetAllCalendarEvents, get_calendar_events_handler) .event(DatabaseEvent::GetAllCalendarEvents, get_calendar_events_handler)
@ -292,6 +293,9 @@ pub enum DatabaseEvent {
#[event(input = "DeleteGroupPayloadPB")] #[event(input = "DeleteGroupPayloadPB")]
DeleteGroup = 115, DeleteGroup = 115,
#[event(input = "DatabaseIdPB", output = "DatabaseMetaPB")]
GetDatabaseMeta = 119,
/// Returns all the databases /// Returns all the databases
#[event(output = "RepeatedDatabaseDescriptionPB")] #[event(output = "RepeatedDatabaseDescriptionPB")]
GetDatabases = 120, GetDatabases = 120,