浏览代码

chore: refactor grid cell expander

appflowy 2 年之前
父节点
当前提交
a568f6323d

+ 27 - 3
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart

@@ -48,11 +48,19 @@ class BlankCell extends StatelessWidget {
   }
 }
 
+abstract class GridCellExpander implements Widget {
+  void onExpand(BuildContext context);
+}
+
 abstract class GridCellWidget implements FlowyHoverWidget {
   @override
   final ValueNotifier<bool> onFocus = ValueNotifier<bool>(false);
 
   final GridCellRequestFocusNotifier requestFocus = GridCellRequestFocusNotifier();
+
+  GridCellExpander? buildExpander() {
+    return null;
+  }
 }
 
 class GridCellRequestFocusNotifier extends ChangeNotifier {
@@ -125,7 +133,7 @@ class CellStateNotifier extends ChangeNotifier {
 
 class CellContainer extends StatelessWidget {
   final GridCellWidget child;
-  final Widget? expander;
+  final GridCellExpander? expander;
   final double width;
   final RegionStateNotifier rowStateNotifier;
   const CellContainer({
@@ -182,17 +190,33 @@ class CellContainer extends StatelessWidget {
 
 class CellEnterRegion extends StatelessWidget {
   final Widget child;
-  final Widget expander;
+  final GridCellExpander expander;
   const CellEnterRegion({required this.child, required this.expander, Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
+    final theme = context.watch<AppTheme>();
+
     return Selector<CellStateNotifier, bool>(
       selector: (context, notifier) => notifier.onEnter,
       builder: (context, onEnter, _) {
         List<Widget> children = [child];
         if (onEnter) {
-          children.add(expander.positioned(right: 0));
+          final hover = FlowyHover(
+            style: HoverStyle(hoverColor: theme.bg3, backgroundColor: theme.surface),
+            builder: (_, onHover) => Container(
+              width: 26,
+              height: 26,
+              padding: const EdgeInsets.all(3),
+              child: expander,
+            ),
+          );
+
+          children.add(GestureDetector(
+            child: hover,
+            behavior: HitTestBehavior.opaque,
+            onTap: () => expander.onExpand(context),
+          ).positioned(right: 0));
         }
 
         return MouseRegion(

+ 4 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart

@@ -25,7 +25,10 @@ class URLCellEditor extends StatefulWidget {
     //
     FlowyOverlay.of(context).insertWithAnchor(
       widget: OverlayContainer(
-        child: SizedBox(width: 200, child: editor),
+        child: SizedBox(
+          width: 200,
+          child: Padding(padding: const EdgeInsets.all(6), child: editor),
+        ),
         constraints: BoxConstraints.loose(const Size(300, 160)),
       ),
       identifier: URLCellEditor.identifier(),

+ 17 - 18
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart

@@ -2,6 +2,7 @@ import 'dart:async';
 import 'package:app_flowy/workspace/application/grid/cell/url_cell_bloc.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
+import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flutter/gestures.dart';
 import 'package:flutter/material.dart';
@@ -36,6 +37,12 @@ class GridURLCell extends StatefulWidget with GridCellWidget {
 
   @override
   State<GridURLCell> createState() => _GridURLCellState();
+
+  @override
+  GridCellExpander? buildExpander() {
+    final cellContext = cellContextBuilder.build() as GridURLCellContext;
+    return _EditURLCellIndicator(cellContext: cellContext);
+  }
 }
 
 class _GridURLCellState extends State<GridURLCell> {
@@ -70,13 +77,7 @@ class _GridURLCellState extends State<GridURLCell> {
             ),
           );
 
-          return CellEnterRegion(
-            child: Align(alignment: Alignment.centerLeft, child: richText),
-            expander: _EditCellIndicator(onTap: () {
-              final cellContext = widget.cellContextBuilder.build() as GridURLCellContext;
-              URLCellEditor.show(context, cellContext);
-            }),
-          );
+          return Align(alignment: Alignment.centerLeft, child: richText);
         },
       ),
     );
@@ -115,20 +116,18 @@ class _GridURLCellState extends State<GridURLCell> {
   }
 }
 
-class _EditCellIndicator extends StatelessWidget {
-  final VoidCallback onTap;
-  const _EditCellIndicator({required this.onTap, Key? key}) : super(key: key);
+class _EditURLCellIndicator extends StatelessWidget with GridCellExpander {
+  final GridURLCellContext cellContext;
+  const _EditURLCellIndicator({required this.cellContext, Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
-    return FlowyIconButton(
-      width: 26,
-      onPressed: onTap,
-      hoverColor: theme.hover,
-      radius: BorderRadius.circular(4),
-      iconPadding: const EdgeInsets.all(5),
-      icon: svgWidget("editor/edit", color: theme.iconColor),
-    );
+    return svgWidget("editor/edit", color: theme.iconColor);
+  }
+
+  @override
+  void onExpand(BuildContext context) {
+    URLCellEditor.show(context, cellContext);
   }
 }

+ 0 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart

@@ -86,7 +86,6 @@ class _GridHeaderCellContainer extends StatelessWidget {
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
     final borderSide = BorderSide(color: theme.shader5, width: 1.0);
-
     final decoration = BoxDecoration(
         border: Border(
       top: borderSide,

+ 13 - 16
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart

@@ -170,14 +170,15 @@ class _RowCells extends StatelessWidget {
   List<Widget> _makeCells(BuildContext context, GridCellMap gridCellMap) {
     return gridCellMap.values.map(
       (gridCell) {
-        Widget? expander;
+        final GridCellWidget child = buildGridCellWidget(gridCell, cellCache);
+        GridCellExpander? expander = child.buildExpander();
         if (gridCell.field.isPrimary) {
-          expander = _CellExpander(onExpand: onExpand);
+          expander = _PrimaryCellExpander(onTap: onExpand);
         }
 
         return CellContainer(
           width: gridCell.field.width.toDouble(),
-          child: buildGridCellWidget(gridCell, cellCache),
+          child: child,
           rowStateNotifier: Provider.of<RegionStateNotifier>(context, listen: false),
           expander: expander,
         );
@@ -199,23 +200,19 @@ class RegionStateNotifier extends ChangeNotifier {
   bool get onEnter => _onEnter;
 }
 
-class _CellExpander extends StatelessWidget {
-  final VoidCallback onExpand;
-  const _CellExpander({required this.onExpand, Key? key}) : super(key: key);
+class _PrimaryCellExpander extends StatelessWidget with GridCellExpander {
+  final VoidCallback onTap;
+  const _PrimaryCellExpander({required this.onTap, Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
-    return FittedBox(
-      fit: BoxFit.contain,
-      child: FlowyIconButton(
-        width: 26,
-        onPressed: onExpand,
-        iconPadding: const EdgeInsets.all(5),
-        radius: BorderRadius.circular(4),
-        icon: svgWidget("grid/expander", color: theme.main1),
-      ),
-    );
+    return svgWidget("grid/expander", color: theme.main1);
+  }
+
+  @override
+  void onExpand(BuildContext context) {
+    onTap();
   }
 }
 

+ 3 - 1
frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart

@@ -52,7 +52,7 @@ class _FlowyHoverState extends State<FlowyHover> {
         child: child,
       );
     } else {
-      return child;
+      return Container(child: child, color: widget.style.backgroundColor);
     }
   }
 }
@@ -63,12 +63,14 @@ class HoverStyle {
   final Color hoverColor;
   final BorderRadius borderRadius;
   final EdgeInsets contentMargin;
+  final Color backgroundColor;
 
   const HoverStyle(
       {this.borderColor = Colors.transparent,
       this.borderWidth = 0,
       this.borderRadius = const BorderRadius.all(Radius.circular(6)),
       this.contentMargin = EdgeInsets.zero,
+      this.backgroundColor = Colors.transparent,
       required this.hoverColor});
 }