Browse Source

chore: show board setting

appflowy 2 years ago
parent
commit
a7cbb3d31a

+ 46 - 0
frontend/app_flowy/lib/plugins/board/application/toolbar/board_setting_bloc.dart

@@ -0,0 +1,46 @@
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'dart:async';
+import 'package:dartz/dartz.dart';
+
+part 'board_setting_bloc.freezed.dart';
+
+class BoardSettingBloc extends Bloc<BoardSettingEvent, BoardSettingState> {
+  final String gridId;
+  BoardSettingBloc({required this.gridId})
+      : super(BoardSettingState.initial()) {
+    on<BoardSettingEvent>(
+      (event, emit) async {
+        event.when(performAction: (action) {
+          emit(state.copyWith(selectedAction: Some(action)));
+        });
+      },
+    );
+  }
+
+  @override
+  Future<void> close() async {
+    return super.close();
+  }
+}
+
+@freezed
+class BoardSettingEvent with _$BoardSettingEvent {
+  const factory BoardSettingEvent.performAction(BoardSettingAction action) =
+      _PerformAction;
+}
+
+@freezed
+class BoardSettingState with _$BoardSettingState {
+  const factory BoardSettingState({
+    required Option<BoardSettingAction> selectedAction,
+  }) = _BoardSettingState;
+
+  factory BoardSettingState.initial() => BoardSettingState(
+        selectedAction: none(),
+      );
+}
+
+enum BoardSettingAction {
+  properties,
+}

+ 46 - 17
frontend/app_flowy/lib/plugins/board/presentation/board_page.dart

@@ -24,6 +24,7 @@ import '../../grid/application/row/row_cache.dart';
 import '../application/board_bloc.dart';
 import 'card/card.dart';
 import 'card/card_cell_builder.dart';
+import 'toolbar/board_toolbar.dart';
 
 class BoardPage extends StatelessWidget {
   final ViewPB view;
@@ -100,25 +101,34 @@ class _BoardContentState extends State<BoardContent> {
         buildWhen: (previous, current) =>
             previous.groupIds.length != current.groupIds.length,
         builder: (context, state) {
+          final theme = context.read<AppTheme>();
           return Container(
-            color: Colors.white,
+            color: theme.surface,
             child: Padding(
-              padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
-              child: AFBoard(
-                scrollManager: scrollManager,
-                scrollController: scrollController,
-                dataController: context.read<BoardBloc>().boardController,
-                headerBuilder: _buildHeader,
-                footBuilder: _buildFooter,
-                cardBuilder: (_, column, columnItem) => _buildCard(
-                  context,
-                  column,
-                  columnItem,
-                ),
-                columnConstraints: const BoxConstraints.tightFor(width: 300),
-                config: AFBoardConfig(
-                  columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
-                ),
+              padding: const EdgeInsets.symmetric(horizontal: 20),
+              child: Column(
+                children: [
+                  const _ToolbarBlocAdaptor(),
+                  Expanded(
+                    child: AFBoard(
+                      scrollManager: scrollManager,
+                      scrollController: scrollController,
+                      dataController: context.read<BoardBloc>().boardController,
+                      headerBuilder: _buildHeader,
+                      footBuilder: _buildFooter,
+                      cardBuilder: (_, column, columnItem) => _buildCard(
+                        context,
+                        column,
+                        columnItem,
+                      ),
+                      columnConstraints:
+                          const BoxConstraints.tightFor(width: 300),
+                      config: AFBoardConfig(
+                        columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
+                      ),
+                    ),
+                  ),
+                ],
               ),
             ),
           );
@@ -277,6 +287,25 @@ class _BoardContentState extends State<BoardContent> {
   }
 }
 
+class _ToolbarBlocAdaptor extends StatelessWidget {
+  const _ToolbarBlocAdaptor({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<BoardBloc, BoardState>(
+      builder: (context, state) {
+        final bloc = context.read<BoardBloc>();
+        final toolbarContext = BoardToolbarContext(
+          viewId: bloc.gridId,
+          fieldCache: bloc.fieldCache,
+        );
+
+        return BoardToolbar(toolbarContext: toolbarContext);
+      },
+    );
+  }
+}
+
 extension HexColor on Color {
   static Color fromHex(String hexString) {
     final buffer = StringBuffer();

+ 168 - 0
frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart

@@ -0,0 +1,168 @@
+import 'package:app_flowy/generated/locale_keys.g.dart';
+import 'package:app_flowy/plugins/board/application/toolbar/board_setting_bloc.dart';
+import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
+import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
+import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_property.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme.dart';
+import 'package:flowy_infra_ui/flowy_infra_ui.dart';
+import 'package:flowy_infra_ui/style_widget/button.dart';
+import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
+import 'package:flowy_infra_ui/style_widget/text.dart';
+import 'package:flowy_infra_ui/widget/spacing.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'board_toolbar.dart';
+
+class BoardSettingContext {
+  final String viewId;
+  final GridFieldCache fieldCache;
+  BoardSettingContext({
+    required this.viewId,
+    required this.fieldCache,
+  });
+
+  factory BoardSettingContext.from(BoardToolbarContext toolbarContext) =>
+      BoardSettingContext(
+        viewId: toolbarContext.viewId,
+        fieldCache: toolbarContext.fieldCache,
+      );
+}
+
+class BoardSettingList extends StatelessWidget {
+  final BoardSettingContext settingContext;
+  final Function(BoardSettingAction, BoardSettingContext) onAction;
+  const BoardSettingList({
+    required this.settingContext,
+    required this.onAction,
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocProvider(
+      create: (context) => BoardSettingBloc(gridId: settingContext.viewId),
+      child: BlocListener<BoardSettingBloc, BoardSettingState>(
+        listenWhen: (previous, current) =>
+            previous.selectedAction != current.selectedAction,
+        listener: (context, state) {
+          state.selectedAction.foldLeft(null, (_, action) {
+            FlowyOverlay.of(context).remove(identifier());
+            onAction(action, settingContext);
+          });
+        },
+        child: BlocBuilder<BoardSettingBloc, BoardSettingState>(
+          builder: (context, state) {
+            return _renderList();
+          },
+        ),
+      ),
+    );
+  }
+
+  Widget _renderList() {
+    final cells = BoardSettingAction.values.map((action) {
+      return _SettingItem(action: action);
+    }).toList();
+
+    return SizedBox(
+      width: 140,
+      child: ListView.separated(
+        shrinkWrap: true,
+        controller: ScrollController(),
+        itemCount: cells.length,
+        separatorBuilder: (context, index) {
+          return VSpace(GridSize.typeOptionSeparatorHeight);
+        },
+        physics: StyledScrollPhysics(),
+        itemBuilder: (BuildContext context, int index) {
+          return cells[index];
+        },
+      ),
+    );
+  }
+
+  static void show(BuildContext context, BoardSettingContext settingContext) {
+    final list = BoardSettingList(
+      settingContext: settingContext,
+      onAction: (action, settingContext) {
+        switch (action) {
+          case BoardSettingAction.properties:
+            GridPropertyList(
+                    gridId: settingContext.viewId,
+                    fieldCache: settingContext.fieldCache)
+                .show(context);
+            break;
+        }
+      },
+    );
+
+    FlowyOverlay.of(context).insertWithAnchor(
+      widget: OverlayContainer(
+        constraints: BoxConstraints.loose(const Size(140, 400)),
+        child: list,
+      ),
+      identifier: identifier(),
+      anchorContext: context,
+      anchorDirection: AnchorDirection.bottomRight,
+      style: FlowyOverlayStyle(blur: false),
+    );
+  }
+
+  static String identifier() {
+    return (BoardSettingList).toString();
+  }
+}
+
+class _SettingItem extends StatelessWidget {
+  final BoardSettingAction action;
+
+  const _SettingItem({
+    required this.action,
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final theme = context.read<AppTheme>();
+    final isSelected = context
+        .read<BoardSettingBloc>()
+        .state
+        .selectedAction
+        .foldLeft(false, (_, selectedAction) => selectedAction == action);
+
+    return SizedBox(
+      height: 30,
+      child: FlowyButton(
+        isSelected: isSelected,
+        text: FlowyText.medium(action.title(),
+            fontSize: 12, color: theme.textColor),
+        hoverColor: theme.hover,
+        onTap: () {
+          context
+              .read<BoardSettingBloc>()
+              .add(BoardSettingEvent.performAction(action));
+        },
+        leftIcon: svgWidget(action.iconName(), color: theme.iconColor),
+      ),
+    );
+  }
+}
+
+extension _GridSettingExtension on BoardSettingAction {
+  String iconName() {
+    switch (this) {
+      case BoardSettingAction.properties:
+        return 'grid/setting/properties';
+    }
+  }
+
+  String title() {
+    switch (this) {
+      case BoardSettingAction.properties:
+        return LocaleKeys.grid_settings_Properties.tr();
+    }
+  }
+}

+ 60 - 0
frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart

@@ -0,0 +1,60 @@
+import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
+import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme.dart';
+import 'package:flowy_infra_ui/style_widget/icon_button.dart';
+import 'package:flutter/widgets.dart';
+import 'package:provider/provider.dart';
+
+import 'board_setting.dart';
+
+class BoardToolbarContext {
+  final String viewId;
+  final GridFieldCache fieldCache;
+
+  BoardToolbarContext({
+    required this.viewId,
+    required this.fieldCache,
+  });
+}
+
+class BoardToolbar extends StatelessWidget {
+  final BoardToolbarContext toolbarContext;
+  const BoardToolbar({
+    required this.toolbarContext,
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return SizedBox(
+      height: 40,
+      child: Row(
+        children: [
+          _SettingButton(
+            settingContext: BoardSettingContext.from(toolbarContext),
+          ),
+        ],
+      ),
+    );
+  }
+}
+
+class _SettingButton extends StatelessWidget {
+  final BoardSettingContext settingContext;
+  const _SettingButton({required this.settingContext, Key? key})
+      : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final theme = context.read<AppTheme>();
+    return FlowyIconButton(
+      hoverColor: theme.hover,
+      width: 22,
+      onPressed: () => BoardSettingList.show(context, settingContext),
+      icon: Padding(
+        padding: const EdgeInsets.symmetric(vertical: 3.0, horizontal: 3.0),
+        child: svgWidget("grid/setting/setting"),
+      ),
+    );
+  }
+}