feat: on enter exit editing property field #1295 (#1747)

* feat: on enter exit editing property field #1295

* chore: use FlowyTextField instead of RoundedInputField

* fix: make all text field border radius 10, added errorBorder

* fix: put cursor position at end of text field

See the related discussion here:
https://github.com/AppFlowy-IO/AppFlowy/pull/1747#issuecomment-1407697216

* chore: make errorText optional on FlowyTextField
This commit is contained in:
Mohammad Zolfaghari
2023-02-02 05:59:56 +03:30
committed by GitHub
parent d505314ab1
commit c9166137be
3 changed files with 32 additions and 24 deletions

View File

@ -6,7 +6,7 @@ import 'package:dartz/dartz.dart' show none;
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.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/style_widget/text_field.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/log.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -135,11 +135,9 @@ class _FieldNameTextField extends StatefulWidget {
class _FieldNameTextFieldState extends State<_FieldNameTextField> { class _FieldNameTextFieldState extends State<_FieldNameTextField> {
FocusNode focusNode = FocusNode(); FocusNode focusNode = FocusNode();
late TextEditingController controller;
@override @override
void initState() { void initState() {
controller = TextEditingController();
focusNode.addListener(() { focusNode.addListener(() {
if (focusNode.hasFocus) { if (focusNode.hasFocus) {
widget.popoverMutex.close(); widget.popoverMutex.close();
@ -157,33 +155,23 @@ class _FieldNameTextFieldState extends State<_FieldNameTextField> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiBlocListener( return BlocListener<FieldEditorBloc, FieldEditorState>(
listeners: [ listenWhen: (p, c) => p.field == none(),
BlocListener<FieldEditorBloc, FieldEditorState>( listener: (context, state) {
listenWhen: (p, c) => p.field == none(), focusNode.requestFocus();
listener: (context, state) { },
focusNode.requestFocus();
},
),
BlocListener<FieldEditorBloc, FieldEditorState>(
listenWhen: (p, c) => controller.text != c.name,
listener: (context, state) {
controller.text = state.name;
},
),
],
child: BlocBuilder<FieldEditorBloc, FieldEditorState>( child: BlocBuilder<FieldEditorBloc, FieldEditorState>(
buildWhen: (previous, current) => buildWhen: (previous, current) =>
previous.errorText != current.errorText, previous.errorText != current.errorText,
builder: (context, state) { builder: (context, state) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0), padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: RoundedInputField( child: FlowyTextField(
height: 36,
focusNode: focusNode, focusNode: focusNode,
style: Theme.of(context).textTheme.bodyMedium, onSubmitted: (String _) => PopoverContainer.of(context).close(),
controller: controller, text: context.read<FieldEditorBloc>().state.name,
errorText: context.read<FieldEditorBloc>().state.errorText, errorText: context.read<FieldEditorBloc>().state.errorText.isEmpty ?
null : context.read<FieldEditorBloc>().state.errorText,
onChanged: (newName) { onChanged: (newName) {
context context
.read<FieldEditorBloc>() .read<FieldEditorBloc>()

View File

@ -19,6 +19,7 @@ class FlowyTextField extends StatefulWidget {
final bool autoClearWhenDone; final bool autoClearWhenDone;
final bool submitOnLeave; final bool submitOnLeave;
final Duration? debounceDuration; final Duration? debounceDuration;
final String? errorText;
const FlowyTextField({ const FlowyTextField({
this.hintText = "", this.hintText = "",
@ -34,6 +35,7 @@ class FlowyTextField extends StatefulWidget {
this.autoClearWhenDone = false, this.autoClearWhenDone = false,
this.submitOnLeave = false, this.submitOnLeave = false,
this.debounceDuration, this.debounceDuration,
this.errorText,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -117,6 +119,7 @@ class FlowyTextFieldState extends State<FlowyTextField> {
), ),
isDense: true, isDense: true,
hintText: widget.hintText, hintText: widget.hintText,
errorText: widget.errorText,
hintStyle: Theme.of(context) hintStyle: Theme.of(context)
.textTheme .textTheme
.bodySmall! .bodySmall!
@ -128,7 +131,21 @@ class FlowyTextFieldState extends State<FlowyTextField> {
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
width: 1.0, width: 1.0,
), ),
borderRadius: Corners.s8Border, borderRadius: Corners.s10Border,
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
width: 1.0,
),
borderRadius: Corners.s10Border,
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
width: 1.0,
),
borderRadius: Corners.s10Border,
), ),
), ),
); );

View File

@ -27,6 +27,7 @@ class RoundedInputField extends StatefulWidget {
final TextEditingController? controller; final TextEditingController? controller;
final bool autoFocus; final bool autoFocus;
final int? maxLength; final int? maxLength;
final Function(String)? onFieldSubmitted;
const RoundedInputField({ const RoundedInputField({
Key? key, Key? key,
@ -51,6 +52,7 @@ class RoundedInputField extends StatefulWidget {
this.controller, this.controller,
this.autoFocus = false, this.autoFocus = false,
this.maxLength, this.maxLength,
this.onFieldSubmitted,
}) : super(key: key); }) : super(key: key);
@override @override
@ -106,6 +108,7 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
maxLength: widget.maxLength, maxLength: widget.maxLength,
maxLengthEnforcement: maxLengthEnforcement:
MaxLengthEnforcement.truncateAfterCompositionEnds, MaxLengthEnforcement.truncateAfterCompositionEnds,
onFieldSubmitted: widget.onFieldSubmitted,
onChanged: (value) { onChanged: (value) {
inputText = value; inputText = value;
if (widget.onChanged != null) { if (widget.onChanged != null) {