chore: config caladen ui

This commit is contained in:
appflowy 2022-05-09 21:32:58 +08:00
parent f617a04900
commit d3841154a5
8 changed files with 246 additions and 70 deletions

View File

Before

Width:  |  Height:  |  Size: 516 B

After

Width:  |  Height:  |  Size: 516 B

View File

@ -28,7 +28,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
emit(state.copyWith(selectedDay: value.day));
}
},
setFormat: (_CalendarFormat value) {
setCalFormat: (_CalendarFormat value) {
emit(state.copyWith(format: value.format));
},
setFocusedDay: (_FocusedDay value) {
@ -38,6 +38,11 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(field: value.field));
},
setIncludeTime: (_IncludeTime value) {
emit(state.copyWith(includeTime: value.includeTime));
},
setDateFormat: (_DateFormat value) {},
setTimeFormat: (_TimeFormat value) {},
);
},
);
@ -97,8 +102,11 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
class DateCalEvent with _$DateCalEvent {
const factory DateCalEvent.initial() = _Initial;
const factory DateCalEvent.selectDay(DateTime day) = _SelectDay;
const factory DateCalEvent.setFormat(CalendarFormat format) = _CalendarFormat;
const factory DateCalEvent.setCalFormat(CalendarFormat format) = _CalendarFormat;
const factory DateCalEvent.setFocusedDay(DateTime day) = _FocusedDay;
const factory DateCalEvent.setTimeFormat(TimeFormat value) = _TimeFormat;
const factory DateCalEvent.setDateFormat(DateFormat value) = _DateFormat;
const factory DateCalEvent.setIncludeTime(bool includeTime) = _IncludeTime;
const factory DateCalEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate;
const factory DateCalEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
}
@ -111,6 +119,7 @@ class DateCalState with _$DateCalState {
required CalendarFormat format,
required DateTime focusedDay,
required bool includeTime,
required Option<String> time,
DateTime? selectedDay,
}) = _DateCalState;
@ -120,5 +129,6 @@ class DateCalState with _$DateCalState {
format: CalendarFormat.month,
focusedDay: DateTime.now(),
includeTime: false,
time: none(),
);
}

View File

@ -1,6 +1,15 @@
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/workspace/application/grid/cell/date_cal_bloc.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:table_calendar/table_calendar.dart';
@ -9,6 +18,7 @@ import 'package:app_flowy/workspace/application/grid/prelude.dart';
final kToday = DateTime.now();
final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day);
const kMargin = EdgeInsets.symmetric(horizontal: 6, vertical: 10);
class CellCalendar with FlowyOverlayDelegate {
final VoidCallback onDismissed;
@ -47,7 +57,7 @@ class CellCalendar with FlowyOverlayDelegate {
FlowyOverlay.of(context).insertWithAnchor(
widget: OverlayContainer(
child: calendar,
constraints: BoxConstraints.tight(const Size(320, 320)),
constraints: BoxConstraints.tight(const Size(320, 500)),
),
identifier: CellCalendar.identifier(),
anchorContext: context,
@ -67,6 +77,9 @@ class CellCalendar with FlowyOverlayDelegate {
@override
void didRemove() => onDismissed();
@override
bool asBarrier() => true;
}
class _CellCalendarWidget extends StatelessWidget {
@ -94,46 +107,175 @@ class _CellCalendarWidget extends StatelessWidget {
},
listenWhen: (p, c) => p.selectedDay != c.selectedDay,
builder: (context, state) {
return TableCalendar(
firstDay: kFirstDay,
lastDay: kLastDay,
focusedDay: state.focusedDay,
rowHeight: 40,
calendarFormat: state.format,
headerStyle: const HeaderStyle(formatButtonVisible: false),
calendarStyle: CalendarStyle(
selectedDecoration: BoxDecoration(
color: theme.main1,
shape: BoxShape.circle,
),
todayDecoration: BoxDecoration(
color: theme.shader4,
shape: BoxShape.circle,
),
selectedTextStyle: TextStyle(
color: theme.surface,
fontSize: 14.0,
),
todayTextStyle: TextStyle(
color: theme.surface,
fontSize: 14.0,
),
),
selectedDayPredicate: (day) {
return isSameDay(state.selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
context.read<DateCalBloc>().add(DateCalEvent.selectDay(selectedDay));
},
onFormatChanged: (format) {
context.read<DateCalBloc>().add(DateCalEvent.setFormat(format));
},
onPageChanged: (focusedDay) {
context.read<DateCalBloc>().add(DateCalEvent.setFocusedDay(focusedDay));
},
);
List<Widget> children = [];
children.addAll([
_buildCalendar(state, theme, context),
const VSpace(10),
]);
if (state.includeTime) {
children.addAll([
const _TimeTextField(),
const VSpace(10),
]);
}
children.addAll([
Divider(height: 1, color: theme.shader5),
const _IncludeTimeButton(),
]);
state.typeOptinoData.fold(() => null, (dateTypeOption) {
children.add(_DateTypeOptionButton(dateTypeOption: dateTypeOption));
});
return Column(children: children);
},
),
);
}
TableCalendar<dynamic> _buildCalendar(DateCalState state, AppTheme theme, BuildContext context) {
return TableCalendar(
firstDay: kFirstDay,
lastDay: kLastDay,
focusedDay: state.focusedDay,
rowHeight: 40,
calendarFormat: state.format,
headerStyle: HeaderStyle(
formatButtonVisible: false,
titleCentered: true,
leftChevronMargin: EdgeInsets.zero,
leftChevronPadding: EdgeInsets.zero,
leftChevronIcon: svgWidget("home/arrow_left"),
rightChevronPadding: EdgeInsets.zero,
rightChevronMargin: EdgeInsets.zero,
rightChevronIcon: svgWidget("home/arrow_right"),
),
calendarStyle: CalendarStyle(
selectedDecoration: BoxDecoration(
color: theme.main1,
shape: BoxShape.circle,
),
todayDecoration: BoxDecoration(
color: theme.shader4,
shape: BoxShape.circle,
),
selectedTextStyle: TextStyle(
color: theme.surface,
fontSize: 14.0,
),
todayTextStyle: TextStyle(
color: theme.surface,
fontSize: 14.0,
),
),
selectedDayPredicate: (day) {
return isSameDay(state.selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
context.read<DateCalBloc>().add(DateCalEvent.selectDay(selectedDay));
},
onFormatChanged: (format) {
context.read<DateCalBloc>().add(DateCalEvent.setCalFormat(format));
},
onPageChanged: (focusedDay) {
context.read<DateCalBloc>().add(DateCalEvent.setFocusedDay(focusedDay));
},
);
}
}
class _IncludeTimeButton extends StatelessWidget {
const _IncludeTimeButton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return BlocSelector<DateCalBloc, DateCalState, bool>(
selector: (state) => state.includeTime,
builder: (context, includeTime) {
return SizedBox(
height: 50,
child: Padding(
padding: kMargin,
child: Row(
children: [
svgWidget("grid/clock", color: theme.iconColor),
const HSpace(4),
FlowyText.medium(LocaleKeys.grid_field_includeTime.tr(), fontSize: 14),
const Spacer(),
Switch(
value: includeTime,
onChanged: (newValue) => context.read<DateCalBloc>().add(DateCalEvent.setIncludeTime(newValue)),
),
],
),
),
);
},
);
}
}
class _TimeTextField extends StatelessWidget {
const _TimeTextField({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}
class _DateTypeOptionButton extends StatelessWidget {
final DateTypeOption dateTypeOption;
const _DateTypeOptionButton({required this.dateTypeOption, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
final title = LocaleKeys.grid_field_dateFormat.tr() + " &" + LocaleKeys.grid_field_timeFormat.tr();
return FlowyButton(
text: FlowyText.medium(title, fontSize: 12),
hoverColor: theme.hover,
margin: kMargin,
onTap: () {
final setting = _CalDateTimeSetting(dateTypeOption: dateTypeOption);
setting.show(context);
},
rightIcon: svgWidget("grid/more", color: theme.iconColor),
);
}
}
class _CalDateTimeSetting extends StatelessWidget {
final DateTypeOption dateTypeOption;
const _CalDateTimeSetting({required this.dateTypeOption, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(children: [
DateFormatButton(onTap: () {
final list = DateFormatList(
selectedFormat: dateTypeOption.dateFormat,
onSelected: (format) {
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectDateFormat(format));
},
);
}),
TimeFormatButton(
timeFormat: dateTypeOption.timeFormat,
onTap: () {
final list = TimeFormatList(
selectedFormat: dateTypeOption.timeFormat,
onSelected: (format) {
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectTimeFormat(format));
});
},
),
]);
}
void show(BuildContext context) {}
}

View File

@ -150,7 +150,7 @@ class FieldCellButton extends StatelessWidget {
onTap: onTap,
leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor),
text: FlowyText.medium(field.name, fontSize: 12),
padding: GridSize.cellContentInsets,
margin: GridSize.cellContentInsets,
);
}
}

View File

@ -80,7 +80,7 @@ class _FieldEditorPannelState extends State<FieldEditorPannel> {
height: GridSize.typeOptionItemHeight,
child: FlowyButton(
text: FlowyText.medium(field.fieldType.title(), fontSize: 12),
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
hoverColor: theme.hover,
onTap: () {
final list = FieldTypeList(onSelectField: (newFieldType) {

View File

@ -50,8 +50,8 @@ class DateTypeOptionWidget extends TypeOptionWidget {
listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()),
builder: (context, state) {
return Column(children: [
_dateFormatButton(context, state.typeOption.dateFormat),
_timeFormatButton(context, state.typeOption.timeFormat),
_renderDateFormatButton(context, state.typeOption.dateFormat),
_renderTimeFormatButton(context, state.typeOption.timeFormat),
const _IncludeTimeButton(),
]);
},
@ -59,44 +59,68 @@ class DateTypeOptionWidget extends TypeOptionWidget {
);
}
Widget _dateFormatButton(BuildContext context, DateFormat dataFormat) {
Widget _renderDateFormatButton(BuildContext context, DateFormat dataFormat) {
return DateFormatButton(onTap: () {
final list = DateFormatList(
selectedFormat: dataFormat,
onSelected: (format) {
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectDateFormat(format));
},
);
overlayDelegate.showOverlay(context, list);
});
}
Widget _renderTimeFormatButton(BuildContext context, TimeFormat timeFormat) {
return TimeFormatButton(
timeFormat: timeFormat,
onTap: () {
final list = TimeFormatList(
selectedFormat: timeFormat,
onSelected: (format) {
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectTimeFormat(format));
});
overlayDelegate.showOverlay(context, list);
},
);
}
}
class DateFormatButton extends StatelessWidget {
final VoidCallback onTap;
const DateFormatButton({required this.onTap, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return SizedBox(
height: GridSize.typeOptionItemHeight,
child: FlowyButton(
text: FlowyText.medium(LocaleKeys.grid_field_dateFormat.tr(), fontSize: 12),
padding: GridSize.typeOptionContentInsets,
margin: GridSize.typeOptionContentInsets,
hoverColor: theme.hover,
onTap: () {
final list = DateFormatList(
selectedFormat: dataFormat,
onSelected: (format) {
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectDateFormat(format));
},
);
overlayDelegate.showOverlay(context, list);
},
onTap: onTap,
rightIcon: svgWidget("grid/more", color: theme.iconColor),
),
);
}
}
Widget _timeFormatButton(BuildContext context, TimeFormat timeFormat) {
class TimeFormatButton extends StatelessWidget {
final TimeFormat timeFormat;
final VoidCallback onTap;
const TimeFormatButton({required this.timeFormat, required this.onTap, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return SizedBox(
height: GridSize.typeOptionItemHeight,
child: FlowyButton(
text: FlowyText.medium(LocaleKeys.grid_field_timeFormat.tr(), fontSize: 12),
padding: GridSize.typeOptionContentInsets,
margin: GridSize.typeOptionContentInsets,
hoverColor: theme.hover,
onTap: () {
final list = TimeFormatList(
selectedFormat: timeFormat,
onSelected: (format) {
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectTimeFormat(format));
});
overlayDelegate.showOverlay(context, list);
},
onTap: onTap,
rightIcon: svgWidget("grid/more", color: theme.iconColor),
),
);

View File

@ -60,7 +60,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
FlowyText.regular(state.typeOption.format.title(), fontSize: 12),
],
),
padding: GridSize.typeOptionContentInsets,
margin: GridSize.typeOptionContentInsets,
hoverColor: theme.hover,
onTap: () {
final list = NumberFormatList(

View File

@ -7,7 +7,7 @@ import 'package:flutter/material.dart';
class FlowyButton extends StatelessWidget {
final Widget text;
final VoidCallback? onTap;
final EdgeInsets padding;
final EdgeInsets margin;
final Widget? leftIcon;
final Widget? rightIcon;
final Color hoverColor;
@ -16,7 +16,7 @@ class FlowyButton extends StatelessWidget {
Key? key,
required this.text,
this.onTap,
this.padding = const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
this.margin = const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
this.leftIcon,
this.rightIcon,
this.hoverColor = Colors.transparent,
@ -50,7 +50,7 @@ class FlowyButton extends StatelessWidget {
}
return Padding(
padding: padding,
padding: margin,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,