mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-25 07:07:32 -04:00
feat: hide url cell accessory when the content is empty (#2754)
This commit is contained in:
parent
4ce94a9ceb
commit
2ecd0a67ad
2 changed files with 106 additions and 59 deletions
|
@ -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…
Add table
Add a link
Reference in a new issue