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 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(
|
||||||
|
@ -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(
|
||||||
|
@ -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: [
|
||||||
|
@ -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),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -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
|
||||||
|
@ -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) =>
|
||||||
|
@ -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,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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(),
|
||||||
|
@ -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,
|
||||||
),
|
),
|
||||||
|
@ -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,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -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(),
|
||||||
|
@ -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,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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(
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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 {
|
||||||
|
@ -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",
|
||||||
|
Loading…
Reference in New Issue
Block a user