Browse Source

feat: hide url cell accessory when the content is empty (#2754)

Nathan.fooo 1 year ago
parent
commit
2ecd0a67ad

+ 13 - 11
frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/accessory/cell_accessory.dart

@@ -19,8 +19,8 @@ class GridCellAccessoryBuildContext {
   });
 }
 
-class GridCellAccessoryBuilder {
-  final GlobalKey _key = GlobalKey();
+class GridCellAccessoryBuilder<T extends State<StatefulWidget>> {
+  final GlobalKey<T> _key = GlobalKey();
 
   final Widget Function(Key key) _builder;
 
@@ -67,9 +67,16 @@ class _PrimaryCellAccessoryState extends State<PrimaryCellAccessory>
   Widget build(BuildContext context) {
     return Tooltip(
       message: LocaleKeys.tooltip_openAsPage.tr(),
-      child: svgWidget(
-        "grid/expander",
-        color: Theme.of(context).colorScheme.primary,
+      child: SizedBox(
+        width: 26,
+        height: 26,
+        child: Padding(
+          padding: const EdgeInsets.all(3.0),
+          child: svgWidget(
+            "grid/expander",
+            color: Theme.of(context).colorScheme.primary,
+          ),
+        ),
       ),
     );
   }
@@ -183,12 +190,7 @@ class CellAccessoryContainer extends StatelessWidget {
       final hover = FlowyHover(
         style:
             HoverStyle(hoverColor: AFThemeExtension.of(context).lightGreyHover),
-        builder: (_, onHover) => Container(
-          width: 26,
-          height: 26,
-          padding: const EdgeInsets.all(3),
-          child: accessory.build(),
-        ),
+        builder: (_, onHover) => accessory.build(),
       );
       return GestureDetector(
         behavior: HitTestBehavior.opaque,

+ 93 - 48
frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/url_cell/url_cell.dart

@@ -1,5 +1,6 @@
 import 'dart:async';
 import 'package:appflowy/generated/locale_keys.g.dart';
+import 'package:appflowy/plugins/database_view/application/cell/cell_controller.dart';
 import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
 import 'package:appflowy/workspace/presentation/home/toast.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
@@ -35,12 +36,14 @@ enum GridURLCellAccessoryType {
   visitURL,
 }
 
+typedef URLCellDataNotifier = CellDataNotifier<String>;
+
 class GridURLCell extends GridCellWidget {
   GridURLCell({
     super.key,
     required this.cellControllerBuilder,
     GridCellStyle? style,
-  }) {
+  }) : _cellDataNotifier = CellDataNotifier(value: '') {
     if (style != null) {
       cellStyle = (style as GridURLCellStyle);
     } else {
@@ -48,36 +51,14 @@ class GridURLCell extends GridCellWidget {
     }
   }
 
+  /// Use
+  final URLCellDataNotifier _cellDataNotifier;
   final CellControllerBuilder cellControllerBuilder;
   late final GridURLCellStyle? cellStyle;
 
   @override
   GridCellState<GridURLCell> createState() => _GridURLCellState();
 
-  GridCellAccessoryBuilder accessoryFromType(
-    GridURLCellAccessoryType ty,
-    GridCellAccessoryBuildContext buildContext,
-  ) {
-    switch (ty) {
-      case GridURLCellAccessoryType.visitURL:
-        final cellContext = cellControllerBuilder.build() as URLCellController;
-        return GridCellAccessoryBuilder(
-          builder: (Key key) => _VisitURLAccessory(
-            key: key,
-            cellContext: cellContext,
-          ),
-        );
-      case GridURLCellAccessoryType.copyURL:
-        final cellContext = cellControllerBuilder.build() as URLCellController;
-        return GridCellAccessoryBuilder(
-          builder: (Key key) => _CopyURLAccessory(
-            key: key,
-            cellContext: cellContext,
-          ),
-        );
-    }
-  }
-
   @override
   List<GridCellAccessoryBuilder> Function(
     GridCellAccessoryBuildContext buildContext,
@@ -86,7 +67,7 @@ class GridURLCell extends GridCellWidget {
         if (cellStyle != null) {
           accessories.addAll(
             cellStyle!.accessoryTypes.map((ty) {
-              return accessoryFromType(ty, buildContext);
+              return _accessoryFromType(ty, buildContext);
             }),
           );
         }
@@ -94,7 +75,7 @@ class GridURLCell extends GridCellWidget {
         // If the accessories is empty then the default accessory will be GridURLCellAccessoryType.visitURL
         if (accessories.isEmpty) {
           accessories.add(
-            accessoryFromType(
+            _accessoryFromType(
               GridURLCellAccessoryType.visitURL,
               buildContext,
             ),
@@ -103,6 +84,28 @@ class GridURLCell extends GridCellWidget {
 
         return accessories;
       };
+
+  GridCellAccessoryBuilder _accessoryFromType(
+    GridURLCellAccessoryType ty,
+    GridCellAccessoryBuildContext buildContext,
+  ) {
+    switch (ty) {
+      case GridURLCellAccessoryType.visitURL:
+        return VisitURLCellAccessoryBuilder(
+          builder: (Key key) => _VisitURLAccessory(
+            key: key,
+            cellDataNotifier: _cellDataNotifier,
+          ),
+        );
+      case GridURLCellAccessoryType.copyURL:
+        return CopyURLCellAccessoryBuilder(
+          builder: (Key key) => _CopyURLAccessory(
+            key: key,
+            cellDataNotifier: _cellDataNotifier,
+          ),
+        );
+    }
+  }
 }
 
 class _GridURLCellState extends GridFocusNodeCellState<GridURLCell> {
@@ -133,8 +136,11 @@ class _GridURLCellState extends GridFocusNodeCellState<GridURLCell> {
       value: _cellBloc,
       child: BlocConsumer<URLCellBloc, URLCellState>(
         listenWhen: (previous, current) => previous.content != current.content,
-        listener: (context, state) => _controller.text = state.content,
+        listener: (context, state) {
+          _controller.text = state.content;
+        },
         builder: (context, state) {
+          widget._cellDataNotifier.value = state.content;
           final urlEditor = Padding(
             padding: EdgeInsets.only(
               left: GridSize.cellContentInsets.left,
@@ -232,33 +238,41 @@ class _EditURLAccessoryState extends State<_EditURLAccessory>
   }
 }
 
+typedef CopyURLCellAccessoryBuilder
+    = GridCellAccessoryBuilder<State<_CopyURLAccessory>>;
+
 class _CopyURLAccessory extends StatefulWidget {
   const _CopyURLAccessory({
     super.key,
-    required this.cellContext,
+    required this.cellDataNotifier,
   });
 
-  final URLCellController cellContext;
+  final URLCellDataNotifier cellDataNotifier;
 
   @override
-  State<StatefulWidget> createState() => _CopyURLAccessoryState();
+  State<_CopyURLAccessory> createState() => _CopyURLAccessoryState();
 }
 
 class _CopyURLAccessoryState extends State<_CopyURLAccessory>
     with GridCellAccessoryState {
   @override
   Widget build(BuildContext context) {
-    return svgWidget(
-      "editor/copy",
-      color: AFThemeExtension.of(context).textColor,
-    );
+    if (widget.cellDataNotifier.value.isNotEmpty) {
+      return _URLAccessoryIconContainer(
+        child: svgWidget(
+          "editor/copy",
+          color: AFThemeExtension.of(context).textColor,
+        ),
+      );
+    } else {
+      return const SizedBox.shrink();
+    }
   }
 
   @override
   void onTap() {
-    final content =
-        widget.cellContext.getCellData(loadIfNotExist: false)?.content;
-    if (content == null) {
+    final content = widget.cellDataNotifier.value;
+    if (content.isEmpty) {
       return;
     }
     Clipboard.setData(ClipboardData(text: content));
@@ -266,33 +280,46 @@ class _CopyURLAccessoryState extends State<_CopyURLAccessory>
   }
 }
 
+typedef VisitURLCellAccessoryBuilder
+    = GridCellAccessoryBuilder<State<_VisitURLAccessory>>;
+
 class _VisitURLAccessory extends StatefulWidget {
   const _VisitURLAccessory({
     super.key,
-    required this.cellContext,
+    required this.cellDataNotifier,
   });
 
-  final URLCellController cellContext;
+  final URLCellDataNotifier cellDataNotifier;
 
   @override
-  State<StatefulWidget> createState() => _VisitURLAccessoryState();
+  State<_VisitURLAccessory> createState() => _VisitURLAccessoryState();
 }
 
 class _VisitURLAccessoryState extends State<_VisitURLAccessory>
     with GridCellAccessoryState {
   @override
   Widget build(BuildContext context) {
-    return svgWidget(
-      "editor/link",
-      color: AFThemeExtension.of(context).textColor,
-    );
+    if (widget.cellDataNotifier.value.isNotEmpty) {
+      return _URLAccessoryIconContainer(
+        child: svgWidget(
+          "editor/link",
+          color: AFThemeExtension.of(context).textColor,
+        ),
+      );
+    } else {
+      return const SizedBox.shrink();
+    }
+  }
+
+  @override
+  bool enable() {
+    return widget.cellDataNotifier.value.isNotEmpty;
   }
 
   @override
   void onTap() {
-    final content =
-        widget.cellContext.getCellData(loadIfNotExist: false)?.content;
-    if (content == null) {
+    final content = widget.cellDataNotifier.value;
+    if (content.isEmpty) {
       return;
     }
     final shouldAddScheme =
@@ -301,3 +328,21 @@ class _VisitURLAccessoryState extends State<_VisitURLAccessory>
     canLaunchUrlString(url).then((value) => launchUrlString(url));
   }
 }
+
+class _URLAccessoryIconContainer extends StatelessWidget {
+  const _URLAccessoryIconContainer({required this.child});
+
+  final Widget child;
+
+  @override
+  Widget build(BuildContext context) {
+    return SizedBox(
+      width: 26,
+      height: 26,
+      child: Padding(
+        padding: const EdgeInsets.all(3.0),
+        child: child,
+      ),
+    );
+  }
+}