mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-10-31 01:54:37 +00:00 
			
		
		
		
	chore: add card container
This commit is contained in:
		
							parent
							
								
									2282aa948e
								
							
						
					
					
						commit
						28e77ae68c
					
				| @ -108,8 +108,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   List<BoardColumnItem> _buildRows(List<RowPB> rows) { |   List<AFColumnItem> _buildRows(List<RowPB> rows) { | ||||||
|     return rows.map((row) { |     final items = rows.map((row) { | ||||||
|       // final rowInfo = RowInfo( |       // final rowInfo = RowInfo( | ||||||
|       //   gridId: _dataController.gridId, |       //   gridId: _dataController.gridId, | ||||||
|       //   blockId: row.blockId, |       //   blockId: row.blockId, | ||||||
| @ -120,6 +120,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> { | |||||||
|       // ); |       // ); | ||||||
|       return BoardColumnItem(row: row); |       return BoardColumnItem(row: row); | ||||||
|     }).toList(); |     }).toList(); | ||||||
|  | 
 | ||||||
|  |     return <AFColumnItem>[...items]; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Future<void> _loadGrid(Emitter<BoardState> emit) async { |   Future<void> _loadGrid(Emitter<BoardState> emit) async { | ||||||
|  | |||||||
| @ -0,0 +1,71 @@ | |||||||
|  | import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; | ||||||
|  | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||||
|  | import 'package:freezed_annotation/freezed_annotation.dart'; | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
|  | part 'board_checkbox_cell_bloc.freezed.dart'; | ||||||
|  | 
 | ||||||
|  | class BoardCheckboxCellBloc | ||||||
|  |     extends Bloc<BoardCheckboxCellEvent, BoardCheckboxCellState> { | ||||||
|  |   final GridCheckboxCellController cellController; | ||||||
|  |   void Function()? _onCellChangedFn; | ||||||
|  |   BoardCheckboxCellBloc({ | ||||||
|  |     required this.cellController, | ||||||
|  |   }) : super(BoardCheckboxCellState.initial(cellController)) { | ||||||
|  |     on<BoardCheckboxCellEvent>( | ||||||
|  |       (event, emit) async { | ||||||
|  |         await event.when( | ||||||
|  |           initial: () async { | ||||||
|  |             _startListening(); | ||||||
|  |           }, | ||||||
|  |           didReceiveCellUpdate: (cellData) { | ||||||
|  |             emit(state.copyWith(isSelected: _isSelected(cellData))); | ||||||
|  |           }, | ||||||
|  |         ); | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> close() async { | ||||||
|  |     if (_onCellChangedFn != null) { | ||||||
|  |       cellController.removeListener(_onCellChangedFn!); | ||||||
|  |       _onCellChangedFn = null; | ||||||
|  |     } | ||||||
|  |     cellController.dispose(); | ||||||
|  |     return super.close(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _startListening() { | ||||||
|  |     _onCellChangedFn = cellController.startListening( | ||||||
|  |       onCellChanged: ((cellContent) { | ||||||
|  |         if (!isClosed) { | ||||||
|  |           add(BoardCheckboxCellEvent.didReceiveCellUpdate(cellContent ?? "")); | ||||||
|  |         } | ||||||
|  |       }), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @freezed | ||||||
|  | class BoardCheckboxCellEvent with _$BoardCheckboxCellEvent { | ||||||
|  |   const factory BoardCheckboxCellEvent.initial() = _InitialCell; | ||||||
|  |   const factory BoardCheckboxCellEvent.didReceiveCellUpdate( | ||||||
|  |       String cellContent) = _DidReceiveCellUpdate; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @freezed | ||||||
|  | class BoardCheckboxCellState with _$BoardCheckboxCellState { | ||||||
|  |   const factory BoardCheckboxCellState({ | ||||||
|  |     required bool isSelected, | ||||||
|  |   }) = _CheckboxCellState; | ||||||
|  | 
 | ||||||
|  |   factory BoardCheckboxCellState.initial(GridCellController context) { | ||||||
|  |     return BoardCheckboxCellState( | ||||||
|  |         isSelected: _isSelected(context.getCellData())); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool _isSelected(String? cellData) { | ||||||
|  |   return cellData == "Yes"; | ||||||
|  | } | ||||||
| @ -0,0 +1,78 @@ | |||||||
|  | import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; | ||||||
|  | import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option_entities.pb.dart'; | ||||||
|  | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||||
|  | import 'package:freezed_annotation/freezed_annotation.dart'; | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
|  | part 'board_url_cell_bloc.freezed.dart'; | ||||||
|  | 
 | ||||||
|  | class BoardURLCellBloc extends Bloc<BoardURLCellEvent, BoardURLCellState> { | ||||||
|  |   final GridURLCellController cellController; | ||||||
|  |   void Function()? _onCellChangedFn; | ||||||
|  |   BoardURLCellBloc({ | ||||||
|  |     required this.cellController, | ||||||
|  |   }) : super(BoardURLCellState.initial(cellController)) { | ||||||
|  |     on<BoardURLCellEvent>( | ||||||
|  |       (event, emit) async { | ||||||
|  |         event.when( | ||||||
|  |           initial: () { | ||||||
|  |             _startListening(); | ||||||
|  |           }, | ||||||
|  |           didReceiveCellUpdate: (cellData) { | ||||||
|  |             emit(state.copyWith( | ||||||
|  |               content: cellData?.content ?? "", | ||||||
|  |               url: cellData?.url ?? "", | ||||||
|  |             )); | ||||||
|  |           }, | ||||||
|  |           updateURL: (String url) { | ||||||
|  |             cellController.saveCellData(url, deduplicate: true); | ||||||
|  |           }, | ||||||
|  |         ); | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> close() async { | ||||||
|  |     if (_onCellChangedFn != null) { | ||||||
|  |       cellController.removeListener(_onCellChangedFn!); | ||||||
|  |       _onCellChangedFn = null; | ||||||
|  |     } | ||||||
|  |     cellController.dispose(); | ||||||
|  |     return super.close(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _startListening() { | ||||||
|  |     _onCellChangedFn = cellController.startListening( | ||||||
|  |       onCellChanged: ((cellData) { | ||||||
|  |         if (!isClosed) { | ||||||
|  |           add(BoardURLCellEvent.didReceiveCellUpdate(cellData)); | ||||||
|  |         } | ||||||
|  |       }), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @freezed | ||||||
|  | class BoardURLCellEvent with _$BoardURLCellEvent { | ||||||
|  |   const factory BoardURLCellEvent.initial() = _InitialCell; | ||||||
|  |   const factory BoardURLCellEvent.updateURL(String url) = _UpdateURL; | ||||||
|  |   const factory BoardURLCellEvent.didReceiveCellUpdate(URLCellDataPB? cell) = | ||||||
|  |       _DidReceiveCellUpdate; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @freezed | ||||||
|  | class BoardURLCellState with _$BoardURLCellState { | ||||||
|  |   const factory BoardURLCellState({ | ||||||
|  |     required String content, | ||||||
|  |     required String url, | ||||||
|  |   }) = _BoardURLCellState; | ||||||
|  | 
 | ||||||
|  |   factory BoardURLCellState.initial(GridURLCellController context) { | ||||||
|  |     final cellData = context.getCellData(); | ||||||
|  |     return BoardURLCellState( | ||||||
|  |       content: cellData?.content ?? "", | ||||||
|  |       url: cellData?.url ?? "", | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -1,10 +1,12 @@ | |||||||
| import 'package:app_flowy/plugins/board/application/card/card_bloc.dart'; | import 'package:app_flowy/plugins/board/application/card/card_bloc.dart'; | ||||||
| import 'package:app_flowy/plugins/board/application/card/card_data_controller.dart'; | import 'package:app_flowy/plugins/board/application/card/card_data_controller.dart'; | ||||||
| import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; | import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; | ||||||
|  | import 'package:flowy_infra/image.dart'; | ||||||
|  | import 'package:flowy_infra/theme.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||||
| 
 |  | ||||||
| import 'card_cell_builder.dart'; | import 'card_cell_builder.dart'; | ||||||
|  | import 'card_container.dart'; | ||||||
| 
 | 
 | ||||||
| class BoardCard extends StatefulWidget { | class BoardCard extends StatefulWidget { | ||||||
|   final String gridId; |   final String gridId; | ||||||
| @ -40,8 +42,10 @@ class _BoardCardState extends State<BoardCard> { | |||||||
|       value: _cardBloc, |       value: _cardBloc, | ||||||
|       child: BlocBuilder<BoardCardBloc, BoardCardState>( |       child: BlocBuilder<BoardCardBloc, BoardCardState>( | ||||||
|         builder: (context, state) { |         builder: (context, state) { | ||||||
|           return Padding( |           return BoardCardContainer( | ||||||
|             padding: const EdgeInsets.all(8.0), |             accessoryBuilder: (context) { | ||||||
|  |               return [const _CardMoreOption()]; | ||||||
|  |             }, | ||||||
|             child: Column( |             child: Column( | ||||||
|               children: _makeCells(context, state.gridCellMap), |               children: _makeCells(context, state.gridCellMap), | ||||||
|             ), |             ), | ||||||
| @ -64,3 +68,17 @@ class _BoardCardState extends State<BoardCard> { | |||||||
|     ).toList(); |     ).toList(); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | class _CardMoreOption extends StatelessWidget with CardAccessory { | ||||||
|  |   const _CardMoreOption({Key? key}) : super(key: key); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return svgWidget('home/details', color: context.read<AppTheme>().iconColor); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void onTap(BuildContext context) { | ||||||
|  |     print('show options'); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | |||||||
| @ -0,0 +1,133 @@ | |||||||
|  | import 'package:flowy_infra/theme.dart'; | ||||||
|  | import 'package:flowy_infra_ui/style_widget/hover.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  | import 'package:styled_widget/styled_widget.dart'; | ||||||
|  | 
 | ||||||
|  | class BoardCardContainer extends StatelessWidget { | ||||||
|  |   final Widget child; | ||||||
|  |   final CardAccessoryBuilder? accessoryBuilder; | ||||||
|  |   const BoardCardContainer({ | ||||||
|  |     required this.child, | ||||||
|  |     this.accessoryBuilder, | ||||||
|  |     Key? key, | ||||||
|  |   }) : super(key: key); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return ChangeNotifierProvider( | ||||||
|  |       create: (_) => _CardContainerNotifier(), | ||||||
|  |       child: Consumer<_CardContainerNotifier>( | ||||||
|  |         builder: (context, notifier, _) { | ||||||
|  |           Widget container = Center(child: child); | ||||||
|  |           if (accessoryBuilder != null) { | ||||||
|  |             final accessories = accessoryBuilder!(context); | ||||||
|  |             if (accessories.isNotEmpty) { | ||||||
|  |               container = _CardEnterRegion( | ||||||
|  |                 child: container, | ||||||
|  |                 accessories: accessories, | ||||||
|  |               ); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |           return Padding( | ||||||
|  |             padding: const EdgeInsets.all(8), | ||||||
|  |             child: container, | ||||||
|  |           ); | ||||||
|  |         }, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class CardAccessory implements Widget { | ||||||
|  |   void onTap(BuildContext context); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | typedef CardAccessoryBuilder = List<CardAccessory> Function( | ||||||
|  |   BuildContext buildContext, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | class CardAccessoryContainer extends StatelessWidget { | ||||||
|  |   final List<CardAccessory> accessories; | ||||||
|  |   const CardAccessoryContainer({required this.accessories, Key? key}) | ||||||
|  |       : super(key: key); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     final theme = context.read<AppTheme>(); | ||||||
|  |     final children = accessories.map((accessory) { | ||||||
|  |       final hover = FlowyHover( | ||||||
|  |         style: HoverStyle( | ||||||
|  |           hoverColor: theme.hover, | ||||||
|  |           backgroundColor: theme.surface, | ||||||
|  |         ), | ||||||
|  |         builder: (_, onHover) => Container( | ||||||
|  |           width: 26, | ||||||
|  |           height: 26, | ||||||
|  |           padding: const EdgeInsets.all(3), | ||||||
|  |           child: accessory, | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  |       return GestureDetector( | ||||||
|  |         child: hover, | ||||||
|  |         behavior: HitTestBehavior.opaque, | ||||||
|  |         onTap: () => accessory.onTap(context), | ||||||
|  |       ); | ||||||
|  |     }).toList(); | ||||||
|  | 
 | ||||||
|  |     return Wrap(children: children, spacing: 6); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _CardEnterRegion extends StatelessWidget { | ||||||
|  |   final Widget child; | ||||||
|  |   final List<CardAccessory> accessories; | ||||||
|  |   const _CardEnterRegion( | ||||||
|  |       {required this.child, required this.accessories, Key? key}) | ||||||
|  |       : super(key: key); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Selector<_CardContainerNotifier, bool>( | ||||||
|  |       selector: (context, notifier) => notifier.onEnter, | ||||||
|  |       builder: (context, onEnter, _) { | ||||||
|  |         List<Widget> children = [child]; | ||||||
|  |         if (onEnter) { | ||||||
|  |           children.add(CardAccessoryContainer(accessories: accessories) | ||||||
|  |               .positioned(right: 0)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return MouseRegion( | ||||||
|  |           cursor: SystemMouseCursors.click, | ||||||
|  |           onEnter: (p) => | ||||||
|  |               Provider.of<_CardContainerNotifier>(context, listen: false) | ||||||
|  |                   .onEnter = true, | ||||||
|  |           onExit: (p) => | ||||||
|  |               Provider.of<_CardContainerNotifier>(context, listen: false) | ||||||
|  |                   .onEnter = false, | ||||||
|  |           child: IntrinsicHeight( | ||||||
|  |               child: Stack( | ||||||
|  |             alignment: AlignmentDirectional.center, | ||||||
|  |             fit: StackFit.expand, | ||||||
|  |             children: children, | ||||||
|  |           )), | ||||||
|  |         ); | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _CardContainerNotifier extends ChangeNotifier { | ||||||
|  |   bool _onEnter = false; | ||||||
|  | 
 | ||||||
|  |   _CardContainerNotifier(); | ||||||
|  | 
 | ||||||
|  |   set onEnter(bool value) { | ||||||
|  |     if (_onEnter != value) { | ||||||
|  |       _onEnter = value; | ||||||
|  |       notifyListeners(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   bool get onEnter => _onEnter; | ||||||
|  | } | ||||||
| @ -8,6 +8,8 @@ import 'package:styled_widget/styled_widget.dart'; | |||||||
| import 'package:app_flowy/generated/locale_keys.g.dart'; | import 'package:app_flowy/generated/locale_keys.g.dart'; | ||||||
| import 'package:easy_localization/easy_localization.dart'; | import 'package:easy_localization/easy_localization.dart'; | ||||||
| 
 | 
 | ||||||
|  | import 'cell_builder.dart'; | ||||||
|  | 
 | ||||||
| class GridCellAccessoryBuildContext { | class GridCellAccessoryBuildContext { | ||||||
|   final BuildContext anchorContext; |   final BuildContext anchorContext; | ||||||
|   final bool isCellEditing; |   final bool isCellEditing; | ||||||
| @ -57,18 +59,6 @@ class PrimaryCellAccessory extends StatelessWidget with GridCellAccessory { | |||||||
|   bool enable() => !isCellEditing; |   bool enable() => !isCellEditing; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| typedef AccessoryBuilder = List<GridCellAccessory> Function( |  | ||||||
|     GridCellAccessoryBuildContext buildContext); |  | ||||||
| 
 |  | ||||||
| abstract class CellAccessory extends Widget { |  | ||||||
|   const CellAccessory({Key? key}) : super(key: key); |  | ||||||
| 
 |  | ||||||
|   // The hover will show if the isHover's value is true |  | ||||||
|   ValueNotifier<bool>? get onAccessoryHover; |  | ||||||
| 
 |  | ||||||
|   AccessoryBuilder? get accessoryBuilder; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| class AccessoryHover extends StatefulWidget { | class AccessoryHover extends StatefulWidget { | ||||||
|   final CellAccessory child; |   final CellAccessory child; | ||||||
|   final EdgeInsets contentPadding; |   final EdgeInsets contentPadding; | ||||||
|  | |||||||
| @ -94,6 +94,18 @@ abstract class CellEditable { | |||||||
|   ValueNotifier<bool> get onCellEditing; |   ValueNotifier<bool> get onCellEditing; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | typedef AccessoryBuilder = List<GridCellAccessory> Function( | ||||||
|  |     GridCellAccessoryBuildContext buildContext); | ||||||
|  | 
 | ||||||
|  | abstract class CellAccessory extends Widget { | ||||||
|  |   const CellAccessory({Key? key}) : super(key: key); | ||||||
|  | 
 | ||||||
|  |   // The hover will show if the isHover's value is true | ||||||
|  |   ValueNotifier<bool>? get onAccessoryHover; | ||||||
|  | 
 | ||||||
|  |   AccessoryBuilder? get accessoryBuilder; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| abstract class GridCellWidget extends StatefulWidget | abstract class GridCellWidget extends StatefulWidget | ||||||
|     implements CellAccessory, CellEditable, CellShortcuts { |     implements CellAccessory, CellEditable, CellShortcuts { | ||||||
|   GridCellWidget({Key? key}) : super(key: key) { |   GridCellWidget({Key? key}) : super(key: key) { | ||||||
|  | |||||||
| @ -25,24 +25,28 @@ class CellContainer extends StatelessWidget { | |||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return ChangeNotifierProxyProvider<RegionStateNotifier, |     return ChangeNotifierProxyProvider<RegionStateNotifier, | ||||||
|         CellContainerNotifier>( |         _CellContainerNotifier>( | ||||||
|       create: (_) => CellContainerNotifier(child), |       create: (_) => _CellContainerNotifier(child), | ||||||
|       update: (_, rowStateNotifier, cellStateNotifier) => |       update: (_, rowStateNotifier, cellStateNotifier) => | ||||||
|           cellStateNotifier!..onEnter = rowStateNotifier.onEnter, |           cellStateNotifier!..onEnter = rowStateNotifier.onEnter, | ||||||
|       child: Selector<CellContainerNotifier, bool>( |       child: Selector<_CellContainerNotifier, bool>( | ||||||
|         selector: (context, notifier) => notifier.isFocus, |         selector: (context, notifier) => notifier.isFocus, | ||||||
|         builder: (context, isFocus, _) { |         builder: (context, isFocus, _) { | ||||||
|           Widget container = Center(child: GridCellShortcuts(child: child)); |           Widget container = Center(child: GridCellShortcuts(child: child)); | ||||||
| 
 | 
 | ||||||
|           if (accessoryBuilder != null) { |           if (accessoryBuilder != null) { | ||||||
|             final accessories = accessoryBuilder!(GridCellAccessoryBuildContext( |             final accessories = accessoryBuilder!( | ||||||
|  |               GridCellAccessoryBuildContext( | ||||||
|                 anchorContext: context, |                 anchorContext: context, | ||||||
|                 isCellEditing: isFocus, |                 isCellEditing: isFocus, | ||||||
|             )); |               ), | ||||||
|  |             ); | ||||||
| 
 | 
 | ||||||
|             if (accessories.isNotEmpty) { |             if (accessories.isNotEmpty) { | ||||||
|               container = |               container = _GridCellEnterRegion( | ||||||
|                   CellEnterRegion(child: container, accessories: accessories); |                 child: container, | ||||||
|  |                 accessories: accessories, | ||||||
|  |               ); | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
| @ -74,16 +78,16 @@ class CellContainer extends StatelessWidget { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class CellEnterRegion extends StatelessWidget { | class _GridCellEnterRegion extends StatelessWidget { | ||||||
|   final Widget child; |   final Widget child; | ||||||
|   final List<GridCellAccessory> accessories; |   final List<GridCellAccessory> accessories; | ||||||
|   const CellEnterRegion( |   const _GridCellEnterRegion( | ||||||
|       {required this.child, required this.accessories, Key? key}) |       {required this.child, required this.accessories, Key? key}) | ||||||
|       : super(key: key); |       : super(key: key); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return Selector<CellContainerNotifier, bool>( |     return Selector<_CellContainerNotifier, bool>( | ||||||
|       selector: (context, notifier) => notifier.onEnter, |       selector: (context, notifier) => notifier.onEnter, | ||||||
|       builder: (context, onEnter, _) { |       builder: (context, onEnter, _) { | ||||||
|         List<Widget> children = [child]; |         List<Widget> children = [child]; | ||||||
| @ -95,10 +99,10 @@ class CellEnterRegion extends StatelessWidget { | |||||||
|         return MouseRegion( |         return MouseRegion( | ||||||
|           cursor: SystemMouseCursors.click, |           cursor: SystemMouseCursors.click, | ||||||
|           onEnter: (p) => |           onEnter: (p) => | ||||||
|               Provider.of<CellContainerNotifier>(context, listen: false) |               Provider.of<_CellContainerNotifier>(context, listen: false) | ||||||
|                   .onEnter = true, |                   .onEnter = true, | ||||||
|           onExit: (p) => |           onExit: (p) => | ||||||
|               Provider.of<CellContainerNotifier>(context, listen: false) |               Provider.of<_CellContainerNotifier>(context, listen: false) | ||||||
|                   .onEnter = false, |                   .onEnter = false, | ||||||
|           child: Stack( |           child: Stack( | ||||||
|             alignment: AlignmentDirectional.center, |             alignment: AlignmentDirectional.center, | ||||||
| @ -111,13 +115,13 @@ class CellEnterRegion extends StatelessWidget { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class CellContainerNotifier extends ChangeNotifier { | class _CellContainerNotifier extends ChangeNotifier { | ||||||
|   final CellEditable cellEditable; |   final CellEditable cellEditable; | ||||||
|   VoidCallback? _onCellFocusListener; |   VoidCallback? _onCellFocusListener; | ||||||
|   bool _isFocus = false; |   bool _isFocus = false; | ||||||
|   bool _onEnter = false; |   bool _onEnter = false; | ||||||
| 
 | 
 | ||||||
|   CellContainerNotifier(this.cellEditable) { |   _CellContainerNotifier(this.cellEditable) { | ||||||
|     _onCellFocusListener = () => isFocus = cellEditable.onCellFocus.value; |     _onCellFocusListener = () => isFocus = cellEditable.onCellFocus.value; | ||||||
|     cellEditable.onCellFocus.addListener(_onCellFocusListener!); |     cellEditable.onCellFocus.addListener(_onCellFocusListener!); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -181,7 +181,13 @@ class RowContent extends StatelessWidget { | |||||||
|     return gridCellMap.values.map( |     return gridCellMap.values.map( | ||||||
|       (cellId) { |       (cellId) { | ||||||
|         final GridCellWidget child = builder.build(cellId); |         final GridCellWidget child = builder.build(cellId); | ||||||
|         accessoryBuilder(GridCellAccessoryBuildContext buildContext) { | 
 | ||||||
|  |         return CellContainer( | ||||||
|  |           width: cellId.field.width.toDouble(), | ||||||
|  |           child: child, | ||||||
|  |           rowStateNotifier: | ||||||
|  |               Provider.of<RegionStateNotifier>(context, listen: false), | ||||||
|  |           accessoryBuilder: (buildContext) { | ||||||
|             final builder = child.accessoryBuilder; |             final builder = child.accessoryBuilder; | ||||||
|             List<GridCellAccessory> accessories = []; |             List<GridCellAccessory> accessories = []; | ||||||
|             if (cellId.field.isPrimary) { |             if (cellId.field.isPrimary) { | ||||||
| @ -195,14 +201,7 @@ class RowContent extends StatelessWidget { | |||||||
|               accessories.addAll(builder(buildContext)); |               accessories.addAll(builder(buildContext)); | ||||||
|             } |             } | ||||||
|             return accessories; |             return accessories; | ||||||
|         } |           }, | ||||||
| 
 |  | ||||||
|         return CellContainer( |  | ||||||
|           width: cellId.field.width.toDouble(), |  | ||||||
|           child: child, |  | ||||||
|           rowStateNotifier: |  | ||||||
|               Provider.of<RegionStateNotifier>(context, listen: false), |  | ||||||
|           accessoryBuilder: accessoryBuilder, |  | ||||||
|         ); |         ); | ||||||
|       }, |       }, | ||||||
|     ).toList(); |     ).toList(); | ||||||
|  | |||||||
| @ -23,18 +23,19 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> { | |||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   void initState() { |   void initState() { | ||||||
|     final column1 = AFBoardColumnData(id: "To Do", items: [ |     List<AFColumnItem> a = [ | ||||||
|       TextItem("Card 1"), |       TextItem("Card 1"), | ||||||
|       TextItem("Card 2"), |       TextItem("Card 2"), | ||||||
|       RichTextItem(title: "Card 3", subtitle: 'Aug 1, 2020 4:05 PM'), |       // RichTextItem(title: "Card 3", subtitle: 'Aug 1, 2020 4:05 PM'), | ||||||
|       TextItem("Card 4"), |       TextItem("Card 4"), | ||||||
|     ]); |     ]; | ||||||
|     final column2 = AFBoardColumnData(id: "In Progress", items: [ |     final column1 = AFBoardColumnData(id: "To Do", items: a); | ||||||
|       RichTextItem(title: "Card 5", subtitle: 'Aug 1, 2020 4:05 PM'), |     final column2 = AFBoardColumnData(id: "In Progress", items: <AFColumnItem>[ | ||||||
|       TextItem("Card 6"), |       // RichTextItem(title: "Card 5", subtitle: 'Aug 1, 2020 4:05 PM'), | ||||||
|  |       // TextItem("Card 6"), | ||||||
|     ]); |     ]); | ||||||
| 
 | 
 | ||||||
|     final column3 = AFBoardColumnData(id: "Done", items: []); |     final column3 = AFBoardColumnData(id: "Done", items: <AFColumnItem>[]); | ||||||
| 
 | 
 | ||||||
|     boardDataController.addColumn(column1); |     boardDataController.addColumn(column1); | ||||||
|     boardDataController.addColumn(column2); |     boardDataController.addColumn(column2); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 appflowy
						appflowy