mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: set time
This commit is contained in:
parent
81d75147d5
commit
a2dfc8bc03
@ -1,5 +1,6 @@
|
||||
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -16,13 +17,17 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
|
||||
final GridDefaultCellContext cellContext;
|
||||
void Function()? _onCellChangedFn;
|
||||
|
||||
DateCalBloc({required this.cellContext}) : super(DateCalState.initial(cellContext)) {
|
||||
DateCalBloc({
|
||||
required DateTypeOption dateTypeOption,
|
||||
required DateTime? selectedDay,
|
||||
required this.cellContext,
|
||||
}) : super(DateCalState.initial(dateTypeOption, selectedDay)) {
|
||||
on<DateCalEvent>(
|
||||
(event, emit) async {
|
||||
await event.map(
|
||||
initial: (_Initial value) async {
|
||||
_startListening();
|
||||
await _loadDateTypeOption(emit);
|
||||
// await _loadDateTypeOption(emit);
|
||||
},
|
||||
selectDay: (_SelectDay value) {
|
||||
if (!isSameDay(state.selectedDay, value.day)) {
|
||||
@ -46,6 +51,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
|
||||
setTimeFormat: (_TimeFormat value) async {
|
||||
await _updateTypeOption(emit, timeFormat: value.timeFormat);
|
||||
},
|
||||
setTime: (_Time value) {},
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -71,12 +77,12 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
|
||||
);
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
Future<void> _loadDateTypeOption(Emitter<DateCalState> emit) async {
|
||||
final result = await cellContext.getTypeOptionData();
|
||||
result.fold(
|
||||
(data) {
|
||||
final typeOptionData = DateTypeOption.fromBuffer(data);
|
||||
|
||||
DateTime? selectedDay;
|
||||
final cellData = cellContext.getCellData()?.data;
|
||||
|
||||
@ -86,7 +92,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
|
||||
}
|
||||
|
||||
emit(state.copyWith(
|
||||
dateTypeOption: some(typeOptionData),
|
||||
dateTypeOption: typeOptionData,
|
||||
selectedDay: selectedDay,
|
||||
));
|
||||
},
|
||||
@ -105,35 +111,31 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
|
||||
TimeFormat? timeFormat,
|
||||
bool? includeTime,
|
||||
}) async {
|
||||
final newDateTypeOption = state.dateTypeOption.fold(() => null, (dateTypeOption) {
|
||||
dateTypeOption.freeze();
|
||||
return dateTypeOption.rebuild((typeOption) {
|
||||
if (dateFormat != null) {
|
||||
typeOption.dateFormat = dateFormat;
|
||||
}
|
||||
state.dateTypeOption.freeze();
|
||||
final newDateTypeOption = state.dateTypeOption.rebuild((typeOption) {
|
||||
if (dateFormat != null) {
|
||||
typeOption.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
if (timeFormat != null) {
|
||||
typeOption.timeFormat = timeFormat;
|
||||
}
|
||||
if (timeFormat != null) {
|
||||
typeOption.timeFormat = timeFormat;
|
||||
}
|
||||
|
||||
if (includeTime != null) {
|
||||
typeOption.includeTime = includeTime;
|
||||
}
|
||||
});
|
||||
if (includeTime != null) {
|
||||
typeOption.includeTime = includeTime;
|
||||
}
|
||||
});
|
||||
|
||||
if (newDateTypeOption != null) {
|
||||
final result = await FieldService.updateFieldTypeOption(
|
||||
gridId: cellContext.gridId,
|
||||
fieldId: cellContext.field.id,
|
||||
typeOptionData: newDateTypeOption.writeToBuffer(),
|
||||
);
|
||||
final result = await FieldService.updateFieldTypeOption(
|
||||
gridId: cellContext.gridId,
|
||||
fieldId: cellContext.field.id,
|
||||
typeOptionData: newDateTypeOption.writeToBuffer(),
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(l) => emit(state.copyWith(dateTypeOption: Some(newDateTypeOption))),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
}
|
||||
result.fold(
|
||||
(l) => emit(state.copyWith(dateTypeOption: newDateTypeOption)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,23 +148,31 @@ class DateCalEvent with _$DateCalEvent {
|
||||
const factory DateCalEvent.setTimeFormat(TimeFormat timeFormat) = _TimeFormat;
|
||||
const factory DateCalEvent.setDateFormat(DateFormat dateFormat) = _DateFormat;
|
||||
const factory DateCalEvent.setIncludeTime(bool includeTime) = _IncludeTime;
|
||||
const factory DateCalEvent.setTime(String time) = _Time;
|
||||
const factory DateCalEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class DateCalState with _$DateCalState {
|
||||
const factory DateCalState({
|
||||
required Option<DateTypeOption> dateTypeOption,
|
||||
required DateTypeOption dateTypeOption,
|
||||
required CalendarFormat format,
|
||||
required DateTime focusedDay,
|
||||
required Option<String> time,
|
||||
required String time,
|
||||
required Option<FlowyError> inputTimeError,
|
||||
DateTime? selectedDay,
|
||||
}) = _DateCalState;
|
||||
|
||||
factory DateCalState.initial(GridCellContext context) => DateCalState(
|
||||
dateTypeOption: none(),
|
||||
factory DateCalState.initial(
|
||||
DateTypeOption dateTypeOption,
|
||||
DateTime? selectedDay,
|
||||
) =>
|
||||
DateCalState(
|
||||
dateTypeOption: dateTypeOption,
|
||||
format: CalendarFormat.month,
|
||||
focusedDay: DateTime.now(),
|
||||
time: none(),
|
||||
selectedDay: selectedDay,
|
||||
time: "",
|
||||
inputTimeError: none(),
|
||||
);
|
||||
}
|
||||
|
@ -8,13 +8,15 @@ 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/rounded_input_field.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:table_calendar/table_calendar.dart';
|
||||
import 'package:app_flowy/workspace/application/grid/prelude.dart';
|
||||
import 'package:dartz/dartz.dart' show Option;
|
||||
import 'package:fixnum/fixnum.dart' as $fixnum;
|
||||
|
||||
final kToday = DateTime.now();
|
||||
final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
|
||||
@ -35,22 +37,38 @@ class CellCalendar with FlowyOverlayDelegate {
|
||||
}) async {
|
||||
CellCalendar.remove(context);
|
||||
|
||||
final calendar = _CellCalendarWidget(
|
||||
onSelected: onSelected,
|
||||
includeTime: false,
|
||||
cellContext: cellContext,
|
||||
);
|
||||
final result = await cellContext.getTypeOptionData();
|
||||
result.fold(
|
||||
(data) {
|
||||
final typeOptionData = DateTypeOption.fromBuffer(data);
|
||||
DateTime? selectedDay;
|
||||
final cellData = cellContext.getCellData()?.data;
|
||||
|
||||
FlowyOverlay.of(context).insertWithAnchor(
|
||||
widget: OverlayContainer(
|
||||
child: calendar,
|
||||
constraints: BoxConstraints.loose(const Size(320, 500)),
|
||||
),
|
||||
identifier: CellCalendar.identifier(),
|
||||
anchorContext: context,
|
||||
anchorDirection: AnchorDirection.leftWithCenterAligned,
|
||||
style: FlowyOverlayStyle(blur: false),
|
||||
delegate: this,
|
||||
if (cellData != null) {
|
||||
final timestamp = $fixnum.Int64.parseInt(cellData).toInt();
|
||||
selectedDay = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
|
||||
}
|
||||
|
||||
final calendar = _CellCalendarWidget(
|
||||
onSelected: onSelected,
|
||||
cellContext: cellContext,
|
||||
dateTypeOption: typeOptionData,
|
||||
selectedDay: selectedDay,
|
||||
);
|
||||
|
||||
FlowyOverlay.of(context).insertWithAnchor(
|
||||
widget: OverlayContainer(
|
||||
child: calendar,
|
||||
constraints: BoxConstraints.loose(const Size(320, 500)),
|
||||
),
|
||||
identifier: CellCalendar.identifier(),
|
||||
anchorContext: context,
|
||||
anchorDirection: AnchorDirection.leftWithCenterAligned,
|
||||
style: FlowyOverlayStyle(blur: false),
|
||||
delegate: this,
|
||||
);
|
||||
},
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
}
|
||||
|
||||
@ -70,14 +88,16 @@ class CellCalendar with FlowyOverlayDelegate {
|
||||
}
|
||||
|
||||
class _CellCalendarWidget extends StatelessWidget {
|
||||
final bool includeTime;
|
||||
final GridDefaultCellContext cellContext;
|
||||
final DateTypeOption dateTypeOption;
|
||||
final DateTime? selectedDay;
|
||||
final void Function(DateTime) onSelected;
|
||||
|
||||
const _CellCalendarWidget({
|
||||
required this.onSelected,
|
||||
required this.includeTime,
|
||||
required this.cellContext,
|
||||
required this.dateTypeOption,
|
||||
this.selectedDay,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -85,7 +105,11 @@ class _CellCalendarWidget extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return BlocProvider(
|
||||
create: (context) => DateCalBloc(cellContext: cellContext)..add(const DateCalEvent.initial()),
|
||||
create: (context) => DateCalBloc(
|
||||
dateTypeOption: dateTypeOption,
|
||||
selectedDay: selectedDay,
|
||||
cellContext: cellContext,
|
||||
)..add(const DateCalEvent.initial()),
|
||||
child: BlocConsumer<DateCalBloc, DateCalState>(
|
||||
listener: (context, state) {
|
||||
if (state.selectedDay != null) {
|
||||
@ -101,12 +125,11 @@ class _CellCalendarWidget extends StatelessWidget {
|
||||
const VSpace(10),
|
||||
]);
|
||||
|
||||
state.dateTypeOption.foldRight(null, (dateTypeOption, _) {
|
||||
if (state.dateTypeOption.includeTime) {
|
||||
children.addAll([
|
||||
const _TimeTextField(),
|
||||
const VSpace(10),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
children.addAll([
|
||||
Divider(height: 1, color: theme.shader5),
|
||||
@ -189,7 +212,7 @@ class _IncludeTimeButton extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return BlocSelector<DateCalBloc, DateCalState, bool>(
|
||||
selector: (state) => state.dateTypeOption.foldRight(false, (option, _) => option.includeTime),
|
||||
selector: (state) => state.dateTypeOption.includeTime,
|
||||
builder: (context, includeTime) {
|
||||
return SizedBox(
|
||||
height: 50,
|
||||
@ -219,7 +242,19 @@ class _TimeTextField extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
final theme = context.watch<AppTheme>();
|
||||
return Padding(
|
||||
padding: kMargin,
|
||||
child: RoundedInputField(
|
||||
height: 40,
|
||||
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
|
||||
normalBorderColor: theme.shader4,
|
||||
errorBorderColor: theme.red,
|
||||
cursorColor: theme.main1,
|
||||
errorText: context.read<DateCalBloc>().state.inputTimeError.fold(() => "", (error) => error.toString()),
|
||||
onEditingComplete: (value) => context.read<DateCalBloc>().add(DateCalEvent.setTime(value)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,29 +265,33 @@ class _DateTypeOptionButton extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
final title = LocaleKeys.grid_field_dateFormat.tr() + " &" + LocaleKeys.grid_field_timeFormat.tr();
|
||||
return BlocSelector<DateCalBloc, DateCalState, Option<DateTypeOption>>(
|
||||
return BlocSelector<DateCalBloc, DateCalState, DateTypeOption>(
|
||||
selector: (state) => state.dateTypeOption,
|
||||
builder: (context, dateTypeOption) {
|
||||
return FlowyButton(
|
||||
text: FlowyText.medium(title, fontSize: 12),
|
||||
hoverColor: theme.hover,
|
||||
margin: kMargin,
|
||||
onTap: () {
|
||||
dateTypeOption.fold(() => null, (dateTypeOption) {
|
||||
final setting = _CalDateTimeSetting(dateTypeOption: dateTypeOption);
|
||||
setting.show(context);
|
||||
});
|
||||
},
|
||||
onTap: () => _showTimeSetting(dateTypeOption, context),
|
||||
rightIcon: svgWidget("grid/more", color: theme.iconColor),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _showTimeSetting(DateTypeOption dateTypeOption, BuildContext context) {
|
||||
final setting = _CalDateTimeSetting(
|
||||
dateTypeOption: dateTypeOption,
|
||||
onEvent: (event) => context.read<DateCalBloc>().add(event),
|
||||
);
|
||||
setting.show(context);
|
||||
}
|
||||
}
|
||||
|
||||
class _CalDateTimeSetting extends StatefulWidget {
|
||||
final DateTypeOption dateTypeOption;
|
||||
const _CalDateTimeSetting({required this.dateTypeOption, Key? key}) : super(key: key);
|
||||
final Function(DateCalEvent) onEvent;
|
||||
const _CalDateTimeSetting({required this.dateTypeOption, required this.onEvent, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<_CalDateTimeSetting> createState() => _CalDateTimeSettingState();
|
||||
@ -283,9 +322,7 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
|
||||
DateFormatButton(onTap: () {
|
||||
final list = DateFormatList(
|
||||
selectedFormat: widget.dateTypeOption.dateFormat,
|
||||
onSelected: (format) {
|
||||
context.read<DateCalBloc>().add(DateCalEvent.setDateFormat(format));
|
||||
},
|
||||
onSelected: (format) => widget.onEvent(DateCalEvent.setDateFormat(format)),
|
||||
);
|
||||
_showOverlay(context, list);
|
||||
}),
|
||||
@ -294,9 +331,7 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
|
||||
onTap: () {
|
||||
final list = TimeFormatList(
|
||||
selectedFormat: widget.dateTypeOption.timeFormat,
|
||||
onSelected: (format) {
|
||||
context.read<DateCalBloc>().add(DateCalEvent.setTimeFormat(format));
|
||||
},
|
||||
onSelected: (format) => widget.onEvent(DateCalEvent.setTimeFormat(format)),
|
||||
);
|
||||
_showOverlay(context, list);
|
||||
},
|
||||
|
@ -53,7 +53,7 @@ class _InputTextFieldState extends State<InputTextField> {
|
||||
widget.onChanged!(text);
|
||||
}
|
||||
},
|
||||
onEditingComplete: () {
|
||||
onEditingComplete: (_) {
|
||||
if (widget.onDone != null) {
|
||||
widget.onDone!(_controller.text);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class RoundedInputField extends StatefulWidget {
|
||||
final String errorText;
|
||||
final TextStyle style;
|
||||
final ValueChanged<String>? onChanged;
|
||||
final VoidCallback? onEditingComplete;
|
||||
final Function(String)? onEditingComplete;
|
||||
final String? initialValue;
|
||||
final EdgeInsets margin;
|
||||
final EdgeInsets padding;
|
||||
@ -90,7 +90,11 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
onEditingComplete: widget.onEditingComplete,
|
||||
onEditingComplete: () {
|
||||
if (widget.onEditingComplete != null) {
|
||||
widget.onEditingComplete!(inputText);
|
||||
}
|
||||
},
|
||||
cursorColor: widget.cursorColor,
|
||||
obscureText: obscuteText,
|
||||
style: widget.style,
|
||||
|
Loading…
Reference in New Issue
Block a user