From 321682717cbe4f01ca362331792d4f0dd12a62c1 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 9 Mar 2022 12:11:27 +0800 Subject: [PATCH] chore: opti row rebuild --- .../lib/workspace/application/grid/data.dart | 14 +- .../workspace/application/grid/row_bloc.dart | 23 +-- .../plugins/grid/src/grid_page.dart | 2 +- .../src/widgets/content/cell_container.dart | 13 +- .../grid/src/widgets/content/grid_row.dart | 133 ++++++++++-------- .../grid/src/widgets/header/header_cell.dart | 4 - 6 files changed, 105 insertions(+), 84 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/data.dart b/frontend/app_flowy/lib/workspace/application/grid/data.dart index b0e260fe8e..c32f87f1a2 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/data.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/data.dart @@ -1,4 +1,5 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:equatable/equatable.dart'; class GridInfo { List rows; @@ -23,15 +24,18 @@ class GridInfo { } } -class GridRowData { - Row row; - List fields; - Map cellMap; - GridRowData({ +class GridRowData extends Equatable { + final Row row; + final List fields; + final Map cellMap; + const GridRowData({ required this.row, required this.fields, required this.cellMap, }); + + @override + List get props => [row.hashCode, cellMap]; } class GridColumnData { diff --git a/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart index 8feb26e4c7..9af22beba9 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row_bloc.dart @@ -1,6 +1,5 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:dartz/dartz.dart'; import 'dart:async'; import 'data.dart'; import 'row_service.dart'; @@ -9,18 +8,18 @@ part 'row_bloc.freezed.dart'; class RowBloc extends Bloc { final RowService service; - final GridRowData data; - RowBloc({required this.data, required this.service}) : super(RowState.initial()) { + RowBloc({required GridRowData data, required this.service}) : super(RowState.initial(data)) { on( (event, emit) async { await event.map( initial: (_InitialRow value) async {}, createRow: (_CreateRow value) {}, - highlightRow: (_HighlightRow value) { - emit(state.copyWith( - isHighlight: value.rowId.fold(() => false, (rowId) => rowId == data.row.id), - )); + activeRow: (_ActiveRow value) { + emit(state.copyWith(active: true)); + }, + disactiveRow: (_DisactiveRow value) { + emit(state.copyWith(active: false)); }, ); }, @@ -35,16 +34,18 @@ class RowBloc extends Bloc { @freezed abstract class RowEvent with _$RowEvent { - const factory RowEvent.initial() = _InitialRow; + const factory RowEvent.initial(GridRowData data) = _InitialRow; const factory RowEvent.createRow() = _CreateRow; - const factory RowEvent.highlightRow(Option rowId) = _HighlightRow; + const factory RowEvent.activeRow() = _ActiveRow; + const factory RowEvent.disactiveRow() = _DisactiveRow; } @freezed abstract class RowState with _$RowState { const factory RowState({ - required bool isHighlight, + required GridRowData data, + required bool active, }) = _RowState; - factory RowState.initial() => const RowState(isHighlight: false); + factory RowState.initial(GridRowData data) => RowState(data: data, active: false); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index ba89c63662..7435ea0e5f 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -139,7 +139,7 @@ class _GridBodyState extends State { delegate: SliverChildBuilderDelegate( (context, index) { final data = gridInfo.rowAtIndex(index); - return RepaintBoundary(child: GridRowWidget(data)); + return RepaintBoundary(child: GridRowWidget(data: data)); }, childCount: gridInfo.numberOfRows(), ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart index 0fbdc3b53c..56cc4e174f 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart @@ -1,9 +1,10 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -class CellContainer extends StatelessWidget { +class CellContainer extends StatefulWidget { final Widget child; final double width; const CellContainer({ @@ -12,23 +13,27 @@ class CellContainer extends StatelessWidget { required this.width, }) : super(key: key); + @override + State createState() => _CellContainerState(); +} + +class _CellContainerState extends State { @override Widget build(BuildContext context) { final theme = context.watch(); final borderSide = BorderSide(color: theme.shader4, width: 0.4); - return GestureDetector( behavior: HitTestBehavior.translucent, onTap: () {}, child: Container( constraints: BoxConstraints( - maxWidth: width, + maxWidth: widget.width, ), decoration: BoxDecoration( border: Border(right: borderSide, bottom: borderSide), ), padding: GridSize.cellContentInsets, - child: Center(child: IntrinsicHeight(child: child)), + child: Center(child: IntrinsicHeight(child: widget.child)), ), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart index 3e43d4fd8d..dce4b61d4f 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart @@ -8,88 +8,103 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; import 'cell_container.dart'; -import 'grid_cell.dart'; -import 'package:dartz/dartz.dart'; -class GridRowWidget extends StatelessWidget { +class GridRowWidget extends StatefulWidget { final GridRowData data; - final Function(bool)? onHoverChange; - const GridRowWidget(this.data, {Key? key, this.onHoverChange}) : super(key: key); + GridRowWidget({required this.data, Key? key}) : super(key: ObjectKey(data.row.id)); + + @override + State createState() => _GridRowWidgetState(); +} + +class _GridRowWidgetState extends State { + late RowBloc _rowBloc; + + @override + void initState() { + _rowBloc = getIt(param1: widget.data); + super.initState(); + } @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(param1: data), - child: BlocBuilder( - builder: (context, state) { - return GestureDetector( - behavior: HitTestBehavior.translucent, - child: MouseRegion( - cursor: SystemMouseCursors.click, - onEnter: (p) => context.read().add(RowEvent.highlightRow(some(data.row.id))), - onExit: (p) => context.read().add(RowEvent.highlightRow(none())), - child: SizedBox( - height: data.row.height.toDouble(), - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: _buildCells(), - ), - ), + return BlocProvider.value( + value: _rowBloc, + child: GestureDetector( + behavior: HitTestBehavior.translucent, + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (p) => _rowBloc.add(const RowEvent.activeRow()), + onExit: (p) => _rowBloc.add(const RowEvent.disactiveRow()), + child: SizedBox( + height: _rowBloc.state.data.row.height.toDouble(), + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const LeadingRow(), + _buildCells(), + const TrailingRow(), + ], ), - ); - }, + ), + ), ), ); } - List _buildCells() { - return [ - SizedBox( - width: GridSize.leadingHeaderPadding, - child: LeadingRow(rowId: data.row.id), - ), - ...data.fields.map( - (field) { - final cellData = data.cellMap[field.id]; - return CellContainer( - width: field.width.toDouble(), - child: GridCellBuilder.buildCell(field, cellData), - ); - }, - ), - SizedBox( - width: GridSize.trailHeaderPadding, - child: TrailingRow(rowId: data.row.id), - ) - ].toList(); + @override + Future dispose() async { + _rowBloc.close(); + super.dispose(); + } + + Widget _buildCells() { + return BlocBuilder( + buildWhen: (p, c) => p.data != c.data, + builder: (context, state) { + return Row( + key: ValueKey(state.data.row.id), + children: state.data.fields.map( + (field) { + final cellData = state.data.cellMap[field.id]; + return CellContainer( + width: field.width.toDouble(), + child: GridCellBuilder.buildCell(field, cellData), + ); + }, + ).toList(), + ); + }, + ); } } class LeadingRow extends StatelessWidget { - final String rowId; - const LeadingRow({required this.rowId, Key? key}) : super(key: key); + const LeadingRow({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state.isHighlight) { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - CreateRowButton(), - ], - ); - } - return const SizedBox.expand(); + return BlocSelector( + selector: (state) => state.active, + builder: (context, isActive) { + return SizedBox( + width: GridSize.leadingHeaderPadding, + child: isActive + ? Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + CreateRowButton(), + ], + ) + : null, + ); }, ); } } class TrailingRow extends StatelessWidget { - final String rowId; - const TrailingRow({required this.rowId, Key? key}) : super(key: key); + const TrailingRow({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart index 9b77af4b3e..aacdcd251e 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/header_cell.dart @@ -18,10 +18,6 @@ class HeaderCell extends StatelessWidget { hoverColor: theme.hover, onTap: () {}, ); - // return Text( - // field.name, - // style: const TextStyle(fontSize: 15.0, color: Colors.black), - // ); } }