mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: show edit field
This commit is contained in:
parent
7c6a857a69
commit
c3c75dde9f
@ -2,7 +2,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
part 'date_bloc.freezed.dart';
|
||||
|
||||
class DateTypeOptionBloc extends Bloc<DateTypeOptionEvent, DateTypeOptionState> {
|
||||
@ -11,18 +11,30 @@ class DateTypeOptionBloc extends Bloc<DateTypeOptionEvent, DateTypeOptionState>
|
||||
(event, emit) async {
|
||||
event.map(
|
||||
didSelectDateFormat: (_DidSelectDateFormat value) {
|
||||
state.typeOption.dateFormat = value.format;
|
||||
emit(state);
|
||||
emit(state.copyWith(typeOption: _updateDateFormat(value.format)));
|
||||
},
|
||||
didSelectTimeFormat: (_DidSelectTimeFormat value) {
|
||||
state.typeOption.timeFormat = value.format;
|
||||
emit(state);
|
||||
emit(state.copyWith(typeOption: _updateTimeFormat(value.format)));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
DateTypeOption _updateTimeFormat(TimeFormat format) {
|
||||
state.typeOption.freeze();
|
||||
return state.typeOption.rebuild((typeOption) {
|
||||
typeOption.timeFormat = format;
|
||||
});
|
||||
}
|
||||
|
||||
DateTypeOption _updateDateFormat(DateFormat format) {
|
||||
state.typeOption.freeze();
|
||||
return state.typeOption.rebuild((typeOption) {
|
||||
typeOption.dateFormat = format;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
return super.close();
|
||||
|
@ -2,6 +2,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'dart:async';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
|
||||
part 'number_bloc.freezed.dart';
|
||||
|
||||
@ -11,14 +12,20 @@ class NumberTypeOptionBloc extends Bloc<NumberTypeOptionEvent, NumberTypeOptionS
|
||||
(event, emit) async {
|
||||
event.map(
|
||||
didSelectFormat: (_DidSelectFormat value) {
|
||||
state.typeOption.format = value.format;
|
||||
emit(state);
|
||||
emit(state.copyWith(typeOption: _updateNumberFormat(value.format)));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
NumberTypeOption _updateNumberFormat(NumberFormat format) {
|
||||
state.typeOption.freeze();
|
||||
return state.typeOption.rebuild((typeOption) {
|
||||
typeOption.format = format;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
return super.close();
|
||||
|
@ -1,110 +0,0 @@
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/workspace/application/grid/prelude.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'field_name_input.dart';
|
||||
import 'field_operation_list.dart';
|
||||
import 'field_tyep_switcher.dart';
|
||||
|
||||
class EditFieldPannel extends StatelessWidget {
|
||||
final GridFieldData fieldData;
|
||||
const EditFieldPannel({required this.fieldData, Key? key}) : super(key: key);
|
||||
|
||||
static void show(BuildContext context, GridFieldData fieldData) {
|
||||
final editor = EditFieldPannel(fieldData: fieldData);
|
||||
FlowyOverlay.of(context).insertWithAnchor(
|
||||
widget: OverlayContainer(
|
||||
child: editor,
|
||||
constraints: BoxConstraints.loose(const Size(300, 200)),
|
||||
),
|
||||
identifier: editor.identifier(),
|
||||
anchorContext: context,
|
||||
anchorDirection: AnchorDirection.bottomWithLeftAligned,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => getIt<EditFieldBloc>(param1: fieldData)..add(const EditFieldEvent.initial()),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
const _FieldNameTextField(),
|
||||
const VSpace(6),
|
||||
const _FieldTypeSwitcher(),
|
||||
const VSpace(6),
|
||||
_FieldOperationList(fieldData, () => FlowyOverlay.of(context).remove(identifier())),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String identifier() {
|
||||
return toString();
|
||||
}
|
||||
}
|
||||
|
||||
class _FieldOperationList extends StatelessWidget {
|
||||
final GridFieldData fieldData;
|
||||
final VoidCallback onDismissed;
|
||||
const _FieldOperationList(this.fieldData, this.onDismissed, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final actions = FieldAction.values
|
||||
.map(
|
||||
(action) => FieldActionItem(
|
||||
fieldId: fieldData.field.id,
|
||||
action: action,
|
||||
onTap: onDismissed,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
return FieldOperationList(actions: actions);
|
||||
}
|
||||
}
|
||||
|
||||
class _FieldTypeSwitcher extends StatelessWidget {
|
||||
const _FieldTypeSwitcher({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<EditFieldBloc, EditFieldState>(
|
||||
builder: (context, state) {
|
||||
final editContext = context.read<EditFieldBloc>().state.editContext;
|
||||
final switchContext = SwitchFieldContext(
|
||||
editContext.gridId,
|
||||
editContext.gridField,
|
||||
editContext.typeOptionData,
|
||||
);
|
||||
return FieldTypeSwitcher(switchContext: switchContext, onSelected: (field, typeOptionData) {});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _FieldNameTextField extends StatelessWidget {
|
||||
const _FieldNameTextField({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<EditFieldBloc, EditFieldState>(
|
||||
buildWhen: ((previous, current) => previous.fieldName == current.fieldName),
|
||||
builder: (context, state) {
|
||||
return FieldNameTextField(
|
||||
name: state.fieldName,
|
||||
errorText: state.errorText,
|
||||
onNameChanged: (newName) {
|
||||
context.read<EditFieldBloc>().add(EditFieldEvent.updateFieldName(newName));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'edit_field_pannel.dart';
|
||||
import 'field_detail_pannel.dart';
|
||||
|
||||
class GridHeaderCell extends StatelessWidget {
|
||||
final GridFieldData fieldData;
|
||||
@ -18,7 +18,7 @@ class GridHeaderCell extends StatelessWidget {
|
||||
final theme = context.watch<AppTheme>();
|
||||
final button = FlowyButton(
|
||||
hoverColor: theme.hover,
|
||||
onTap: () => EditFieldPannel.show(context, fieldData),
|
||||
onTap: () => FieldDetailPannel.show(context, fieldData),
|
||||
rightIcon: svg("editor/details", color: theme.iconColor),
|
||||
text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)),
|
||||
);
|
||||
|
@ -50,15 +50,15 @@ class DateTypeOptionWidget extends TypeOptionWidget {
|
||||
listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()),
|
||||
builder: (context, state) {
|
||||
return Column(children: [
|
||||
_dateFormatButton(context),
|
||||
_timeFormatButton(context),
|
||||
_dateFormatButton(context, state.typeOption.dateFormat),
|
||||
_timeFormatButton(context, state.typeOption.timeFormat),
|
||||
]);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _dateFormatButton(BuildContext context) {
|
||||
Widget _dateFormatButton(BuildContext context, DateFormat dataFormat) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return SizedBox(
|
||||
height: GridSize.typeOptionItemHeight,
|
||||
@ -67,9 +67,12 @@ class DateTypeOptionWidget extends TypeOptionWidget {
|
||||
padding: GridSize.typeOptionContentInsets,
|
||||
hoverColor: theme.hover,
|
||||
onTap: () {
|
||||
final list = DateFormatList(onSelected: (format) {
|
||||
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectDateFormat(format));
|
||||
});
|
||||
final list = DateFormatList(
|
||||
selectedFormat: dataFormat,
|
||||
onSelected: (format) {
|
||||
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectDateFormat(format));
|
||||
},
|
||||
);
|
||||
overlayDelegate.showOverlay(context, list);
|
||||
},
|
||||
rightIcon: svg("grid/more", color: theme.iconColor),
|
||||
@ -77,7 +80,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _timeFormatButton(BuildContext context) {
|
||||
Widget _timeFormatButton(BuildContext context, TimeFormat timeFormat) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return SizedBox(
|
||||
height: GridSize.typeOptionItemHeight,
|
||||
@ -86,9 +89,11 @@ class DateTypeOptionWidget extends TypeOptionWidget {
|
||||
padding: GridSize.typeOptionContentInsets,
|
||||
hoverColor: theme.hover,
|
||||
onTap: () {
|
||||
final list = TimeFormatList(onSelected: (format) {
|
||||
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectTimeFormat(format));
|
||||
});
|
||||
final list = TimeFormatList(
|
||||
selectedFormat: timeFormat,
|
||||
onSelected: (format) {
|
||||
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectTimeFormat(format));
|
||||
});
|
||||
overlayDelegate.showOverlay(context, list);
|
||||
},
|
||||
rightIcon: svg("grid/more", color: theme.iconColor),
|
||||
@ -98,8 +103,9 @@ class DateTypeOptionWidget extends TypeOptionWidget {
|
||||
}
|
||||
|
||||
class DateFormatList extends StatelessWidget {
|
||||
final DateFormat selectedFormat;
|
||||
final Function(DateFormat format) onSelected;
|
||||
const DateFormatList({required this.onSelected, Key? key}) : super(key: key);
|
||||
const DateFormatList({required this.selectedFormat, required this.onSelected, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -109,7 +115,8 @@ class DateFormatList extends StatelessWidget {
|
||||
onSelected: (format) {
|
||||
onSelected(format);
|
||||
FlowyOverlay.of(context).remove(identifier());
|
||||
});
|
||||
},
|
||||
isSelected: selectedFormat == format);
|
||||
}).toList();
|
||||
|
||||
return SizedBox(
|
||||
@ -134,18 +141,30 @@ class DateFormatList extends StatelessWidget {
|
||||
}
|
||||
|
||||
class DateFormatItem extends StatelessWidget {
|
||||
final bool isSelected;
|
||||
final DateFormat dateFormat;
|
||||
final Function(DateFormat format) onSelected;
|
||||
const DateFormatItem({required this.dateFormat, required this.onSelected, Key? key}) : super(key: key);
|
||||
const DateFormatItem({
|
||||
required this.dateFormat,
|
||||
required this.onSelected,
|
||||
required this.isSelected,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
Widget? checkmark;
|
||||
if (isSelected) {
|
||||
checkmark = svg("grid/checkmark");
|
||||
}
|
||||
|
||||
return SizedBox(
|
||||
height: GridSize.typeOptionItemHeight,
|
||||
child: FlowyButton(
|
||||
text: FlowyText.medium(dateFormat.title(), fontSize: 12),
|
||||
hoverColor: theme.hover,
|
||||
rightIcon: checkmark,
|
||||
onTap: () => onSelected(dateFormat),
|
||||
),
|
||||
);
|
||||
@ -170,13 +189,19 @@ extension DateFormatExtension on DateFormat {
|
||||
}
|
||||
|
||||
class TimeFormatList extends StatelessWidget {
|
||||
final TimeFormat selectedFormat;
|
||||
final Function(TimeFormat format) onSelected;
|
||||
const TimeFormatList({required this.onSelected, Key? key}) : super(key: key);
|
||||
const TimeFormatList({
|
||||
required this.selectedFormat,
|
||||
required this.onSelected,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final formatItems = TimeFormat.values.map((format) {
|
||||
return TimeFormatItem(
|
||||
isSelected: format == selectedFormat,
|
||||
timeFormat: format,
|
||||
onSelected: (format) {
|
||||
onSelected(format);
|
||||
@ -207,17 +232,29 @@ class TimeFormatList extends StatelessWidget {
|
||||
|
||||
class TimeFormatItem extends StatelessWidget {
|
||||
final TimeFormat timeFormat;
|
||||
final bool isSelected;
|
||||
final Function(TimeFormat format) onSelected;
|
||||
const TimeFormatItem({required this.timeFormat, required this.onSelected, Key? key}) : super(key: key);
|
||||
const TimeFormatItem({
|
||||
required this.timeFormat,
|
||||
required this.onSelected,
|
||||
required this.isSelected,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
Widget? checkmark;
|
||||
if (isSelected) {
|
||||
checkmark = svg("grid/checkmark");
|
||||
}
|
||||
|
||||
return SizedBox(
|
||||
height: GridSize.typeOptionItemHeight,
|
||||
child: FlowyButton(
|
||||
text: FlowyText.medium(timeFormat.title(), fontSize: 12),
|
||||
hoverColor: theme.hover,
|
||||
rightIcon: checkmark,
|
||||
onTap: () => onSelected(timeFormat),
|
||||
),
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user