mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-24 22:57:12 -04:00
Merge pull request #441 from AppFlowy-IO/feat_date_cell
Feautre: support date column
This commit is contained in:
commit
ce85050114
19 changed files with 278 additions and 82 deletions
|
@ -200,7 +200,6 @@ void _resolveGridDeps(GetIt getIt) {
|
||||||
|
|
||||||
getIt.registerFactoryParam<DateCellBloc, CellData, void>(
|
getIt.registerFactoryParam<DateCellBloc, CellData, void>(
|
||||||
(cellData, _) => DateCellBloc(
|
(cellData, _) => DateCellBloc(
|
||||||
service: CellService(),
|
|
||||||
cellData: cellData,
|
cellData: cellData,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -26,15 +26,10 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
|
||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
select: (_Selected value) async {
|
select: (_Selected value) async {
|
||||||
_service.updateCell(
|
_updateCellData();
|
||||||
gridId: state.cellData.gridId,
|
|
||||||
fieldId: state.cellData.field.id,
|
|
||||||
rowId: state.cellData.rowId,
|
|
||||||
data: !state.isSelected ? "Yes" : "No",
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
didReceiveCellUpdate: (_DidReceiveCellUpdate value) {
|
didReceiveCellUpdate: (_DidReceiveCellUpdate value) {
|
||||||
emit(state.copyWith(isSelected: isSelected(value.cell)));
|
emit(state.copyWith(isSelected: _isSelected(value.cell)));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -50,22 +45,33 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
_listener.updateCellNotifier.addPublishListener((result) {
|
_listener.updateCellNotifier.addPublishListener((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(notificationData) async {
|
(notificationData) async => await _loadCellData(),
|
||||||
final result = await _service.getCell(
|
|
||||||
gridId: state.cellData.gridId,
|
|
||||||
fieldId: state.cellData.field.id,
|
|
||||||
rowId: state.cellData.rowId,
|
|
||||||
);
|
|
||||||
result.fold(
|
|
||||||
(cell) => add(CheckboxCellEvent.didReceiveCellUpdate(cell)),
|
|
||||||
(err) => Log.error(err),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
_listener.start();
|
_listener.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _loadCellData() async {
|
||||||
|
final result = await _service.getCell(
|
||||||
|
gridId: state.cellData.gridId,
|
||||||
|
fieldId: state.cellData.field.id,
|
||||||
|
rowId: state.cellData.rowId,
|
||||||
|
);
|
||||||
|
result.fold(
|
||||||
|
(cell) => add(CheckboxCellEvent.didReceiveCellUpdate(cell)),
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _updateCellData() {
|
||||||
|
_service.updateCell(
|
||||||
|
gridId: state.cellData.gridId,
|
||||||
|
fieldId: state.cellData.field.id,
|
||||||
|
rowId: state.cellData.rowId,
|
||||||
|
data: !state.isSelected ? "Yes" : "No",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -83,11 +89,11 @@ class CheckboxCellState with _$CheckboxCellState {
|
||||||
}) = _CheckboxCellState;
|
}) = _CheckboxCellState;
|
||||||
|
|
||||||
factory CheckboxCellState.initial(CellData cellData) {
|
factory CheckboxCellState.initial(CellData cellData) {
|
||||||
return CheckboxCellState(cellData: cellData, isSelected: isSelected(cellData.cell));
|
return CheckboxCellState(cellData: cellData, isSelected: _isSelected(cellData.cell));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSelected(Cell? cell) {
|
bool _isSelected(Cell? cell) {
|
||||||
final content = cell?.content ?? "";
|
final content = cell?.content ?? "";
|
||||||
return content == "Yes";
|
return content == "Yes";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart';
|
||||||
|
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
@ -8,17 +11,30 @@ import 'cell_service.dart';
|
||||||
part 'date_cell_bloc.freezed.dart';
|
part 'date_cell_bloc.freezed.dart';
|
||||||
|
|
||||||
class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
||||||
final CellService service;
|
final CellService _service;
|
||||||
final CellData cellData;
|
final CellListener _cellListener;
|
||||||
|
final FieldListener _fieldListener;
|
||||||
|
|
||||||
DateCellBloc({
|
DateCellBloc({required CellData cellData})
|
||||||
required this.service,
|
: _service = CellService(),
|
||||||
required this.cellData,
|
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
||||||
}) : super(DateCellState.initial()) {
|
_fieldListener = FieldListener(fieldId: cellData.field.id),
|
||||||
|
super(DateCellState.initial(cellData)) {
|
||||||
on<DateCellEvent>(
|
on<DateCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
event.map(
|
||||||
initial: (_InitialCell value) async {},
|
initial: (_InitialCell value) {
|
||||||
|
_startListening();
|
||||||
|
},
|
||||||
|
selectDay: (_SelectDay value) {
|
||||||
|
_updateCellData(value.day);
|
||||||
|
},
|
||||||
|
didReceiveCellUpdate: (_DidReceiveCellUpdate value) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
cellData: state.cellData.copyWith(cell: value.cell),
|
||||||
|
content: value.cell.content,
|
||||||
|
));
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -26,20 +42,69 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
|
await _cellListener.stop();
|
||||||
|
await _fieldListener.stop();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _startListening() {
|
||||||
|
_cellListener.updateCellNotifier.addPublishListener((result) {
|
||||||
|
result.fold(
|
||||||
|
(notificationData) => _loadCellData(),
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
_cellListener.start();
|
||||||
|
|
||||||
|
_fieldListener.updateFieldNotifier.addPublishListener((result) {
|
||||||
|
result.fold(
|
||||||
|
(field) => _loadCellData(),
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
_fieldListener.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadCellData() async {
|
||||||
|
final result = await _service.getCell(
|
||||||
|
gridId: state.cellData.gridId,
|
||||||
|
fieldId: state.cellData.field.id,
|
||||||
|
rowId: state.cellData.rowId,
|
||||||
|
);
|
||||||
|
result.fold(
|
||||||
|
(cell) => add(DateCellEvent.didReceiveCellUpdate(cell)),
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _updateCellData(DateTime day) {
|
||||||
|
final data = day.millisecondsSinceEpoch ~/ 1000;
|
||||||
|
_service.updateCell(
|
||||||
|
gridId: state.cellData.gridId,
|
||||||
|
fieldId: state.cellData.field.id,
|
||||||
|
rowId: state.cellData.rowId,
|
||||||
|
data: data.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class DateCellEvent with _$DateCellEvent {
|
class DateCellEvent with _$DateCellEvent {
|
||||||
const factory DateCellEvent.initial() = _InitialCell;
|
const factory DateCellEvent.initial() = _InitialCell;
|
||||||
|
const factory DateCellEvent.selectDay(DateTime day) = _SelectDay;
|
||||||
|
const factory DateCellEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class DateCellState with _$DateCellState {
|
class DateCellState with _$DateCellState {
|
||||||
const factory DateCellState({
|
const factory DateCellState({
|
||||||
Cell? cell,
|
required CellData cellData,
|
||||||
|
required String content,
|
||||||
|
DateTime? selectedDay,
|
||||||
}) = _DateCellState;
|
}) = _DateCellState;
|
||||||
|
|
||||||
factory DateCellState.initial() => const DateCellState();
|
factory DateCellState.initial(CellData cellData) => DateCellState(
|
||||||
|
cellData: cellData,
|
||||||
|
content: cellData.cell?.content ?? "",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart';
|
import 'package:app_flowy/workspace/application/grid/cell_bloc/cell_listener.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/cell_bloc/select_option_service.dart';
|
import 'package:app_flowy/workspace/application/grid/cell_bloc/select_option_service.dart';
|
||||||
|
import 'package:app_flowy/workspace/application/grid/field/field_listener.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
||||||
|
@ -11,12 +12,14 @@ part 'selection_cell_bloc.freezed.dart';
|
||||||
|
|
||||||
class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
||||||
final SelectOptionService _service;
|
final SelectOptionService _service;
|
||||||
final CellListener _listener;
|
final CellListener _cellListener;
|
||||||
|
final FieldListener _fieldListener;
|
||||||
|
|
||||||
SelectionCellBloc({
|
SelectionCellBloc({
|
||||||
required CellData cellData,
|
required CellData cellData,
|
||||||
}) : _service = SelectOptionService(),
|
}) : _service = SelectOptionService(),
|
||||||
_listener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
||||||
|
_fieldListener = FieldListener(fieldId: cellData.field.id),
|
||||||
super(SelectionCellState.initial(cellData)) {
|
super(SelectionCellState.initial(cellData)) {
|
||||||
on<SelectionCellEvent>(
|
on<SelectionCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
|
@ -35,7 +38,8 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _listener.stop();
|
await _cellListener.stop();
|
||||||
|
await _fieldListener.stop();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,13 +60,21 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
_listener.updateCellNotifier.addPublishListener((result) {
|
_cellListener.updateCellNotifier.addPublishListener((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(notificationData) => _loadOptions(),
|
(notificationData) => _loadOptions(),
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
_listener.start();
|
_cellListener.start();
|
||||||
|
|
||||||
|
_fieldListener.updateFieldNotifier.addPublishListener((result) {
|
||||||
|
result.fold(
|
||||||
|
(field) => _loadOptions(),
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
_fieldListener.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'row_service.freezed.dart';
|
||||||
|
|
||||||
class RowService {
|
class RowService {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
|
@ -29,19 +32,12 @@ class RowService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CellData extends Equatable {
|
@freezed
|
||||||
final String gridId;
|
class CellData with _$CellData {
|
||||||
final String rowId;
|
const factory CellData({
|
||||||
final Field field;
|
required String gridId,
|
||||||
final Cell? cell;
|
required String rowId,
|
||||||
|
required Field field,
|
||||||
const CellData({
|
Cell? cell,
|
||||||
required this.rowId,
|
}) = _CellData;
|
||||||
required this.gridId,
|
|
||||||
required this.field,
|
|
||||||
required this.cell,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object?> get props => [cell, field];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/prelude.dart';
|
import 'package:app_flowy/workspace/application/grid/prelude.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:table_calendar/table_calendar.dart';
|
||||||
|
import 'package:window_size/window_size.dart';
|
||||||
|
|
||||||
class DateCell extends StatefulWidget {
|
class DateCell extends StatefulWidget {
|
||||||
final CellData cellData;
|
final CellData cellData;
|
||||||
|
@ -20,7 +24,7 @@ class _DateCellState extends State<DateCell> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_cellBloc = getIt<DateCellBloc>(param1: widget.cellData);
|
_cellBloc = getIt<DateCellBloc>(param1: widget.cellData)..add(const DateCellEvent.initial());
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +34,20 @@ class _DateCellState extends State<DateCell> {
|
||||||
value: _cellBloc,
|
value: _cellBloc,
|
||||||
child: BlocBuilder<DateCellBloc, DateCellState>(
|
child: BlocBuilder<DateCellBloc, DateCellState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Container();
|
return SizedBox.expand(
|
||||||
|
child: GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: () => _CellCalendar.show(
|
||||||
|
context,
|
||||||
|
onSelected: (day) => context.read<DateCellBloc>().add(DateCellEvent.selectDay(day)),
|
||||||
|
),
|
||||||
|
child: MouseRegion(
|
||||||
|
opaque: false,
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
child: Center(child: FlowyText.medium(state.content, fontSize: 12)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -42,3 +59,79 @@ class _DateCellState extends State<DateCell> {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final kToday = DateTime.now();
|
||||||
|
final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
|
||||||
|
final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day);
|
||||||
|
|
||||||
|
class _CellCalendar extends StatefulWidget {
|
||||||
|
final void Function(DateTime) onSelected;
|
||||||
|
const _CellCalendar({required this.onSelected, Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_CellCalendar> createState() => _CellCalendarState();
|
||||||
|
|
||||||
|
static Future<void> show(BuildContext context, {required void Function(DateTime) onSelected}) async {
|
||||||
|
_CellCalendar.remove(context);
|
||||||
|
final window = await getWindowInfo();
|
||||||
|
final calendar = _CellCalendar(onSelected: onSelected);
|
||||||
|
const size = Size(460, 400);
|
||||||
|
FlowyOverlay.of(context).insertWithRect(
|
||||||
|
widget: OverlayContainer(
|
||||||
|
child: calendar,
|
||||||
|
constraints: BoxConstraints.loose(const Size(460, 400)),
|
||||||
|
),
|
||||||
|
identifier: _CellCalendar.identifier(),
|
||||||
|
anchorPosition: Offset(-size.width / 2.0, -size.height / 2.0),
|
||||||
|
anchorSize: window.frame.size,
|
||||||
|
anchorDirection: AnchorDirection.center,
|
||||||
|
style: FlowyOverlayStyle(blur: false),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove(BuildContext context) {
|
||||||
|
FlowyOverlay.of(context).remove(identifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
static String identifier() {
|
||||||
|
return (_CellCalendar).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CellCalendarState extends State<_CellCalendar> {
|
||||||
|
CalendarFormat _calendarFormat = CalendarFormat.month;
|
||||||
|
DateTime _focusedDay = DateTime.now();
|
||||||
|
DateTime? _selectedDay;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return TableCalendar(
|
||||||
|
firstDay: kFirstDay,
|
||||||
|
lastDay: kLastDay,
|
||||||
|
focusedDay: _focusedDay,
|
||||||
|
calendarFormat: _calendarFormat,
|
||||||
|
headerStyle: const HeaderStyle(formatButtonVisible: false),
|
||||||
|
selectedDayPredicate: (day) {
|
||||||
|
return isSameDay(_selectedDay, day);
|
||||||
|
},
|
||||||
|
onDaySelected: (selectedDay, focusedDay) {
|
||||||
|
if (!isSameDay(_selectedDay, selectedDay)) {
|
||||||
|
// Call `setState()` when updating the selected day
|
||||||
|
setState(() {
|
||||||
|
_selectedDay = selectedDay;
|
||||||
|
_focusedDay = focusedDay;
|
||||||
|
widget.onSelected(selectedDay);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFormatChanged: (format) {
|
||||||
|
setState(() {
|
||||||
|
_calendarFormat = format;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onPageChanged: (focusedDay) {
|
||||||
|
_focusedDay = focusedDay;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -86,7 +86,12 @@ class _MultiSelectCellState extends State<MultiSelectCell> {
|
||||||
return SizedBox.expand(
|
return SizedBox.expand(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
SelectOptionCellEditor.show(context, state.cellData, state.options, state.selectedOptions);
|
SelectOptionCellEditor.show(
|
||||||
|
context,
|
||||||
|
state.cellData,
|
||||||
|
state.options,
|
||||||
|
state.selectedOptions,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Row(children: children),
|
child: Row(children: children),
|
||||||
),
|
),
|
||||||
|
|
|
@ -36,10 +36,6 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
static String identifier() {
|
|
||||||
return (SelectOptionCellEditor).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
|
@ -96,6 +92,10 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
||||||
FlowyOverlay.of(context).remove(identifier());
|
FlowyOverlay.of(context).remove(identifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String identifier() {
|
||||||
|
return (SelectOptionCellEditor).toString();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool asBarrier() => true;
|
bool asBarrier() => true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ class FieldTypeList extends StatelessWidget with FlowyOverlayDelegate {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final cells = FieldType.values.where((ty) => ty != FieldType.DateTime).map((fieldType) {
|
final cells = FieldType.values.map((fieldType) {
|
||||||
return FieldTypeCell(
|
return FieldTypeCell(
|
||||||
fieldType: fieldType,
|
fieldType: fieldType,
|
||||||
onSelectField: (fieldType) {
|
onSelectField: (fieldType) {
|
||||||
|
|
|
@ -95,6 +95,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.11"
|
||||||
|
material_color_utilities:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: material_color_utilities
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.3"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -176,7 +183,7 @@ packages:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.3"
|
version: "0.4.8"
|
||||||
textstyle_extensions:
|
textstyle_extensions:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -7,7 +7,7 @@ packages:
|
||||||
name: archive
|
name: archive
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.8"
|
version: "3.1.6"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -200,7 +200,7 @@ packages:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.0"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -275,7 +275,7 @@ packages:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.9"
|
version: "0.4.8"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -6,9 +6,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
flowy_sdk
|
flowy_sdk
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
|
||||||
)
|
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
||||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||||
|
@ -17,8 +14,3 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||||
endforeach(plugin)
|
endforeach(plugin)
|
||||||
|
|
||||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
|
||||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
|
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
|
||||||
endforeach(ffi_plugin)
|
|
||||||
|
|
|
@ -346,7 +346,7 @@ packages:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.0"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -456,7 +456,7 @@ packages:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.9"
|
version: "0.4.8"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -512,7 +512,7 @@ packages:
|
||||||
name: fluttertoast
|
name: fluttertoast
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.0.8"
|
version: "8.0.9"
|
||||||
freezed:
|
freezed:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
@ -1031,6 +1031,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
simple_gesture_detector:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: simple_gesture_detector
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
sized_context:
|
sized_context:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -1120,6 +1127,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.1+2"
|
version: "0.3.1+2"
|
||||||
|
table_calendar:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: table_calendar
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.5"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -73,6 +73,7 @@ dependencies:
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
device_info_plus: ^3.2.1
|
device_info_plus: ^3.2.1
|
||||||
fluttertoast: ^8.0.8
|
fluttertoast: ^8.0.8
|
||||||
|
table_calendar: ^3.0.5
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^1.0.0
|
flutter_lints: ^1.0.0
|
||||||
|
|
|
@ -69,9 +69,8 @@ impl CellDataOperation for DateTypeOption {
|
||||||
_cell_meta: Option<CellMeta>,
|
_cell_meta: Option<CellMeta>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> Result<String, FlowyError> {
|
||||||
let changeset = changeset.into();
|
let changeset = changeset.into();
|
||||||
if let Err(e) = changeset.parse::<i64>() {
|
if changeset.parse::<f64>().is_err() || changeset.parse::<i64>().is_err() {
|
||||||
tracing::error!("Parse {} to i64 failed: {}", changeset.to_string(), e);
|
return Err(FlowyError::internal().context(format!("Parse {} failed", changeset.to_string())));
|
||||||
return Err(FlowyError::internal().context(e));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(TypeOptionCellData::new(changeset, self.field_type()).json())
|
Ok(TypeOptionCellData::new(changeset, self.field_type()).json())
|
||||||
|
|
|
@ -74,7 +74,7 @@ fn crate_log_filter(level: String) -> String {
|
||||||
filters.push(format!("lib_ot={}", level));
|
filters.push(format!("lib_ot={}", level));
|
||||||
filters.push(format!("lib_ws={}", level));
|
filters.push(format!("lib_ws={}", level));
|
||||||
filters.push(format!("lib_infra={}", level));
|
filters.push(format!("lib_infra={}", level));
|
||||||
filters.push(format!("flowy_sync={}", level));
|
filters.push(format!("flowy_sync={}", "debug"));
|
||||||
|
|
||||||
filters.push(format!("dart_ffi={}", "info"));
|
filters.push(format!("dart_ffi={}", "info"));
|
||||||
filters.push(format!("flowy_database={}", "info"));
|
filters.push(format!("flowy_database={}", "info"));
|
||||||
|
|
|
@ -8,7 +8,6 @@ use std::collections::HashMap;
|
||||||
use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString};
|
use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString};
|
||||||
|
|
||||||
pub const DEFAULT_ROW_HEIGHT: i32 = 42;
|
pub const DEFAULT_ROW_HEIGHT: i32 = 42;
|
||||||
pub const DEFAULT_FIELD_WIDTH: i32 = 150;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
|
||||||
pub struct GridMeta {
|
pub struct GridMeta {
|
||||||
|
@ -110,6 +109,7 @@ pub struct FieldMeta {
|
||||||
|
|
||||||
impl FieldMeta {
|
impl FieldMeta {
|
||||||
pub fn new(name: &str, desc: &str, field_type: FieldType) -> Self {
|
pub fn new(name: &str, desc: &str, field_type: FieldType) -> Self {
|
||||||
|
let width = field_type.default_cell_width();
|
||||||
Self {
|
Self {
|
||||||
id: uuid::Uuid::new_v4().to_string(),
|
id: uuid::Uuid::new_v4().to_string(),
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
@ -117,7 +117,7 @@ impl FieldMeta {
|
||||||
field_type,
|
field_type,
|
||||||
frozen: false,
|
frozen: false,
|
||||||
visibility: true,
|
visibility: true,
|
||||||
width: DEFAULT_FIELD_WIDTH,
|
width,
|
||||||
type_options: Default::default(),
|
type_options: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,6 +270,13 @@ impl FieldType {
|
||||||
let ty = self.clone();
|
let ty = self.clone();
|
||||||
format!("{}", ty as u8)
|
format!("{}", ty as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default_cell_width(&self) -> i32 {
|
||||||
|
match self {
|
||||||
|
FieldType::DateTime => 180,
|
||||||
|
_ => 150,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
|
||||||
|
|
|
@ -156,7 +156,7 @@ impl GridBlockMetaPad {
|
||||||
match cal_diff::<PlainTextAttributes>(old, new) {
|
match cal_diff::<PlainTextAttributes>(old, new) {
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
Some(delta) => {
|
Some(delta) => {
|
||||||
tracing::trace!("[GridBlockMeta] Composing change {}", delta.to_delta_str());
|
tracing::debug!("[GridBlockMeta] Composing change {}", delta.to_delta_str());
|
||||||
self.delta = self.delta.compose(&delta)?;
|
self.delta = self.delta.compose(&delta)?;
|
||||||
Ok(Some(GridBlockMetaChange { delta, md5: self.md5() }))
|
Ok(Some(GridBlockMetaChange { delta, md5: self.md5() }))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue