mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: cursor jump randomly in check list item (#5565)
* chore: remove debug logs * fix: cursor jump ramdomly in checklist item
This commit is contained in:
parent
ed82ec8eef
commit
75cea400d2
@ -16,7 +16,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_chat_types/flutter_chat_types.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:nanoid/nanoid.dart';
|
||||
|
||||
import 'chat_message_listener.dart';
|
||||
|
||||
part 'chat_bloc.freezed.dart';
|
||||
|
||||
const sendMessageErrorKey = "sendMessageError";
|
||||
|
@ -1,9 +1,9 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/bloc/checklist_cell_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_cell_editor.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_progress_bar.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
@ -62,23 +62,24 @@ class _ChecklistItemsState extends State<ChecklistItems> {
|
||||
if (showIncompleteOnly) {
|
||||
tasks.removeWhere((task) => task.isSelected);
|
||||
}
|
||||
final children = tasks
|
||||
.mapIndexed(
|
||||
(index, task) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: ChecklistItem(
|
||||
key: ValueKey(task.data.id),
|
||||
task: task,
|
||||
autofocus: widget.state.newTask && index == tasks.length - 1,
|
||||
onSubmitted: () {
|
||||
if (index == tasks.length - 1) {
|
||||
widget.bloc.add(const ChecklistCellEvent.createNewTask(""));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
// final children = tasks
|
||||
// .mapIndexed(
|
||||
// (index, task) => Padding(
|
||||
// padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
// child: ChecklistItem(
|
||||
// key: ValueKey('${task.data.id}$index'),
|
||||
// task: task,
|
||||
// autofocus: widget.state.newTask && index == tasks.length - 1,
|
||||
// onSubmitted: () {
|
||||
// if (index == tasks.length - 1) {
|
||||
// // create a new task under the last task if the users press enter
|
||||
// widget.bloc.add(const ChecklistCellEvent.createNewTask(''));
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// .toList();
|
||||
return Align(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: Column(
|
||||
@ -116,7 +117,7 @@ class _ChecklistItemsState extends State<ChecklistItems> {
|
||||
),
|
||||
),
|
||||
const VSpace(2.0),
|
||||
...children,
|
||||
_ChecklistCellEditors(tasks: tasks),
|
||||
ChecklistItemControl(cellNotifer: widget.cellContainerNotifier),
|
||||
],
|
||||
),
|
||||
@ -124,6 +125,41 @@ class _ChecklistItemsState extends State<ChecklistItems> {
|
||||
}
|
||||
}
|
||||
|
||||
class _ChecklistCellEditors extends StatelessWidget {
|
||||
const _ChecklistCellEditors({
|
||||
required this.tasks,
|
||||
});
|
||||
|
||||
final List<ChecklistSelectOption> tasks;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bloc = context.read<ChecklistCellBloc>();
|
||||
final state = bloc.state;
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
...tasks.mapIndexed(
|
||||
(index, task) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: ChecklistItem(
|
||||
key: ValueKey('${task.data.id}$index'),
|
||||
task: task,
|
||||
autofocus: state.newTask && index == tasks.length - 1,
|
||||
onSubmitted: () {
|
||||
if (index == tasks.length - 1) {
|
||||
// create a new task under the last task if the users press enter
|
||||
bloc.add(const ChecklistCellEvent.createNewTask(''));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ChecklistItemControl extends StatelessWidget {
|
||||
const ChecklistItemControl({super.key, required this.cellNotifer});
|
||||
|
||||
|
@ -1,23 +1,21 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/widgets/common/type_option_separator.dart';
|
||||
import 'package:appflowy/util/debounce.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../application/cell/bloc/checklist_cell_bloc.dart';
|
||||
|
||||
import 'checklist_cell_textfield.dart';
|
||||
import 'checklist_progress_bar.dart';
|
||||
|
||||
class ChecklistCellEditor extends StatefulWidget {
|
||||
@ -89,7 +87,7 @@ class _ChecklistCellEditorState extends State<ChecklistCellEditor> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Displays the a list of all the exisiting tasks and an input field to create
|
||||
/// Displays the a list of all the existing tasks and an input field to create
|
||||
/// a new task if `isAddingNewTask` is true
|
||||
class ChecklistItemList extends StatelessWidget {
|
||||
const ChecklistItemList({
|
||||
@ -159,167 +157,136 @@ class ChecklistItem extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ChecklistItemState extends State<ChecklistItem> {
|
||||
late final TextEditingController _textController;
|
||||
final FocusNode _focusNode = FocusNode(skipTraversal: true);
|
||||
final FocusNode _textFieldFocusNode = FocusNode();
|
||||
TextEditingController textController = TextEditingController();
|
||||
final textFieldFocusNode = FocusNode();
|
||||
final focusNode = FocusNode(skipTraversal: true);
|
||||
|
||||
bool _isHovered = false;
|
||||
bool _isFocused = false;
|
||||
Timer? _debounceOnChanged;
|
||||
bool isHovered = false;
|
||||
bool isFocused = false;
|
||||
|
||||
final _debounceOnChanged = Debounce(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
);
|
||||
|
||||
final selectTaskShortcut = {
|
||||
SingleActivator(
|
||||
LogicalKeyboardKey.enter,
|
||||
meta: Platform.isMacOS,
|
||||
control: !Platform.isMacOS,
|
||||
): const _SelectTaskIntent(),
|
||||
const SingleActivator(LogicalKeyboardKey.escape):
|
||||
const _EndEditingTaskIntent(),
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_textController = TextEditingController(text: widget.task.data.name);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_debounceOnChanged?.cancel();
|
||||
_textController.dispose();
|
||||
_focusNode.dispose();
|
||||
_textFieldFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(ChecklistItem oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.task.data.name != oldWidget.task.data.name) {
|
||||
final selection = _textController.selection;
|
||||
// Ensure the selection offset is within the new text bounds
|
||||
int offset = selection.start;
|
||||
if (offset > widget.task.data.name.length) {
|
||||
offset = widget.task.data.name.length;
|
||||
}
|
||||
_textController.selection = TextSelection.collapsed(offset: offset);
|
||||
textController.text = widget.task.data.name;
|
||||
if (widget.autofocus) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
focusNode.requestFocus();
|
||||
textFieldFocusNode.requestFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_debounceOnChanged.dispose();
|
||||
|
||||
textController.dispose();
|
||||
focusNode.dispose();
|
||||
textFieldFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isFocusedOrHovered =
|
||||
isHovered || isFocused || textFieldFocusNode.hasFocus;
|
||||
final color = isFocusedOrHovered
|
||||
? AFThemeExtension.of(context).lightGreyHover
|
||||
: Colors.transparent;
|
||||
return FocusableActionDetector(
|
||||
focusNode: _focusNode,
|
||||
onShowHoverHighlight: (isHovered) {
|
||||
setState(() => _isHovered = isHovered);
|
||||
},
|
||||
onFocusChange: (isFocused) {
|
||||
setState(() => _isFocused = isFocused);
|
||||
},
|
||||
actions: {
|
||||
_SelectTaskIntent: CallbackAction<_SelectTaskIntent>(
|
||||
onInvoke: (_SelectTaskIntent intent) {
|
||||
// Log.debug("checklist widget on enter");
|
||||
context
|
||||
.read<ChecklistCellBloc>()
|
||||
.add(ChecklistCellEvent.selectTask(widget.task.data.id));
|
||||
return;
|
||||
},
|
||||
),
|
||||
_EndEditingTaskIntent: CallbackAction<_EndEditingTaskIntent>(
|
||||
onInvoke: (_EndEditingTaskIntent intent) {
|
||||
// Log.debug("checklist widget on escape");
|
||||
_textFieldFocusNode.unfocus();
|
||||
return;
|
||||
},
|
||||
),
|
||||
},
|
||||
shortcuts: {
|
||||
SingleActivator(
|
||||
LogicalKeyboardKey.enter,
|
||||
meta: Platform.isMacOS,
|
||||
control: !Platform.isMacOS,
|
||||
): const _SelectTaskIntent(),
|
||||
},
|
||||
focusNode: focusNode,
|
||||
onShowHoverHighlight: (value) => setState(() {
|
||||
isHovered = value;
|
||||
}),
|
||||
onFocusChange: (value) => setState(() {
|
||||
isFocused = value;
|
||||
}),
|
||||
actions: _buildActions(),
|
||||
shortcuts: selectTaskShortcut,
|
||||
child: Container(
|
||||
constraints: BoxConstraints(minHeight: GridSize.popoverItemHeight),
|
||||
constraints: BoxConstraints(
|
||||
minHeight: GridSize.popoverItemHeight,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: _isHovered || _isFocused || _textFieldFocusNode.hasFocus
|
||||
? AFThemeExtension.of(context).lightGreyHover
|
||||
: Colors.transparent,
|
||||
color: color,
|
||||
borderRadius: Corners.s6Border,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
ExcludeFocus(
|
||||
child: FlowyIconButton(
|
||||
width: 32,
|
||||
icon: FlowySvg(
|
||||
widget.task.isSelected
|
||||
? FlowySvgs.check_filled_s
|
||||
: FlowySvgs.uncheck_s,
|
||||
blendMode: BlendMode.dst,
|
||||
),
|
||||
hoverColor: Colors.transparent,
|
||||
onPressed: () => context.read<ChecklistCellBloc>().add(
|
||||
ChecklistCellEvent.selectTask(widget.task.data.id),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Shortcuts(
|
||||
shortcuts: const {
|
||||
SingleActivator(LogicalKeyboardKey.escape):
|
||||
_EndEditingTaskIntent(),
|
||||
},
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return TextField(
|
||||
controller: _textController,
|
||||
focusNode: _textFieldFocusNode,
|
||||
autofocus: widget.autofocus,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
isCollapsed: true,
|
||||
contentPadding: EdgeInsets.only(
|
||||
top: 8.0,
|
||||
bottom: 8.0,
|
||||
left: 2.0,
|
||||
right: _isHovered ? 2.0 : 8.0,
|
||||
),
|
||||
hintText: LocaleKeys.grid_checklist_taskHint.tr(),
|
||||
),
|
||||
textInputAction: widget.onSubmitted == null
|
||||
? TextInputAction.next
|
||||
: null,
|
||||
onChanged: (text) {
|
||||
if (_textController.value.composing.isCollapsed) {
|
||||
_debounceOnChangedText(text);
|
||||
}
|
||||
},
|
||||
onSubmitted: (description) {
|
||||
if (widget.onSubmitted != null) {
|
||||
// Log.debug("checklist widget on submitted");
|
||||
widget.onSubmitted?.call();
|
||||
} else {
|
||||
// Log.debug("checklist widget Focus next task");
|
||||
Actions.invoke(context, const NextFocusIntent());
|
||||
}
|
||||
_submitUpdateTaskDescription(description);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_isHovered || _isFocused || _textFieldFocusNode.hasFocus)
|
||||
_DeleteTaskButton(
|
||||
onPressed: () => context.read<ChecklistCellBloc>().add(
|
||||
ChecklistCellEvent.deleteTask(widget.task.data.id),
|
||||
),
|
||||
),
|
||||
],
|
||||
child: _buildChild(
|
||||
context,
|
||||
isFocusedOrHovered,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _debounceOnChangedText(String text) {
|
||||
_debounceOnChanged?.cancel();
|
||||
_debounceOnChanged = Timer(const Duration(milliseconds: 300), () {
|
||||
_submitUpdateTaskDescription(text);
|
||||
});
|
||||
Widget _buildChild(BuildContext context, bool isFocusedOrHovered) {
|
||||
return Row(
|
||||
children: [
|
||||
ChecklistCellCheckIcon(task: widget.task),
|
||||
Expanded(
|
||||
child: ChecklistCellTextfield(
|
||||
textController: textController,
|
||||
focusNode: textFieldFocusNode,
|
||||
autofocus: widget.autofocus,
|
||||
onChanged: () {
|
||||
_debounceOnChanged.call(() {
|
||||
if (textController.selection.isCollapsed) {
|
||||
_submitUpdateTaskDescription(textController.text);
|
||||
}
|
||||
});
|
||||
},
|
||||
onSubmitted: () {
|
||||
_submitUpdateTaskDescription(textController.text);
|
||||
|
||||
if (widget.onSubmitted != null) {
|
||||
widget.onSubmitted?.call();
|
||||
} else {
|
||||
Actions.invoke(context, const NextFocusIntent());
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
if (isFocusedOrHovered)
|
||||
ChecklistCellDeleteButton(
|
||||
onPressed: () => context.read<ChecklistCellBloc>().add(
|
||||
ChecklistCellEvent.deleteTask(widget.task.data.id),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Map<Type, Action<Intent>> _buildActions() {
|
||||
return {
|
||||
_SelectTaskIntent: CallbackAction<_SelectTaskIntent>(
|
||||
onInvoke: (_SelectTaskIntent intent) {
|
||||
context
|
||||
.read<ChecklistCellBloc>()
|
||||
.add(ChecklistCellEvent.selectTask(widget.task.data.id));
|
||||
return;
|
||||
},
|
||||
),
|
||||
_EndEditingTaskIntent: CallbackAction<_EndEditingTaskIntent>(
|
||||
onInvoke: (_EndEditingTaskIntent intent) {
|
||||
textFieldFocusNode.unfocus();
|
||||
return;
|
||||
},
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
void _submitUpdateTaskDescription(String description) {
|
||||
@ -423,55 +390,3 @@ class _NewTaskItemState extends State<NewTaskItem> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DeleteTaskButton extends StatefulWidget {
|
||||
const _DeleteTaskButton({
|
||||
required this.onPressed,
|
||||
});
|
||||
|
||||
final VoidCallback onPressed;
|
||||
|
||||
@override
|
||||
State<_DeleteTaskButton> createState() => _DeleteTaskButtonState();
|
||||
}
|
||||
|
||||
class _DeleteTaskButtonState extends State<_DeleteTaskButton> {
|
||||
final _materialStatesController = WidgetStatesController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_materialStatesController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
onPressed: widget.onPressed,
|
||||
onHover: (_) => setState(() {}),
|
||||
onFocusChange: (_) => setState(() {}),
|
||||
style: ButtonStyle(
|
||||
fixedSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
minimumSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
maximumSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
overlayColor: WidgetStateProperty.resolveWith((state) {
|
||||
if (state.contains(WidgetState.focused)) {
|
||||
return AFThemeExtension.of(context).greyHover;
|
||||
}
|
||||
return Colors.transparent;
|
||||
}),
|
||||
shape: const WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: Corners.s6Border),
|
||||
),
|
||||
),
|
||||
statesController: _materialStatesController,
|
||||
child: FlowySvg(
|
||||
FlowySvgs.delete_s,
|
||||
color: _materialStatesController.value.contains(WidgetState.hovered) ||
|
||||
_materialStatesController.value.contains(WidgetState.focused)
|
||||
? Theme.of(context).colorScheme.error
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,129 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../application/cell/bloc/checklist_cell_bloc.dart';
|
||||
|
||||
class ChecklistCellCheckIcon extends StatelessWidget {
|
||||
const ChecklistCellCheckIcon({
|
||||
super.key,
|
||||
required this.task,
|
||||
});
|
||||
|
||||
final ChecklistSelectOption task;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ExcludeFocus(
|
||||
child: FlowyIconButton(
|
||||
width: 32,
|
||||
icon: FlowySvg(
|
||||
task.isSelected ? FlowySvgs.check_filled_s : FlowySvgs.uncheck_s,
|
||||
blendMode: BlendMode.dst,
|
||||
),
|
||||
hoverColor: Colors.transparent,
|
||||
onPressed: () => context.read<ChecklistCellBloc>().add(
|
||||
ChecklistCellEvent.selectTask(task.data.id),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ChecklistCellTextfield extends StatelessWidget {
|
||||
const ChecklistCellTextfield({
|
||||
super.key,
|
||||
required this.textController,
|
||||
required this.focusNode,
|
||||
required this.autofocus,
|
||||
required this.onChanged,
|
||||
this.onSubmitted,
|
||||
});
|
||||
|
||||
final TextEditingController textController;
|
||||
final FocusNode focusNode;
|
||||
final bool autofocus;
|
||||
final VoidCallback? onSubmitted;
|
||||
final VoidCallback onChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const contentPadding = EdgeInsets.symmetric(
|
||||
vertical: 6.0,
|
||||
horizontal: 2.0,
|
||||
);
|
||||
return TextField(
|
||||
controller: textController,
|
||||
focusNode: focusNode,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
isCollapsed: true,
|
||||
contentPadding: contentPadding,
|
||||
hintText: LocaleKeys.grid_checklist_taskHint.tr(),
|
||||
),
|
||||
textInputAction: onSubmitted == null ? TextInputAction.next : null,
|
||||
onChanged: (_) => onChanged(),
|
||||
onSubmitted: (_) => onSubmitted?.call(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ChecklistCellDeleteButton extends StatefulWidget {
|
||||
const ChecklistCellDeleteButton({
|
||||
super.key,
|
||||
required this.onPressed,
|
||||
});
|
||||
|
||||
final VoidCallback onPressed;
|
||||
|
||||
@override
|
||||
State<ChecklistCellDeleteButton> createState() =>
|
||||
_ChecklistCellDeleteButtonState();
|
||||
}
|
||||
|
||||
class _ChecklistCellDeleteButtonState extends State<ChecklistCellDeleteButton> {
|
||||
final _materialStatesController = WidgetStatesController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_materialStatesController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
onPressed: widget.onPressed,
|
||||
onHover: (_) => setState(() {}),
|
||||
onFocusChange: (_) => setState(() {}),
|
||||
style: ButtonStyle(
|
||||
fixedSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
minimumSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
maximumSize: const WidgetStatePropertyAll(Size.square(32)),
|
||||
overlayColor: WidgetStateProperty.resolveWith((state) {
|
||||
if (state.contains(WidgetState.focused)) {
|
||||
return AFThemeExtension.of(context).greyHover;
|
||||
}
|
||||
return Colors.transparent;
|
||||
}),
|
||||
shape: const WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: Corners.s6Border),
|
||||
),
|
||||
),
|
||||
statesController: _materialStatesController,
|
||||
child: FlowySvg(
|
||||
FlowySvgs.delete_s,
|
||||
color: _materialStatesController.value.contains(WidgetState.hovered) ||
|
||||
_materialStatesController.value.contains(WidgetState.focused)
|
||||
? Theme.of(context).colorScheme.error
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user