mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
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:
parent
a070ed2441
commit
d4cef2e866
@ -14,6 +14,7 @@ Future<T?> showMobileBottomSheet<T>(
|
||||
bool showHeader = false,
|
||||
bool showCloseButton = false,
|
||||
String title = '', // only works if showHeader is true
|
||||
Color? backgroundColor,
|
||||
}) async {
|
||||
assert(() {
|
||||
if (showCloseButton || title.isNotEmpty) assert(showHeader);
|
||||
@ -26,6 +27,7 @@ Future<T?> showMobileBottomSheet<T>(
|
||||
enableDrag: isDragEnabled,
|
||||
useSafeArea: true,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
backgroundColor: backgroundColor,
|
||||
shape: shape ??
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
|
@ -51,6 +51,10 @@ class _RowDetailNumberCellState
|
||||
],
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
keyboardType: const TextInputType.numberWithOptions(
|
||||
signed: true,
|
||||
decimal: true,
|
||||
),
|
||||
focusNode: focusNode,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 16),
|
||||
decoration: InputDecoration(
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.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/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/database_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) {
|
||||
showFlowyMobileBottomSheet(
|
||||
showMobileBottomSheet(
|
||||
context,
|
||||
title: LocaleKeys.board_cardActions.tr(),
|
||||
builder: (_) => Row(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
padding: const EdgeInsets.only(top: 4, bottom: 32),
|
||||
builder: (_) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Expanded(
|
||||
child: BottomSheetActionWidget(
|
||||
svg: FlowySvgs.copy_s,
|
||||
text: LocaleKeys.button_duplicate.tr(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: _CardActionButton(
|
||||
onTap: () {
|
||||
final rowId = _bloc.state.currentRowId;
|
||||
if (rowId == null) {
|
||||
@ -162,13 +162,14 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
},
|
||||
icon: FlowySvgs.copy_s,
|
||||
text: LocaleKeys.button_duplicate.tr(),
|
||||
),
|
||||
),
|
||||
const HSpace(8),
|
||||
Expanded(
|
||||
child: BottomSheetActionWidget(
|
||||
svg: FlowySvgs.m_delete_m,
|
||||
text: LocaleKeys.button_delete.tr(),
|
||||
const Divider(height: 9),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: _CardActionButton(
|
||||
onTap: () {
|
||||
final rowId = _bloc.state.currentRowId;
|
||||
if (rowId == null) {
|
||||
@ -183,14 +184,51 @@ class _MobileRowDetailPageState extends State<MobileRowDetailPage> {
|
||||
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 {
|
||||
const RowDetailFab({
|
||||
super.key,
|
||||
@ -352,10 +390,10 @@ class MobileRowDetailPageContentState
|
||||
placeholder: LocaleKeys.grid_row_titlePlaceholder.tr(),
|
||||
textStyle:
|
||||
Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
fontSize: 22,
|
||||
fontSize: 23,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
cellPadding: const EdgeInsets.symmetric(vertical: 8),
|
||||
cellPadding: const EdgeInsets.symmetric(vertical: 9),
|
||||
useRoundedBorder: false,
|
||||
);
|
||||
|
||||
@ -366,7 +404,7 @@ class MobileRowDetailPageContentState
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: cellBuilder.build(
|
||||
cellContext,
|
||||
style: cellStyle,
|
||||
@ -379,10 +417,10 @@ class MobileRowDetailPageContentState
|
||||
),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.only(top: 8, bottom: 100),
|
||||
padding: const EdgeInsets.only(top: 9, bottom: 100),
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: MobileRowPropertyList(
|
||||
cellBuilder: cellBuilder,
|
||||
viewId: viewId,
|
||||
@ -390,7 +428,7 @@ class MobileRowDetailPageContentState
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
padding: const EdgeInsets.fromLTRB(6, 6, 16, 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
@ -38,11 +38,15 @@ class _CheckboxCellState extends GridCellState<MobileCheckboxCell> {
|
||||
builder: (context, state) {
|
||||
return Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
// TODO(yijing): improve icon here
|
||||
child: FlowySvg(
|
||||
state.isSelected ? FlowySvgs.checkbox_s : FlowySvgs.uncheck_s,
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
size: const Size.square(24),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
||||
child: FlowySvg(
|
||||
state.isSelected
|
||||
? FlowySvgs.check_filled_s
|
||||
: FlowySvgs.uncheck_s,
|
||||
blendMode: BlendMode.dst,
|
||||
size: const Size.square(24),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -50,11 +50,13 @@ class _NumberCellState extends GridEditableTextCell<MobileNumberCell> {
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
focusNode: focusNode,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15),
|
||||
decoration: InputDecoration(
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
hintText: widget.hintText,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
||||
isCollapsed: true,
|
||||
),
|
||||
// close keyboard when tapping outside of the text field
|
||||
|
@ -56,12 +56,13 @@ class _MobileTextCellState extends GridEditableTextCell<MobileTextCell> {
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
focusNode: focusNode,
|
||||
style: widget.cellStyle.textStyle,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontSize: 15),
|
||||
decoration: InputDecoration(
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
hintText: widget.cellStyle.placeholder,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
||||
isCollapsed: true,
|
||||
),
|
||||
onTapOutside: (event) =>
|
||||
|
@ -1,6 +1,7 @@
|
||||
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/cells/timestamp_cell/timestamp_cell_bloc.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@ -36,7 +37,13 @@ class _TimestampCellState extends GridCellState<MobileTimestampCell> {
|
||||
builder: (context, state) {
|
||||
return Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(state.dateStr),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
||||
child: FlowyText(
|
||||
state.dateStr,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -59,7 +59,8 @@ class _GridURLCellState extends GridCellState<MobileURLCell> {
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
hintText: widget.hintText,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
||||
isCollapsed: true,
|
||||
),
|
||||
// close keyboard when tapping outside of the text field
|
||||
|
@ -64,16 +64,13 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
},
|
||||
didReceveFilters: (List<FilterInfo> filters) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
reorderable: filters.isEmpty && state.sorts.isEmpty,
|
||||
filters: filters,
|
||||
),
|
||||
state.copyWith(filters: filters),
|
||||
);
|
||||
},
|
||||
didReceveSorts: (List<SortInfo> sorts) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
reorderable: sorts.isEmpty && state.filters.isEmpty,
|
||||
reorderable: sorts.isEmpty,
|
||||
sorts: sorts,
|
||||
),
|
||||
);
|
||||
|
@ -124,6 +124,7 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate {
|
||||
) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(bottom: 4),
|
||||
color: Theme.of(context).cardColor,
|
||||
height: fixHeight,
|
||||
child: FlowyTextField(
|
||||
hintText: LocaleKeys.grid_settings_filterBy.tr(),
|
||||
|
@ -16,7 +16,7 @@ class GridAddRowButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FlowyButton(
|
||||
text: FlowyText.medium(
|
||||
text: FlowyText(
|
||||
LocaleKeys.grid_row_newRow.tr(),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
|
@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.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/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_header_bloc.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) {
|
||||
return BlocBuilder<GridHeaderBloc, GridHeaderState>(
|
||||
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(
|
||||
(fieldInfo) => PlatformExtension.isDesktop
|
||||
? GridFieldCell(
|
||||
@ -129,7 +136,7 @@ class _GridHeaderState extends State<_GridHeader> {
|
||||
child: child,
|
||||
),
|
||||
draggingWidgetOpacity: 0,
|
||||
header: const _CellLeading(),
|
||||
header: _cellLeading(firstField),
|
||||
needsLongPressDraggable: PlatformExtension.isMobile,
|
||||
footer: _CellTrailing(viewId: widget.viewId),
|
||||
onReorder: (int oldIndex, int newIndex) {
|
||||
@ -162,16 +169,25 @@ class _GridHeaderState extends State<_GridHeader> {
|
||||
.add(GridHeaderEvent.moveField(field, oldIndex, newIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _CellLeading extends StatelessWidget {
|
||||
const _CellLeading({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: GridSize.leadingHeaderPadding,
|
||||
);
|
||||
Widget _cellLeading(FieldInfo? fieldInfo) {
|
||||
if (PlatformExtension.isDesktop) {
|
||||
return SizedBox(width: GridSize.leadingHeaderPadding);
|
||||
} else {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
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(
|
||||
margin: PlatformExtension.isDesktop
|
||||
? GridSize.cellContentInsets
|
||||
: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
|
||||
: const EdgeInsets.symmetric(vertical: 14, horizontal: 12),
|
||||
radius: BorderRadius.zero,
|
||||
text: FlowyText.medium(
|
||||
text: FlowyText(
|
||||
LocaleKeys.grid_field_newProperty.tr(),
|
||||
fontSize: 15,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: PlatformExtension.isDesktop ? null : Theme.of(context).hintColor,
|
||||
),
|
||||
@ -245,6 +262,7 @@ class _CreateFieldButtonState extends State<CreateFieldButton> {
|
||||
},
|
||||
leftIcon: FlowySvg(
|
||||
FlowySvgs.add_s,
|
||||
size: const Size.square(18),
|
||||
color: PlatformExtension.isDesktop ? null : Theme.of(context).hintColor,
|
||||
),
|
||||
);
|
||||
|
@ -27,31 +27,22 @@ class MobileFieldButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
return SizedBox(
|
||||
width: fieldInfo.fieldSettings!.width.toDouble(),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
right: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: FlowyButton(
|
||||
onTap: () {
|
||||
showEditFieldScreen(context, viewId, fieldInfo);
|
||||
},
|
||||
onTap: () => showEditFieldScreen(context, viewId, fieldInfo),
|
||||
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(
|
||||
fieldInfo.fieldType.icon(),
|
||||
color: Theme.of(context).hintColor,
|
||||
size: const Size.square(18),
|
||||
),
|
||||
text: FlowyText.medium(
|
||||
text: FlowyText(
|
||||
fieldInfo.name,
|
||||
fontSize: 15,
|
||||
maxLines: maxLines,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -71,14 +71,9 @@ class _MobileGridRowState extends State<MobileGridRow> {
|
||||
children: [
|
||||
SizedBox(width: GridSize.leadingHeaderPadding),
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
onTap: () => widget.openDetailPage(context),
|
||||
child: IgnorePointer(
|
||||
child: RowContent(
|
||||
builder: _cellBuilder,
|
||||
onExpand: () => widget.openDetailPage(context),
|
||||
),
|
||||
),
|
||||
child: RowContent(
|
||||
builder: _cellBuilder,
|
||||
onExpand: () => widget.openDetailPage(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -155,9 +150,8 @@ class RowContent extends StatelessWidget {
|
||||
return MobileCellContainer(
|
||||
width: cellId.fieldInfo.fieldSettings!.width.toDouble(),
|
||||
isPrimary: cellId.fieldInfo.field.isPrimary,
|
||||
accessoryBuilder: (buildContext) {
|
||||
return [];
|
||||
},
|
||||
accessoryBuilder: (_) => [],
|
||||
onPrimaryFieldCellTap: onExpand,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
|
@ -124,6 +124,7 @@ class _SortTextFieldDelegate extends SliverPersistentHeaderDelegate {
|
||||
) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(bottom: 4),
|
||||
color: Theme.of(context).cardColor,
|
||||
height: fixHeight,
|
||||
child: FlowyTextField(
|
||||
hintText: LocaleKeys.grid_settings_sortBy.tr(),
|
||||
|
@ -77,11 +77,7 @@ class _DatabaseTabBarViewState extends State<DatabaseTabBarView> {
|
||||
BlocListener<DatabaseTabBarBloc, DatabaseTabBarState>(
|
||||
listenWhen: (p, c) => p.selectedIndex != c.selectedIndex,
|
||||
listener: (context, state) {
|
||||
_pageController?.animateToPage(
|
||||
state.selectedIndex,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.ease,
|
||||
);
|
||||
_pageController?.jumpToPage(state.selectedIndex);
|
||||
},
|
||||
),
|
||||
],
|
||||
|
@ -154,10 +154,12 @@ class _DateCellState extends GridCellState<GridDateCell> {
|
||||
);
|
||||
} else {
|
||||
return FlowyButton(
|
||||
radius: BorderRadius.zero,
|
||||
hoverColor: Colors.transparent,
|
||||
text: Container(
|
||||
alignment: alignment,
|
||||
padding: padding,
|
||||
child: FlowyText.medium(text, color: color),
|
||||
child: FlowyText(text, color: color, fontSize: 15),
|
||||
),
|
||||
onTap: () {
|
||||
showMobileBottomSheet(
|
||||
|
@ -13,6 +13,7 @@ class MobileCellContainer extends StatelessWidget {
|
||||
final AccessoryBuilder? accessoryBuilder;
|
||||
final double width;
|
||||
final bool isPrimary;
|
||||
final VoidCallback? onPrimaryFieldCellTap;
|
||||
|
||||
const MobileCellContainer({
|
||||
super.key,
|
||||
@ -20,6 +21,7 @@ class MobileCellContainer extends StatelessWidget {
|
||||
required this.width,
|
||||
required this.isPrimary,
|
||||
this.accessoryBuilder,
|
||||
this.onPrimaryFieldCellTap,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -48,9 +50,17 @@ class MobileCellContainer extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
if (isPrimary) {
|
||||
container = IgnorePointer(child: container);
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {
|
||||
if (isPrimary) {
|
||||
onPrimaryFieldCellTap?.call();
|
||||
return;
|
||||
}
|
||||
if (!isFocus) {
|
||||
child.requestFocus.notify();
|
||||
}
|
||||
|
@ -246,6 +246,8 @@ class _SelectOptionWrapState extends State<SelectOptionWrap> {
|
||||
);
|
||||
} else {
|
||||
return FlowyButton(
|
||||
hoverColor: Colors.transparent,
|
||||
radius: BorderRadius.zero,
|
||||
text: Padding(
|
||||
padding: widget.cellStyle.cellPadding ?? GridSize.cellContentInsets,
|
||||
child: _buildMobileOptions(isInRowDetail: false),
|
||||
|
@ -6,6 +6,7 @@ import 'package:appflowy/plugins/database_view/application/cell/cell_controller_
|
||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||
import 'package:easy_localization/easy_localization.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/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -200,10 +201,14 @@ class _CopyURLAccessoryState extends State<_CopyURLAccessory>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.cellDataNotifier.value.isNotEmpty) {
|
||||
return _URLAccessoryIconContainer(
|
||||
child: FlowySvg(
|
||||
FlowySvgs.copy_s,
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
return FlowyTooltip(
|
||||
message: LocaleKeys.tooltip_urlCopyAccessory.tr(),
|
||||
preferBelow: false,
|
||||
child: _URLAccessoryIconContainer(
|
||||
child: FlowySvg(
|
||||
FlowySvgs.copy_s,
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@ -242,10 +247,14 @@ class _VisitURLAccessoryState extends State<_VisitURLAccessory>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.cellDataNotifier.value.isNotEmpty) {
|
||||
return _URLAccessoryIconContainer(
|
||||
child: FlowySvg(
|
||||
FlowySvgs.attach_s,
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
return FlowyTooltip(
|
||||
message: LocaleKeys.tooltip_urlLaunchAccessory.tr(),
|
||||
preferBelow: false,
|
||||
child: _URLAccessoryIconContainer(
|
||||
child: FlowySvg(
|
||||
FlowySvgs.attach_s,
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
|
@ -177,7 +177,9 @@
|
||||
"dragRow": "Long press to reorder the row",
|
||||
"viewDataBase": "View database",
|
||||
"referencePage": "This {name} is referenced",
|
||||
"addBlockBelow": "Add a block below"
|
||||
"addBlockBelow": "Add a block below",
|
||||
"urlLaunchAccessory": "Open in browser",
|
||||
"urlCopyAccessory": "Copy URL"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Close side bar",
|
||||
|
Loading…
Reference in New Issue
Block a user