chore: various database UI fixes (#4077)

* chore: only activate row detail from primary field

* chore: fix create filter and sort list

* chore: allow reordering rows when active filter

* chore: reduce animations in tab bar

* chore: url accessory tooltip

* feat: use number keyboard for number cell inputs

* chore: mobile grid padding adjustments

* chore: field cell redesign and first field cannot be reordered

* fix: deal with empty fields

* chore: improve appearance of card action sheet
This commit is contained in:
Richard Shiue 2023-12-04 22:58:02 +08:00 committed by GitHub
parent a070ed2441
commit d4cef2e866
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 172 additions and 90 deletions

View File

@ -14,6 +14,7 @@ Future<T?> showMobileBottomSheet<T>(
bool showHeader = false, bool showHeader = false,
bool showCloseButton = false, bool showCloseButton = false,
String title = '', // only works if showHeader is true String title = '', // only works if showHeader is true
Color? backgroundColor,
}) async { }) async {
assert(() { assert(() {
if (showCloseButton || title.isNotEmpty) assert(showHeader); if (showCloseButton || title.isNotEmpty) assert(showHeader);
@ -26,6 +27,7 @@ Future<T?> showMobileBottomSheet<T>(
enableDrag: isDragEnabled, enableDrag: isDragEnabled,
useSafeArea: true, useSafeArea: true,
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
backgroundColor: backgroundColor,
shape: shape ?? shape: shape ??
const RoundedRectangleBorder( const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical( borderRadius: BorderRadius.vertical(

View File

@ -51,6 +51,10 @@ class _RowDetailNumberCellState
], ],
child: TextField( child: TextField(
controller: _controller, controller: _controller,
keyboardType: const TextInputType.numberWithOptions(
signed: true,
decimal: true,
),
focusNode: focusNode, focusNode: focusNode,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 16), style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 16),
decoration: InputDecoration( decoration: InputDecoration(

View File

@ -1,7 +1,6 @@
import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart'; import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/mobile/presentation/widgets/show_flowy_mobile_bottom_sheet.dart';
import 'package:appflowy/plugins/database_view/application/cell/cell_service.dart'; import 'package:appflowy/plugins/database_view/application/cell/cell_service.dart';
import 'package:appflowy/plugins/database_view/application/database_controller.dart'; import 'package:appflowy/plugins/database_view/application/database_controller.dart';
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart'; import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
@ -139,15 +138,16 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
} }
void _showCardActions(BuildContext context) { void _showCardActions(BuildContext context) {
showFlowyMobileBottomSheet( showMobileBottomSheet(
context, context,
title: LocaleKeys.board_cardActions.tr(), backgroundColor: Theme.of(context).colorScheme.background,
builder: (_) => Row( padding: const EdgeInsets.only(top: 4, bottom: 32),
builder: (_) => Column(
mainAxisSize: MainAxisSize.min,
children: [ children: [
Expanded( Padding(
child: BottomSheetActionWidget( padding: const EdgeInsets.symmetric(horizontal: 8.0),
svg: FlowySvgs.copy_s, child: _CardActionButton(
text: LocaleKeys.button_duplicate.tr(),
onTap: () { onTap: () {
final rowId = _bloc.state.currentRowId; final rowId = _bloc.state.currentRowId;
if (rowId == null) { if (rowId == null) {
@ -162,13 +162,14 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
}, },
icon: FlowySvgs.copy_s,
text: LocaleKeys.button_duplicate.tr(),
), ),
), ),
const HSpace(8), const Divider(height: 9),
Expanded( Padding(
child: BottomSheetActionWidget( padding: const EdgeInsets.symmetric(horizontal: 8.0),
svg: FlowySvgs.m_delete_m, child: _CardActionButton(
text: LocaleKeys.button_delete.tr(),
onTap: () { onTap: () {
final rowId = _bloc.state.currentRowId; final rowId = _bloc.state.currentRowId;
if (rowId == null) { if (rowId == null) {
@ -183,14 +184,51 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
}, },
icon: FlowySvgs.m_delete_m,
text: LocaleKeys.button_delete.tr(),
color: Theme.of(context).colorScheme.error,
), ),
), ),
const Divider(height: 9),
], ],
), ),
); );
} }
} }
class _CardActionButton extends StatelessWidget {
const _CardActionButton({
required this.onTap,
required this.icon,
required this.text,
this.color,
});
final VoidCallback onTap;
final FlowySvgData icon;
final String text;
final Color? color;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Container(
height: 44,
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
children: [
FlowySvg(icon, size: const Size.square(20), color: color),
const HSpace(8),
FlowyText(text, fontSize: 15, color: color),
],
),
),
);
}
}
class RowDetailFab extends StatelessWidget { class RowDetailFab extends StatelessWidget {
const RowDetailFab({ const RowDetailFab({
super.key, super.key,
@ -352,10 +390,10 @@ class MobileRowDetailPageContentState
placeholder: LocaleKeys.grid_row_titlePlaceholder.tr(), placeholder: LocaleKeys.grid_row_titlePlaceholder.tr(),
textStyle: textStyle:
Theme.of(context).textTheme.bodyMedium?.copyWith( Theme.of(context).textTheme.bodyMedium?.copyWith(
fontSize: 22, fontSize: 23,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
cellPadding: const EdgeInsets.symmetric(vertical: 8), cellPadding: const EdgeInsets.symmetric(vertical: 9),
useRoundedBorder: false, useRoundedBorder: false,
); );
@ -366,7 +404,7 @@ class MobileRowDetailPageContentState
); );
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 18), padding: const EdgeInsets.symmetric(horizontal: 16),
child: cellBuilder.build( child: cellBuilder.build(
cellContext, cellContext,
style: cellStyle, style: cellStyle,
@ -379,10 +417,10 @@ class MobileRowDetailPageContentState
), ),
Expanded( Expanded(
child: ListView( child: ListView(
padding: const EdgeInsets.only(top: 8, bottom: 100), padding: const EdgeInsets.only(top: 9, bottom: 100),
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 18), padding: const EdgeInsets.symmetric(horizontal: 16),
child: MobileRowPropertyList( child: MobileRowPropertyList(
cellBuilder: cellBuilder, cellBuilder: cellBuilder,
viewId: viewId, viewId: viewId,
@ -390,7 +428,7 @@ class MobileRowDetailPageContentState
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.fromLTRB(6, 6, 16, 0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [

View File

@ -38,11 +38,15 @@ class _CheckboxCellState extends GridCellState<MobileCheckboxCell> {
builder: (context, state) { builder: (context, state) {
return Align( return Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
// TODO(yijing): improve icon here child: Padding(
child: FlowySvg( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
state.isSelected ? FlowySvgs.checkbox_s : FlowySvgs.uncheck_s, child: FlowySvg(
color: Theme.of(context).colorScheme.onBackground, state.isSelected
size: const Size.square(24), ? FlowySvgs.check_filled_s
: FlowySvgs.uncheck_s,
blendMode: BlendMode.dst,
size: const Size.square(24),
),
), ),
); );
}, },

View File

@ -50,11 +50,13 @@ class _NumberCellState extends GridEditableTextCell<MobileNumberCell> {
child: TextField( child: TextField(
controller: _controller, controller: _controller,
focusNode: focusNode, focusNode: focusNode,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15),
decoration: InputDecoration( decoration: InputDecoration(
enabledBorder: InputBorder.none, enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none, focusedBorder: InputBorder.none,
hintText: widget.hintText, hintText: widget.hintText,
contentPadding: EdgeInsets.zero, contentPadding:
const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
isCollapsed: true, isCollapsed: true,
), ),
// close keyboard when tapping outside of the text field // close keyboard when tapping outside of the text field

View File

@ -56,12 +56,13 @@ class _MobileTextCellState extends GridEditableTextCell<MobileTextCell> {
child: TextField( child: TextField(
controller: _controller, controller: _controller,
focusNode: focusNode, focusNode: focusNode,
style: widget.cellStyle.textStyle, style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15),
decoration: InputDecoration( decoration: InputDecoration(
enabledBorder: InputBorder.none, enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none, focusedBorder: InputBorder.none,
hintText: widget.cellStyle.placeholder, hintText: widget.cellStyle.placeholder,
contentPadding: EdgeInsets.zero, contentPadding:
const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
isCollapsed: true, isCollapsed: true,
), ),
onTapOutside: (event) => onTapOutside: (event) =>

View File

@ -1,6 +1,7 @@
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/plugins/database_view/widgets/row/cell_builder.dart'; import 'package:appflowy/plugins/database_view/widgets/row/cell_builder.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/timestamp_cell/timestamp_cell_bloc.dart'; import 'package:appflowy/plugins/database_view/widgets/row/cells/timestamp_cell/timestamp_cell_bloc.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -36,7 +37,13 @@ class _TimestampCellState extends GridCellState<MobileTimestampCell> {
builder: (context, state) { builder: (context, state) {
return Align( return Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text(state.dateStr), child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
child: FlowyText(
state.dateStr,
fontSize: 15,
),
),
); );
}, },
), ),

View File

@ -59,7 +59,8 @@ class _GridURLCellState extends GridCellState<MobileURLCell> {
enabledBorder: InputBorder.none, enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none, focusedBorder: InputBorder.none,
hintText: widget.hintText, hintText: widget.hintText,
contentPadding: EdgeInsets.zero, contentPadding:
const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
isCollapsed: true, isCollapsed: true,
), ),
// close keyboard when tapping outside of the text field // close keyboard when tapping outside of the text field

View File

@ -64,16 +64,13 @@ class GridBloc extends Bloc<GridEvent, GridState> {
}, },
didReceveFilters: (List<FilterInfo> filters) { didReceveFilters: (List<FilterInfo> filters) {
emit( emit(
state.copyWith( state.copyWith(filters: filters),
reorderable: filters.isEmpty && state.sorts.isEmpty,
filters: filters,
),
); );
}, },
didReceveSorts: (List<SortInfo> sorts) { didReceveSorts: (List<SortInfo> sorts) {
emit( emit(
state.copyWith( state.copyWith(
reorderable: sorts.isEmpty && state.filters.isEmpty, reorderable: sorts.isEmpty,
sorts: sorts, sorts: sorts,
), ),
); );

View File

@ -124,6 +124,7 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate {
) { ) {
return Container( return Container(
padding: const EdgeInsets.only(bottom: 4), padding: const EdgeInsets.only(bottom: 4),
color: Theme.of(context).cardColor,
height: fixHeight, height: fixHeight,
child: FlowyTextField( child: FlowyTextField(
hintText: LocaleKeys.grid_settings_filterBy.tr(), hintText: LocaleKeys.grid_settings_filterBy.tr(),

View File

@ -16,7 +16,7 @@ class GridAddRowButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FlowyButton( return FlowyButton(
text: FlowyText.medium( text: FlowyText(
LocaleKeys.grid_row_newRow.tr(), LocaleKeys.grid_row_newRow.tr(),
color: Theme.of(context).hintColor, color: Theme.of(context).hintColor,
), ),

View File

@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/database/field/bottom_sheet_create_field.dart'; import 'package:appflowy/mobile/presentation/database/field/bottom_sheet_create_field.dart';
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart'; import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
import 'package:appflowy/plugins/database_view/application/field/field_info.dart';
import 'package:appflowy/plugins/database_view/grid/application/grid_bloc.dart'; import 'package:appflowy/plugins/database_view/grid/application/grid_bloc.dart';
import 'package:appflowy/plugins/database_view/grid/application/grid_header_bloc.dart'; import 'package:appflowy/plugins/database_view/grid/application/grid_header_bloc.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/mobile_field_cell.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/mobile_field_cell.dart';
@ -92,7 +93,13 @@ class _GridHeaderState extends State<_GridHeader> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<GridHeaderBloc, GridHeaderState>( return BlocBuilder<GridHeaderBloc, GridHeaderState>(
builder: (context, state) { builder: (context, state) {
final cells = state.fields final fields = [...state.fields];
FieldInfo? firstField;
if (PlatformExtension.isMobile && fields.isNotEmpty) {
firstField = fields.removeAt(0);
}
final cells = fields
.map( .map(
(fieldInfo) => PlatformExtension.isDesktop (fieldInfo) => PlatformExtension.isDesktop
? GridFieldCell( ? GridFieldCell(
@ -129,7 +136,7 @@ class _GridHeaderState extends State<_GridHeader> {
child: child, child: child,
), ),
draggingWidgetOpacity: 0, draggingWidgetOpacity: 0,
header: const _CellLeading(), header: _cellLeading(firstField),
needsLongPressDraggable: PlatformExtension.isMobile, needsLongPressDraggable: PlatformExtension.isMobile,
footer: _CellTrailing(viewId: widget.viewId), footer: _CellTrailing(viewId: widget.viewId),
onReorder: (int oldIndex, int newIndex) { onReorder: (int oldIndex, int newIndex) {
@ -162,16 +169,25 @@ class _GridHeaderState extends State<_GridHeader> {
.add(GridHeaderEvent.moveField(field, oldIndex, newIndex)); .add(GridHeaderEvent.moveField(field, oldIndex, newIndex));
} }
} }
}
class _CellLeading extends StatelessWidget { Widget _cellLeading(FieldInfo? fieldInfo) {
const _CellLeading({Key? key}) : super(key: key); if (PlatformExtension.isDesktop) {
return SizedBox(width: GridSize.leadingHeaderPadding);
@override } else {
Widget build(BuildContext context) { return Row(
return SizedBox( mainAxisSize: MainAxisSize.min,
width: GridSize.leadingHeaderPadding, children: [
); SizedBox(width: GridSize.leadingHeaderPadding),
if (fieldInfo != null)
MobileFieldButton(
key: _getKeyById(fieldInfo.id),
viewId: widget.viewId,
fieldController: widget.fieldController,
fieldInfo: fieldInfo,
),
],
);
}
} }
} }
@ -222,10 +238,11 @@ class _CreateFieldButtonState extends State<CreateFieldButton> {
return FlowyButton( return FlowyButton(
margin: PlatformExtension.isDesktop margin: PlatformExtension.isDesktop
? GridSize.cellContentInsets ? GridSize.cellContentInsets
: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), : const EdgeInsets.symmetric(vertical: 14, horizontal: 12),
radius: BorderRadius.zero, radius: BorderRadius.zero,
text: FlowyText.medium( text: FlowyText(
LocaleKeys.grid_field_newProperty.tr(), LocaleKeys.grid_field_newProperty.tr(),
fontSize: 15,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
color: PlatformExtension.isDesktop ? null : Theme.of(context).hintColor, color: PlatformExtension.isDesktop ? null : Theme.of(context).hintColor,
), ),
@ -245,6 +262,7 @@ class _CreateFieldButtonState extends State<CreateFieldButton> {
}, },
leftIcon: FlowySvg( leftIcon: FlowySvg(
FlowySvgs.add_s, FlowySvgs.add_s,
size: const Size.square(18),
color: PlatformExtension.isDesktop ? null : Theme.of(context).hintColor, color: PlatformExtension.isDesktop ? null : Theme.of(context).hintColor,
), ),
); );

View File

@ -27,31 +27,22 @@ class MobileFieldButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return SizedBox(
width: fieldInfo.fieldSettings!.width.toDouble(), width: fieldInfo.fieldSettings!.width.toDouble(),
decoration: BoxDecoration(
border: Border(
right: BorderSide(
color: Theme.of(context).dividerColor,
width: 1.0,
),
),
),
child: FlowyButton( child: FlowyButton(
onTap: () { onTap: () => showEditFieldScreen(context, viewId, fieldInfo),
showEditFieldScreen(context, viewId, fieldInfo);
},
radius: BorderRadius.zero, radius: BorderRadius.zero,
margin: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), margin: const EdgeInsets.symmetric(vertical: 14, horizontal: 12),
leftIconSize: const Size.square(18),
leftIcon: FlowySvg( leftIcon: FlowySvg(
fieldInfo.fieldType.icon(), fieldInfo.fieldType.icon(),
color: Theme.of(context).hintColor, size: const Size.square(18),
), ),
text: FlowyText.medium( text: FlowyText(
fieldInfo.name, fieldInfo.name,
fontSize: 15,
maxLines: maxLines, maxLines: maxLines,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
color: Theme.of(context).hintColor,
), ),
), ),
); );

View File

@ -71,14 +71,9 @@ class _MobileGridRowState extends State<MobileGridRow> {
children: [ children: [
SizedBox(width: GridSize.leadingHeaderPadding), SizedBox(width: GridSize.leadingHeaderPadding),
Expanded( Expanded(
child: InkWell( child: RowContent(
onTap: () => widget.openDetailPage(context), builder: _cellBuilder,
child: IgnorePointer( onExpand: () => widget.openDetailPage(context),
child: RowContent(
builder: _cellBuilder,
onExpand: () => widget.openDetailPage(context),
),
),
), ),
), ),
], ],
@ -155,9 +150,8 @@ class RowContent extends StatelessWidget {
return MobileCellContainer( return MobileCellContainer(
width: cellId.fieldInfo.fieldSettings!.width.toDouble(), width: cellId.fieldInfo.fieldSettings!.width.toDouble(),
isPrimary: cellId.fieldInfo.field.isPrimary, isPrimary: cellId.fieldInfo.field.isPrimary,
accessoryBuilder: (buildContext) { accessoryBuilder: (_) => [],
return []; onPrimaryFieldCellTap: onExpand,
},
child: child, child: child,
); );
}, },

View File

@ -124,6 +124,7 @@ class _SortTextFieldDelegate extends SliverPersistentHeaderDelegate {
) { ) {
return Container( return Container(
padding: const EdgeInsets.only(bottom: 4), padding: const EdgeInsets.only(bottom: 4),
color: Theme.of(context).cardColor,
height: fixHeight, height: fixHeight,
child: FlowyTextField( child: FlowyTextField(
hintText: LocaleKeys.grid_settings_sortBy.tr(), hintText: LocaleKeys.grid_settings_sortBy.tr(),

View File

@ -77,11 +77,7 @@ class _DatabaseTabBarViewState extends State<DatabaseTabBarView> {
BlocListener<DatabaseTabBarBloc, DatabaseTabBarState>( BlocListener<DatabaseTabBarBloc, DatabaseTabBarState>(
listenWhen: (p, c) => p.selectedIndex != c.selectedIndex, listenWhen: (p, c) => p.selectedIndex != c.selectedIndex,
listener: (context, state) { listener: (context, state) {
_pageController?.animateToPage( _pageController?.jumpToPage(state.selectedIndex);
state.selectedIndex,
duration: const Duration(milliseconds: 300),
curve: Curves.ease,
);
}, },
), ),
], ],

View File

@ -154,10 +154,12 @@ class _DateCellState extends GridCellState<GridDateCell> {
); );
} else { } else {
return FlowyButton( return FlowyButton(
radius: BorderRadius.zero,
hoverColor: Colors.transparent,
text: Container( text: Container(
alignment: alignment, alignment: alignment,
padding: padding, padding: padding,
child: FlowyText.medium(text, color: color), child: FlowyText(text, color: color, fontSize: 15),
), ),
onTap: () { onTap: () {
showMobileBottomSheet( showMobileBottomSheet(

View File

@ -13,6 +13,7 @@ class MobileCellContainer extends StatelessWidget {
final AccessoryBuilder? accessoryBuilder; final AccessoryBuilder? accessoryBuilder;
final double width; final double width;
final bool isPrimary; final bool isPrimary;
final VoidCallback? onPrimaryFieldCellTap;
const MobileCellContainer({ const MobileCellContainer({
super.key, super.key,
@ -20,6 +21,7 @@ class MobileCellContainer extends StatelessWidget {
required this.width, required this.width,
required this.isPrimary, required this.isPrimary,
this.accessoryBuilder, this.accessoryBuilder,
this.onPrimaryFieldCellTap,
}); });
@override @override
@ -48,9 +50,17 @@ class MobileCellContainer extends StatelessWidget {
} }
} }
if (isPrimary) {
container = IgnorePointer(child: container);
}
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
if (isPrimary) {
onPrimaryFieldCellTap?.call();
return;
}
if (!isFocus) { if (!isFocus) {
child.requestFocus.notify(); child.requestFocus.notify();
} }

View File

@ -246,6 +246,8 @@ class _SelectOptionWrapState extends State<SelectOptionWrap> {
); );
} else { } else {
return FlowyButton( return FlowyButton(
hoverColor: Colors.transparent,
radius: BorderRadius.zero,
text: Padding( text: Padding(
padding: widget.cellStyle.cellPadding ?? GridSize.cellContentInsets, padding: widget.cellStyle.cellPadding ?? GridSize.cellContentInsets,
child: _buildMobileOptions(isInRowDetail: false), child: _buildMobileOptions(isInRowDetail: false),

View File

@ -6,6 +6,7 @@ import 'package:appflowy/plugins/database_view/application/cell/cell_controller_
import 'package:appflowy/workspace/presentation/home/toast.dart'; import 'package:appflowy/workspace/presentation/home/toast.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -200,10 +201,14 @@ class _CopyURLAccessoryState extends State<_CopyURLAccessory>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (widget.cellDataNotifier.value.isNotEmpty) { if (widget.cellDataNotifier.value.isNotEmpty) {
return _URLAccessoryIconContainer( return FlowyTooltip(
child: FlowySvg( message: LocaleKeys.tooltip_urlCopyAccessory.tr(),
FlowySvgs.copy_s, preferBelow: false,
color: AFThemeExtension.of(context).textColor, child: _URLAccessoryIconContainer(
child: FlowySvg(
FlowySvgs.copy_s,
color: AFThemeExtension.of(context).textColor,
),
), ),
); );
} else { } else {
@ -242,10 +247,14 @@ class _VisitURLAccessoryState extends State<_VisitURLAccessory>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (widget.cellDataNotifier.value.isNotEmpty) { if (widget.cellDataNotifier.value.isNotEmpty) {
return _URLAccessoryIconContainer( return FlowyTooltip(
child: FlowySvg( message: LocaleKeys.tooltip_urlLaunchAccessory.tr(),
FlowySvgs.attach_s, preferBelow: false,
color: AFThemeExtension.of(context).textColor, child: _URLAccessoryIconContainer(
child: FlowySvg(
FlowySvgs.attach_s,
color: AFThemeExtension.of(context).textColor,
),
), ),
); );
} else { } else {

View File

@ -177,7 +177,9 @@
"dragRow": "Long press to reorder the row", "dragRow": "Long press to reorder the row",
"viewDataBase": "View database", "viewDataBase": "View database",
"referencePage": "This {name} is referenced", "referencePage": "This {name} is referenced",
"addBlockBelow": "Add a block below" "addBlockBelow": "Add a block below",
"urlLaunchAccessory": "Open in browser",
"urlCopyAccessory": "Copy URL"
}, },
"sideBar": { "sideBar": {
"closeSidebar": "Close side bar", "closeSidebar": "Close side bar",