mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-11-04 03:54:44 +00:00 
			
		
		
		
	feat: hide url cell accessory when the content is empty (#2754)
This commit is contained in:
		
							parent
							
								
									4ce94a9ceb
								
							
						
					
					
						commit
						2ecd0a67ad
					
				@ -19,8 +19,8 @@ class GridCellAccessoryBuildContext {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GridCellAccessoryBuilder {
 | 
					class GridCellAccessoryBuilder<T extends State<StatefulWidget>> {
 | 
				
			||||||
  final GlobalKey _key = GlobalKey();
 | 
					  final GlobalKey<T> _key = GlobalKey();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final Widget Function(Key key) _builder;
 | 
					  final Widget Function(Key key) _builder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -67,10 +67,17 @@ class _PrimaryCellAccessoryState extends State<PrimaryCellAccessory>
 | 
				
			|||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Tooltip(
 | 
					    return Tooltip(
 | 
				
			||||||
      message: LocaleKeys.tooltip_openAsPage.tr(),
 | 
					      message: LocaleKeys.tooltip_openAsPage.tr(),
 | 
				
			||||||
 | 
					      child: SizedBox(
 | 
				
			||||||
 | 
					        width: 26,
 | 
				
			||||||
 | 
					        height: 26,
 | 
				
			||||||
 | 
					        child: Padding(
 | 
				
			||||||
 | 
					          padding: const EdgeInsets.all(3.0),
 | 
				
			||||||
          child: svgWidget(
 | 
					          child: svgWidget(
 | 
				
			||||||
            "grid/expander",
 | 
					            "grid/expander",
 | 
				
			||||||
            color: Theme.of(context).colorScheme.primary,
 | 
					            color: Theme.of(context).colorScheme.primary,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -183,12 +190,7 @@ class CellAccessoryContainer extends StatelessWidget {
 | 
				
			|||||||
      final hover = FlowyHover(
 | 
					      final hover = FlowyHover(
 | 
				
			||||||
        style:
 | 
					        style:
 | 
				
			||||||
            HoverStyle(hoverColor: AFThemeExtension.of(context).lightGreyHover),
 | 
					            HoverStyle(hoverColor: AFThemeExtension.of(context).lightGreyHover),
 | 
				
			||||||
        builder: (_, onHover) => Container(
 | 
					        builder: (_, onHover) => accessory.build(),
 | 
				
			||||||
          width: 26,
 | 
					 | 
				
			||||||
          height: 26,
 | 
					 | 
				
			||||||
          padding: const EdgeInsets.all(3),
 | 
					 | 
				
			||||||
          child: accessory.build(),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      return GestureDetector(
 | 
					      return GestureDetector(
 | 
				
			||||||
        behavior: HitTestBehavior.opaque,
 | 
					        behavior: HitTestBehavior.opaque,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
import 'dart:async';
 | 
					import 'dart:async';
 | 
				
			||||||
import 'package:appflowy/generated/locale_keys.g.dart';
 | 
					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/plugins/database_view/application/cell/cell_controller_builder.dart';
 | 
				
			||||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
 | 
					import 'package:appflowy/workspace/presentation/home/toast.dart';
 | 
				
			||||||
import 'package:appflowy_popover/appflowy_popover.dart';
 | 
					import 'package:appflowy_popover/appflowy_popover.dart';
 | 
				
			||||||
@ -35,12 +36,14 @@ enum GridURLCellAccessoryType {
 | 
				
			|||||||
  visitURL,
 | 
					  visitURL,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef URLCellDataNotifier = CellDataNotifier<String>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GridURLCell extends GridCellWidget {
 | 
					class GridURLCell extends GridCellWidget {
 | 
				
			||||||
  GridURLCell({
 | 
					  GridURLCell({
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
    required this.cellControllerBuilder,
 | 
					    required this.cellControllerBuilder,
 | 
				
			||||||
    GridCellStyle? style,
 | 
					    GridCellStyle? style,
 | 
				
			||||||
  }) {
 | 
					  }) : _cellDataNotifier = CellDataNotifier(value: '') {
 | 
				
			||||||
    if (style != null) {
 | 
					    if (style != null) {
 | 
				
			||||||
      cellStyle = (style as GridURLCellStyle);
 | 
					      cellStyle = (style as GridURLCellStyle);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -48,36 +51,14 @@ class GridURLCell extends GridCellWidget {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Use
 | 
				
			||||||
 | 
					  final URLCellDataNotifier _cellDataNotifier;
 | 
				
			||||||
  final CellControllerBuilder cellControllerBuilder;
 | 
					  final CellControllerBuilder cellControllerBuilder;
 | 
				
			||||||
  late final GridURLCellStyle? cellStyle;
 | 
					  late final GridURLCellStyle? cellStyle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  GridCellState<GridURLCell> createState() => _GridURLCellState();
 | 
					  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
 | 
					  @override
 | 
				
			||||||
  List<GridCellAccessoryBuilder> Function(
 | 
					  List<GridCellAccessoryBuilder> Function(
 | 
				
			||||||
    GridCellAccessoryBuildContext buildContext,
 | 
					    GridCellAccessoryBuildContext buildContext,
 | 
				
			||||||
@ -86,7 +67,7 @@ class GridURLCell extends GridCellWidget {
 | 
				
			|||||||
        if (cellStyle != null) {
 | 
					        if (cellStyle != null) {
 | 
				
			||||||
          accessories.addAll(
 | 
					          accessories.addAll(
 | 
				
			||||||
            cellStyle!.accessoryTypes.map((ty) {
 | 
					            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 the accessories is empty then the default accessory will be GridURLCellAccessoryType.visitURL
 | 
				
			||||||
        if (accessories.isEmpty) {
 | 
					        if (accessories.isEmpty) {
 | 
				
			||||||
          accessories.add(
 | 
					          accessories.add(
 | 
				
			||||||
            accessoryFromType(
 | 
					            _accessoryFromType(
 | 
				
			||||||
              GridURLCellAccessoryType.visitURL,
 | 
					              GridURLCellAccessoryType.visitURL,
 | 
				
			||||||
              buildContext,
 | 
					              buildContext,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
@ -103,6 +84,28 @@ class GridURLCell extends GridCellWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return accessories;
 | 
					        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> {
 | 
					class _GridURLCellState extends GridFocusNodeCellState<GridURLCell> {
 | 
				
			||||||
@ -133,8 +136,11 @@ class _GridURLCellState extends GridFocusNodeCellState<GridURLCell> {
 | 
				
			|||||||
      value: _cellBloc,
 | 
					      value: _cellBloc,
 | 
				
			||||||
      child: BlocConsumer<URLCellBloc, URLCellState>(
 | 
					      child: BlocConsumer<URLCellBloc, URLCellState>(
 | 
				
			||||||
        listenWhen: (previous, current) => previous.content != current.content,
 | 
					        listenWhen: (previous, current) => previous.content != current.content,
 | 
				
			||||||
        listener: (context, state) => _controller.text = state.content,
 | 
					        listener: (context, state) {
 | 
				
			||||||
 | 
					          _controller.text = state.content;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        builder: (context, state) {
 | 
					        builder: (context, state) {
 | 
				
			||||||
 | 
					          widget._cellDataNotifier.value = state.content;
 | 
				
			||||||
          final urlEditor = Padding(
 | 
					          final urlEditor = Padding(
 | 
				
			||||||
            padding: EdgeInsets.only(
 | 
					            padding: EdgeInsets.only(
 | 
				
			||||||
              left: GridSize.cellContentInsets.left,
 | 
					              left: GridSize.cellContentInsets.left,
 | 
				
			||||||
@ -232,33 +238,41 @@ class _EditURLAccessoryState extends State<_EditURLAccessory>
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef CopyURLCellAccessoryBuilder
 | 
				
			||||||
 | 
					    = GridCellAccessoryBuilder<State<_CopyURLAccessory>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _CopyURLAccessory extends StatefulWidget {
 | 
					class _CopyURLAccessory extends StatefulWidget {
 | 
				
			||||||
  const _CopyURLAccessory({
 | 
					  const _CopyURLAccessory({
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
    required this.cellContext,
 | 
					    required this.cellDataNotifier,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final URLCellController cellContext;
 | 
					  final URLCellDataNotifier cellDataNotifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  State<StatefulWidget> createState() => _CopyURLAccessoryState();
 | 
					  State<_CopyURLAccessory> createState() => _CopyURLAccessoryState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _CopyURLAccessoryState extends State<_CopyURLAccessory>
 | 
					class _CopyURLAccessoryState extends State<_CopyURLAccessory>
 | 
				
			||||||
    with GridCellAccessoryState {
 | 
					    with GridCellAccessoryState {
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return svgWidget(
 | 
					    if (widget.cellDataNotifier.value.isNotEmpty) {
 | 
				
			||||||
 | 
					      return _URLAccessoryIconContainer(
 | 
				
			||||||
 | 
					        child: svgWidget(
 | 
				
			||||||
          "editor/copy",
 | 
					          "editor/copy",
 | 
				
			||||||
          color: AFThemeExtension.of(context).textColor,
 | 
					          color: AFThemeExtension.of(context).textColor,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return const SizedBox.shrink();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void onTap() {
 | 
					  void onTap() {
 | 
				
			||||||
    final content =
 | 
					    final content = widget.cellDataNotifier.value;
 | 
				
			||||||
        widget.cellContext.getCellData(loadIfNotExist: false)?.content;
 | 
					    if (content.isEmpty) {
 | 
				
			||||||
    if (content == null) {
 | 
					 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Clipboard.setData(ClipboardData(text: content));
 | 
					    Clipboard.setData(ClipboardData(text: content));
 | 
				
			||||||
@ -266,33 +280,46 @@ class _CopyURLAccessoryState extends State<_CopyURLAccessory>
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef VisitURLCellAccessoryBuilder
 | 
				
			||||||
 | 
					    = GridCellAccessoryBuilder<State<_VisitURLAccessory>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _VisitURLAccessory extends StatefulWidget {
 | 
					class _VisitURLAccessory extends StatefulWidget {
 | 
				
			||||||
  const _VisitURLAccessory({
 | 
					  const _VisitURLAccessory({
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
    required this.cellContext,
 | 
					    required this.cellDataNotifier,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final URLCellController cellContext;
 | 
					  final URLCellDataNotifier cellDataNotifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  State<StatefulWidget> createState() => _VisitURLAccessoryState();
 | 
					  State<_VisitURLAccessory> createState() => _VisitURLAccessoryState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _VisitURLAccessoryState extends State<_VisitURLAccessory>
 | 
					class _VisitURLAccessoryState extends State<_VisitURLAccessory>
 | 
				
			||||||
    with GridCellAccessoryState {
 | 
					    with GridCellAccessoryState {
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return svgWidget(
 | 
					    if (widget.cellDataNotifier.value.isNotEmpty) {
 | 
				
			||||||
 | 
					      return _URLAccessoryIconContainer(
 | 
				
			||||||
 | 
					        child: svgWidget(
 | 
				
			||||||
          "editor/link",
 | 
					          "editor/link",
 | 
				
			||||||
          color: AFThemeExtension.of(context).textColor,
 | 
					          color: AFThemeExtension.of(context).textColor,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return const SizedBox.shrink();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool enable() {
 | 
				
			||||||
 | 
					    return widget.cellDataNotifier.value.isNotEmpty;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void onTap() {
 | 
					  void onTap() {
 | 
				
			||||||
    final content =
 | 
					    final content = widget.cellDataNotifier.value;
 | 
				
			||||||
        widget.cellContext.getCellData(loadIfNotExist: false)?.content;
 | 
					    if (content.isEmpty) {
 | 
				
			||||||
    if (content == null) {
 | 
					 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    final shouldAddScheme =
 | 
					    final shouldAddScheme =
 | 
				
			||||||
@ -301,3 +328,21 @@ class _VisitURLAccessoryState extends State<_VisitURLAccessory>
 | 
				
			|||||||
    canLaunchUrlString(url).then((value) => launchUrlString(url));
 | 
					    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,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user