board_page.dart 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // ignore_for_file: unused_field
  2. import 'dart:collection';
  3. import 'package:app_flowy/plugins/board/application/card/card_data_controller.dart';
  4. import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
  5. import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
  6. import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
  7. import 'package:app_flowy/plugins/grid/presentation/widgets/cell/cell_builder.dart';
  8. import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_detail.dart';
  9. import 'package:appflowy_board/appflowy_board.dart';
  10. import 'package:flowy_infra_ui/widget/error_page.dart';
  11. import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
  12. import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
  13. import 'package:flutter/material.dart';
  14. import 'package:flutter_bloc/flutter_bloc.dart';
  15. import '../../grid/application/row/row_cache.dart';
  16. import '../application/board_bloc.dart';
  17. import 'card/card.dart';
  18. import 'card/card_cell_builder.dart';
  19. class BoardPage extends StatelessWidget {
  20. final ViewPB view;
  21. BoardPage({required this.view, Key? key}) : super(key: ValueKey(view.id));
  22. @override
  23. Widget build(BuildContext context) {
  24. return BlocProvider(
  25. create: (context) =>
  26. BoardBloc(view: view)..add(const BoardEvent.initial()),
  27. child: BlocBuilder<BoardBloc, BoardState>(
  28. builder: (context, state) {
  29. return state.loadingState.map(
  30. loading: (_) =>
  31. const Center(child: CircularProgressIndicator.adaptive()),
  32. finish: (result) {
  33. return result.successOrFail.fold(
  34. (_) => BoardContent(),
  35. (err) => FlowyErrorPage(err.toString()),
  36. );
  37. },
  38. );
  39. },
  40. ),
  41. );
  42. }
  43. }
  44. class BoardContent extends StatelessWidget {
  45. final config = AFBoardConfig(
  46. columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
  47. );
  48. BoardContent({Key? key}) : super(key: key);
  49. @override
  50. Widget build(BuildContext context) {
  51. return BlocBuilder<BoardBloc, BoardState>(
  52. builder: (context, state) {
  53. return Container(
  54. color: Colors.white,
  55. child: Padding(
  56. padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
  57. child: AFBoard(
  58. // key: UniqueKey(),
  59. scrollController: ScrollController(),
  60. dataController: context.read<BoardBloc>().afBoardDataController,
  61. headerBuilder: _buildHeader,
  62. footBuilder: _buildFooter,
  63. cardBuilder: (_, data) => _buildCard(context, data),
  64. columnConstraints: const BoxConstraints.tightFor(width: 240),
  65. config: AFBoardConfig(
  66. columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
  67. ),
  68. ),
  69. ),
  70. );
  71. },
  72. );
  73. }
  74. Widget _buildHeader(BuildContext context, AFBoardColumnData columnData) {
  75. return AppFlowyColumnHeader(
  76. icon: const Icon(Icons.lightbulb_circle),
  77. title: Text(columnData.desc),
  78. addIcon: const Icon(Icons.add, size: 20),
  79. moreIcon: const Icon(Icons.more_horiz, size: 20),
  80. height: 50,
  81. margin: config.columnItemPadding,
  82. );
  83. }
  84. Widget _buildFooter(BuildContext context, AFBoardColumnData columnData) {
  85. return AppFlowyColumnFooter(
  86. icon: const Icon(Icons.add, size: 20),
  87. title: const Text('New'),
  88. height: 50,
  89. margin: config.columnItemPadding,
  90. onAddButtonClick: () {
  91. context.read<BoardBloc>().add(BoardEvent.createRow(columnData.id));
  92. });
  93. }
  94. Widget _buildCard(BuildContext context, AFColumnItem item) {
  95. final rowPB = (item as BoardColumnItem).row;
  96. final rowCache = context.read<BoardBloc>().getRowCache(rowPB.blockId);
  97. /// Return placeholder widget if the rowCache is null.
  98. if (rowCache == null) return SizedBox(key: ObjectKey(item));
  99. final fieldCache = context.read<BoardBloc>().fieldCache;
  100. final gridId = context.read<BoardBloc>().gridId;
  101. final cardController = CardDataController(
  102. fieldCache: fieldCache,
  103. rowCache: rowCache,
  104. rowPB: rowPB,
  105. );
  106. final cellBuilder = BoardCellBuilder(cardController);
  107. final isEditing = context.read<BoardBloc>().state.editingRow.fold(
  108. () => false,
  109. (editingRow) => editingRow.id == rowPB.id,
  110. );
  111. return AppFlowyColumnItemCard(
  112. key: ObjectKey(item),
  113. child: BoardCard(
  114. gridId: gridId,
  115. isEditing: isEditing,
  116. cellBuilder: cellBuilder,
  117. dataController: cardController,
  118. onEditEditing: (rowId) {
  119. context.read<BoardBloc>().add(BoardEvent.endEditRow(rowId));
  120. },
  121. openCard: (context) => _openCard(
  122. gridId,
  123. fieldCache,
  124. rowPB,
  125. rowCache,
  126. context,
  127. ),
  128. ),
  129. );
  130. }
  131. void _openCard(String gridId, GridFieldCache fieldCache, RowPB rowPB,
  132. GridRowCache rowCache, BuildContext context) {
  133. final rowInfo = RowInfo(
  134. gridId: gridId,
  135. fields: UnmodifiableListView(fieldCache.fields),
  136. rowPB: rowPB,
  137. );
  138. final dataController = GridRowDataController(
  139. rowInfo: rowInfo,
  140. fieldCache: fieldCache,
  141. rowCache: rowCache,
  142. );
  143. RowDetailPage(
  144. cellBuilder: GridCellBuilder(delegate: dataController),
  145. dataController: dataController,
  146. ).show(context);
  147. }
  148. }
  149. extension HexColor on Color {
  150. static Color fromHex(String hexString) {
  151. final buffer = StringBuffer();
  152. if (hexString.length == 6 || hexString.length == 7) buffer.write('ff');
  153. buffer.write(hexString.replaceFirst('#', ''));
  154. return Color(int.parse(buffer.toString(), radix: 16));
  155. }
  156. }