| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 | 
							- import 'package:app_flowy/generated/locale_keys.g.dart';
 
- import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
 
- import 'package:app_flowy/plugins/grid/application/filter/filter_menu_bloc.dart';
 
- import 'package:app_flowy/plugins/grid/application/grid_data_controller.dart';
 
- import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
 
- import 'package:app_flowy/plugins/grid/application/grid_bloc.dart';
 
- import 'package:easy_localization/easy_localization.dart';
 
- import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
 
- import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 
- import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
 
- import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart';
 
- import 'package:flowy_infra_ui/style_widget/text.dart';
 
- import 'package:flowy_infra_ui/widget/error_page.dart';
 
- import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 
- import 'package:flutter_bloc/flutter_bloc.dart';
 
- import 'package:flutter/material.dart';
 
- import 'package:linked_scroll_controller/linked_scroll_controller.dart';
 
- import '../application/row/row_cache.dart';
 
- import '../application/setting/setting_bloc.dart';
 
- import 'controller/grid_scroll.dart';
 
- import 'layout/layout.dart';
 
- import 'layout/sizes.dart';
 
- import 'widgets/cell/cell_builder.dart';
 
- import 'widgets/row/grid_row.dart';
 
- import 'widgets/footer/grid_footer.dart';
 
- import 'widgets/header/grid_header.dart';
 
- import 'widgets/row/row_detail.dart';
 
- import 'widgets/shortcuts.dart';
 
- import 'widgets/filter/menu.dart';
 
- import 'widgets/toolbar/grid_toolbar.dart';
 
- class GridPage extends StatefulWidget {
 
-   final ViewPB view;
 
-   final GridController gridController;
 
-   final VoidCallback? onDeleted;
 
-   GridPage({
 
-     required this.view,
 
-     this.onDeleted,
 
-     Key? key,
 
-   })  : gridController = GridController(view: view),
 
-         super(key: key);
 
-   @override
 
-   State<GridPage> createState() => _GridPageState();
 
- }
 
- class _GridPageState extends State<GridPage> {
 
-   @override
 
-   Widget build(BuildContext context) {
 
-     return MultiBlocProvider(
 
-       providers: [
 
-         BlocProvider<GridBloc>(
 
-           create: (context) => GridBloc(
 
-             view: widget.view,
 
-             gridController: widget.gridController,
 
-           )..add(const GridEvent.initial()),
 
-         ),
 
-         BlocProvider<GridFilterMenuBloc>(
 
-           create: (context) => GridFilterMenuBloc(
 
-             viewId: widget.view.id,
 
-             fieldController: widget.gridController.fieldController,
 
-           )..add(const GridFilterMenuEvent.initial()),
 
-         ),
 
-         BlocProvider<GridSettingBloc>(
 
-           create: (context) => GridSettingBloc(gridId: widget.view.id),
 
-         ),
 
-       ],
 
-       child: BlocBuilder<GridBloc, GridState>(
 
-         builder: (context, state) {
 
-           return state.loadingState.map(
 
-             loading: (_) =>
 
-                 const Center(child: CircularProgressIndicator.adaptive()),
 
-             finish: (result) => result.successOrFail.fold(
 
-               (_) => const GridShortcuts(child: FlowyGrid()),
 
-               (err) => FlowyErrorPage(err.toString()),
 
-             ),
 
-           );
 
-         },
 
-       ),
 
-     );
 
-   }
 
-   @override
 
-   void dispose() {
 
-     super.dispose();
 
-   }
 
-   @override
 
-   void deactivate() {
 
-     super.deactivate();
 
-   }
 
-   @override
 
-   void didUpdateWidget(covariant GridPage oldWidget) {
 
-     super.didUpdateWidget(oldWidget);
 
-   }
 
- }
 
- class FlowyGrid extends StatefulWidget {
 
-   const FlowyGrid({Key? key}) : super(key: key);
 
-   @override
 
-   State<FlowyGrid> createState() => _FlowyGridState();
 
- }
 
- class _FlowyGridState extends State<FlowyGrid> {
 
-   final _scrollController = GridScrollController(
 
-       scrollGroupController: LinkedScrollControllerGroup());
 
-   late ScrollController headerScrollController;
 
-   @override
 
-   void initState() {
 
-     headerScrollController = _scrollController.linkHorizontalController();
 
-     super.initState();
 
-   }
 
-   @override
 
-   void dispose() {
 
-     _scrollController.dispose();
 
-     super.dispose();
 
-   }
 
-   @override
 
-   Widget build(BuildContext context) {
 
-     return BlocBuilder<GridBloc, GridState>(
 
-       buildWhen: (previous, current) => previous.fields != current.fields,
 
-       builder: (context, state) {
 
-         final contentWidth = GridLayout.headerWidth(state.fields.value);
 
-         final child = _wrapScrollView(
 
-           contentWidth,
 
-           [
 
-             const _GridRows(),
 
-             const _GridFooter(),
 
-           ],
 
-         );
 
-         return Column(
 
-           crossAxisAlignment: CrossAxisAlignment.start,
 
-           children: [
 
-             const GridToolbar(),
 
-             const GridFilterMenu(),
 
-             _gridHeader(context, state.gridId),
 
-             Flexible(child: child),
 
-             const RowCountBadge(),
 
-           ],
 
-         );
 
-       },
 
-     );
 
-   }
 
-   Widget _wrapScrollView(
 
-     double contentWidth,
 
-     List<Widget> slivers,
 
-   ) {
 
-     final verticalScrollView = ScrollConfiguration(
 
-       behavior: const ScrollBehavior().copyWith(scrollbars: false),
 
-       child: CustomScrollView(
 
-         physics: StyledScrollPhysics(),
 
-         controller: _scrollController.verticalController,
 
-         slivers: slivers,
 
-       ),
 
-     );
 
-     final sizedVerticalScrollView = SizedBox(
 
-       width: contentWidth,
 
-       child: verticalScrollView,
 
-     );
 
-     final horizontalScrollView = StyledSingleChildScrollView(
 
-       controller: _scrollController.horizontalController,
 
-       axis: Axis.horizontal,
 
-       child: sizedVerticalScrollView,
 
-     );
 
-     return ScrollbarListStack(
 
-       axis: Axis.vertical,
 
-       controller: _scrollController.verticalController,
 
-       barSize: GridSize.scrollBarSize,
 
-       child: horizontalScrollView,
 
-     );
 
-   }
 
-   Widget _gridHeader(BuildContext context, String gridId) {
 
-     final fieldController =
 
-         context.read<GridBloc>().gridController.fieldController;
 
-     return GridHeaderSliverAdaptor(
 
-       gridId: gridId,
 
-       fieldController: fieldController,
 
-       anchorScrollController: headerScrollController,
 
-     );
 
-   }
 
- }
 
- class _GridRows extends StatefulWidget {
 
-   const _GridRows({Key? key}) : super(key: key);
 
-   @override
 
-   State<_GridRows> createState() => _GridRowsState();
 
- }
 
- class _GridRowsState extends State<_GridRows> {
 
-   final _key = GlobalKey<SliverAnimatedListState>();
 
-   @override
 
-   Widget build(BuildContext context) {
 
-     return BlocConsumer<GridBloc, GridState>(
 
-       listenWhen: (previous, current) => previous.reason != current.reason,
 
-       listener: (context, state) {
 
-         state.reason.whenOrNull(
 
-           insert: (item) {
 
-             _key.currentState?.insertItem(item.index);
 
-           },
 
-           delete: (item) {
 
-             _key.currentState?.removeItem(
 
-               item.index,
 
-               (context, animation) =>
 
-                   _renderRow(context, item.rowInfo, animation),
 
-             );
 
-           },
 
-         );
 
-       },
 
-       buildWhen: (previous, current) => false,
 
-       builder: (context, state) {
 
-         return SliverAnimatedList(
 
-           key: _key,
 
-           initialItemCount: context.read<GridBloc>().state.rowInfos.length,
 
-           itemBuilder:
 
-               (BuildContext context, int index, Animation<double> animation) {
 
-             final rowInfos = context.read<GridBloc>().state.rowInfos;
 
-             if (index >= rowInfos.length) {
 
-               return const SizedBox();
 
-             } else {
 
-               final RowInfo rowInfo = rowInfos[index];
 
-               return _renderRow(context, rowInfo, animation);
 
-             }
 
-           },
 
-         );
 
-       },
 
-     );
 
-   }
 
-   Widget _renderRow(
 
-     BuildContext context,
 
-     RowInfo rowInfo,
 
-     Animation<double> animation,
 
-   ) {
 
-     final rowCache = context.read<GridBloc>().getRowCache(
 
-           rowInfo.rowPB.blockId,
 
-           rowInfo.rowPB.id,
 
-         );
 
-     /// Return placeholder widget if the rowCache is null.
 
-     if (rowCache == null) return const SizedBox();
 
-     final fieldController =
 
-         context.read<GridBloc>().gridController.fieldController;
 
-     final dataController = GridRowDataController(
 
-       rowInfo: rowInfo,
 
-       fieldController: fieldController,
 
-       rowCache: rowCache,
 
-     );
 
-     return SizeTransition(
 
-       sizeFactor: animation,
 
-       child: GridRowWidget(
 
-         rowInfo: rowInfo,
 
-         dataController: dataController,
 
-         cellBuilder: GridCellBuilder(delegate: dataController),
 
-         openDetailPage: (context, cellBuilder) {
 
-           _openRowDetailPage(
 
-             context,
 
-             rowInfo,
 
-             fieldController,
 
-             rowCache,
 
-             cellBuilder,
 
-           );
 
-         },
 
-         key: ValueKey(rowInfo.rowPB.id),
 
-       ),
 
-     );
 
-   }
 
-   void _openRowDetailPage(
 
-     BuildContext context,
 
-     RowInfo rowInfo,
 
-     GridFieldController fieldController,
 
-     GridRowCache rowCache,
 
-     GridCellBuilder cellBuilder,
 
-   ) {
 
-     final dataController = GridRowDataController(
 
-       rowInfo: rowInfo,
 
-       fieldController: fieldController,
 
-       rowCache: rowCache,
 
-     );
 
-     FlowyOverlay.show(
 
-         context: context,
 
-         builder: (BuildContext context) {
 
-           return RowDetailPage(
 
-             cellBuilder: cellBuilder,
 
-             dataController: dataController,
 
-           );
 
-         });
 
-   }
 
- }
 
- class _GridFooter extends StatelessWidget {
 
-   const _GridFooter({Key? key}) : super(key: key);
 
-   @override
 
-   Widget build(BuildContext context) {
 
-     return SliverPadding(
 
-       padding: const EdgeInsets.only(bottom: 200),
 
-       sliver: SliverToBoxAdapter(
 
-         child: SizedBox(
 
-           height: GridSize.footerHeight,
 
-           child: Padding(
 
-             padding: GridSize.footerContentInsets,
 
-             child: const SizedBox(height: 40, child: GridAddRowButton()),
 
-           ),
 
-         ),
 
-       ),
 
-     );
 
-   }
 
- }
 
- class RowCountBadge extends StatelessWidget {
 
-   const RowCountBadge({Key? key}) : super(key: key);
 
-   @override
 
-   Widget build(BuildContext context) {
 
-     return BlocSelector<GridBloc, GridState, int>(
 
-       selector: (state) => state.rowCount,
 
-       builder: (context, rowCount) {
 
-         return Padding(
 
-           padding: GridSize.footerContentInsets,
 
-           child: Row(
 
-             mainAxisAlignment: MainAxisAlignment.start,
 
-             children: [
 
-               FlowyText.regular(
 
-                 '${LocaleKeys.grid_row_count.tr()} : ',
 
-                 fontSize: 13,
 
-                 color: Theme.of(context).hintColor,
 
-               ),
 
-               FlowyText.regular(rowCount.toString(), fontSize: 13),
 
-             ],
 
-           ),
 
-         );
 
-       },
 
-     );
 
-   }
 
- }
 
 
  |