TF-1884 Support RTL mode for TextField
(cherry picked from commit 3f8445141bea9dbf276a6a336114e4e2b549936f)
This commit is contained in:
@@ -47,7 +47,6 @@ export 'utils/platform_info.dart';
|
|||||||
export 'presentation/views/text/slogan_builder.dart';
|
export 'presentation/views/text/slogan_builder.dart';
|
||||||
export 'presentation/views/text/text_field_builder.dart';
|
export 'presentation/views/text/text_field_builder.dart';
|
||||||
export 'presentation/views/text/input_decoration_builder.dart';
|
export 'presentation/views/text/input_decoration_builder.dart';
|
||||||
export 'presentation/views/text/text_builder.dart';
|
|
||||||
export 'presentation/views/text/rich_text_builder.dart';
|
export 'presentation/views/text/rich_text_builder.dart';
|
||||||
export 'presentation/views/responsive/responsive_widget.dart';
|
export 'presentation/views/responsive/responsive_widget.dart';
|
||||||
export 'presentation/views/list/tree_view.dart';
|
export 'presentation/views/list/tree_view.dart';
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -576,6 +577,7 @@ class _TypeAheadFieldQuickSearchState<T, R> extends State<TypeAheadFieldQuickSea
|
|||||||
FocusNode? _focusNode;
|
FocusNode? _focusNode;
|
||||||
TextEditingController? _textEditingController;
|
TextEditingController? _textEditingController;
|
||||||
_SuggestionsBox? _suggestionsBox;
|
_SuggestionsBox? _suggestionsBox;
|
||||||
|
late TextDirection _textDirection;
|
||||||
|
|
||||||
TextEditingController? get _effectiveController =>
|
TextEditingController? get _effectiveController =>
|
||||||
widget.textFieldConfiguration.controller ?? _textEditingController;
|
widget.textFieldConfiguration.controller ?? _textEditingController;
|
||||||
@@ -622,6 +624,8 @@ class _TypeAheadFieldQuickSearchState<T, R> extends State<TypeAheadFieldQuickSea
|
|||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
|
|
||||||
|
_textDirection = widget.textFieldConfiguration.textDirection ?? TextDirection.ltr;
|
||||||
|
|
||||||
if (widget.textFieldConfiguration.controller == null) {
|
if (widget.textFieldConfiguration.controller == null) {
|
||||||
_textEditingController = TextEditingController();
|
_textEditingController = TextEditingController();
|
||||||
}
|
}
|
||||||
@@ -840,7 +844,17 @@ class _TypeAheadFieldQuickSearchState<T, R> extends State<TypeAheadFieldQuickSea
|
|||||||
maxLength: widget.textFieldConfiguration.maxLength,
|
maxLength: widget.textFieldConfiguration.maxLength,
|
||||||
maxLengthEnforcement: widget.textFieldConfiguration.maxLengthEnforcement,
|
maxLengthEnforcement: widget.textFieldConfiguration.maxLengthEnforcement,
|
||||||
obscureText: widget.textFieldConfiguration.obscureText,
|
obscureText: widget.textFieldConfiguration.obscureText,
|
||||||
onChanged: widget.textFieldConfiguration.onChanged,
|
onChanged: (input) {
|
||||||
|
widget.textFieldConfiguration.onChanged?.call(input);
|
||||||
|
if (input.isNotEmpty) {
|
||||||
|
final directionByText = DirectionUtils.getDirectionByEndsText(input);
|
||||||
|
if (directionByText != _textDirection) {
|
||||||
|
setState(() {
|
||||||
|
_textDirection = directionByText;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
onSubmitted: widget.textFieldConfiguration.onSubmitted,
|
onSubmitted: widget.textFieldConfiguration.onSubmitted,
|
||||||
onEditingComplete: widget.textFieldConfiguration.onEditingComplete,
|
onEditingComplete: widget.textFieldConfiguration.onEditingComplete,
|
||||||
onTap: widget.textFieldConfiguration.onTap,
|
onTap: widget.textFieldConfiguration.onTap,
|
||||||
@@ -851,9 +865,8 @@ class _TypeAheadFieldQuickSearchState<T, R> extends State<TypeAheadFieldQuickSea
|
|||||||
cursorWidth: widget.textFieldConfiguration.cursorWidth,
|
cursorWidth: widget.textFieldConfiguration.cursorWidth,
|
||||||
cursorRadius: widget.textFieldConfiguration.cursorRadius,
|
cursorRadius: widget.textFieldConfiguration.cursorRadius,
|
||||||
cursorColor: widget.textFieldConfiguration.cursorColor,
|
cursorColor: widget.textFieldConfiguration.cursorColor,
|
||||||
textDirection: widget.textFieldConfiguration.textDirection,
|
textDirection: _textDirection,
|
||||||
enableInteractiveSelection:
|
enableInteractiveSelection: widget.textFieldConfiguration.enableInteractiveSelection,
|
||||||
widget.textFieldConfiguration.enableInteractiveSelection,
|
|
||||||
readOnly: widget.hideKeyboard,
|
readOnly: widget.hideKeyboard,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
import 'package:core/presentation/utils/style_utils.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class TextBuilder {
|
|
||||||
String? _text;
|
|
||||||
TextStyle? _textStyle;
|
|
||||||
TextAlign? _textAlign;
|
|
||||||
Key? _key;
|
|
||||||
|
|
||||||
TextBuilder key(Key key) {
|
|
||||||
_key = key;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextBuilder text(String text) {
|
|
||||||
_text = text;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextBuilder textStyle(TextStyle textStyle) {
|
|
||||||
_textStyle = textStyle;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextBuilder textAlign(TextAlign textAlign) {
|
|
||||||
_textAlign = textAlign;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text build() {
|
|
||||||
return Text(_text ?? '', key: _key ?? const Key('TextBuilder'), style: _textStyle ?? CommonTextStyle.textStyleNormal, textAlign: _textAlign ?? TextAlign.center);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CenterTextBuilder extends TextBuilder {
|
|
||||||
@override
|
|
||||||
Text build() {
|
|
||||||
return Text(_text ?? '', key: _key ?? const Key('TextBuilder'), style: _textStyle, textAlign: TextAlign.center);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,100 +1,117 @@
|
|||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TextFieldBuilder {
|
class TextFieldBuilder extends StatefulWidget {
|
||||||
Key? _key;
|
|
||||||
ValueChanged<String>? _onTextChange;
|
|
||||||
ValueChanged<String>? _onTextSubmitted;
|
|
||||||
TextStyle? _textStyle;
|
|
||||||
TextInputAction? _textInputAction;
|
|
||||||
InputDecoration? _inputDecoration;
|
|
||||||
bool? _obscureText;
|
|
||||||
int? _maxLines = 1;
|
|
||||||
int? _minLines;
|
|
||||||
TextEditingController? _textController;
|
|
||||||
TextInputType? _keyboardType;
|
|
||||||
Color? _cursorColor;
|
|
||||||
bool? _autoFocus;
|
|
||||||
FocusNode? _focusNode;
|
|
||||||
|
|
||||||
void key(Key key) {
|
final ValueChanged<String>? onTextChange;
|
||||||
_key = key;
|
final ValueChanged<String>? onTextSubmitted;
|
||||||
|
final VoidCallback? onTap;
|
||||||
|
final TextStyle? textStyle;
|
||||||
|
final TextInputAction? textInputAction;
|
||||||
|
final InputDecoration? decoration;
|
||||||
|
final bool obscureText;
|
||||||
|
final int? maxLines;
|
||||||
|
final int? minLines;
|
||||||
|
final TextEditingController? controller;
|
||||||
|
final TextInputType? keyboardType;
|
||||||
|
final Color cursorColor;
|
||||||
|
final bool autoFocus;
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
final String? fromValue;
|
||||||
|
final Brightness? keyboardAppearance;
|
||||||
|
final bool autocorrect;
|
||||||
|
final TextDirection textDirection;
|
||||||
|
final bool readOnly;
|
||||||
|
final MouseCursor? mouseCursor;
|
||||||
|
|
||||||
|
const TextFieldBuilder({
|
||||||
|
super.key,
|
||||||
|
this.cursorColor = AppColor.primaryColor,
|
||||||
|
this.autocorrect = false,
|
||||||
|
this.obscureText = false,
|
||||||
|
this.autoFocus = false,
|
||||||
|
this.readOnly = false,
|
||||||
|
this.textStyle = const TextStyle(color: AppColor.textFieldTextColor),
|
||||||
|
this.textDirection = TextDirection.ltr,
|
||||||
|
this.textInputAction,
|
||||||
|
this.decoration,
|
||||||
|
this.maxLines,
|
||||||
|
this.minLines,
|
||||||
|
this.controller,
|
||||||
|
this.keyboardType,
|
||||||
|
this.focusNode,
|
||||||
|
this.fromValue,
|
||||||
|
this.keyboardAppearance,
|
||||||
|
this.mouseCursor,
|
||||||
|
this.onTap,
|
||||||
|
this.onTextChange,
|
||||||
|
this.onTextSubmitted,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<TextFieldBuilder> createState() => _TextFieldBuilderState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TextFieldBuilderState extends State<TextFieldBuilder> {
|
||||||
|
|
||||||
|
late TextEditingController _controller;
|
||||||
|
late TextDirection _textDirection;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
if (widget.fromValue != null) {
|
||||||
|
_controller = TextEditingController.fromValue(TextEditingValue(text: widget.fromValue!));
|
||||||
|
} else if (widget.controller != null) {
|
||||||
|
_controller = widget.controller!;
|
||||||
|
} else {
|
||||||
|
_controller = TextEditingController();
|
||||||
|
}
|
||||||
|
_textDirection = widget.textDirection;
|
||||||
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onChange(ValueChanged<String> onChange) {
|
@override
|
||||||
_onTextChange = onChange;
|
Widget build(BuildContext context) {
|
||||||
}
|
|
||||||
|
|
||||||
void onSubmitted(ValueChanged<String> onSubmitted) {
|
|
||||||
_onTextSubmitted = onSubmitted;
|
|
||||||
}
|
|
||||||
|
|
||||||
void textStyle(TextStyle style) {
|
|
||||||
_textStyle = style;
|
|
||||||
}
|
|
||||||
|
|
||||||
void textInputAction(TextInputAction inputAction) {
|
|
||||||
_textInputAction = inputAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void textDecoration(InputDecoration inputDecoration) {
|
|
||||||
_inputDecoration = inputDecoration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void obscureText(bool obscureText) {
|
|
||||||
_obscureText = obscureText;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setText(String value) {
|
|
||||||
_textController = TextEditingController.fromValue(TextEditingValue(text: value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void addController(TextEditingController? textEditingController) {
|
|
||||||
_textController = textEditingController;
|
|
||||||
}
|
|
||||||
|
|
||||||
void maxLines(int? value) {
|
|
||||||
_maxLines = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void minLines(int? value) {
|
|
||||||
_minLines = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void keyboardType(TextInputType? value) {
|
|
||||||
_keyboardType = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cursorColor(Color? color) {
|
|
||||||
_cursorColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void autoFocus(bool autoFocus) {
|
|
||||||
_autoFocus = autoFocus;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addFocusNode(FocusNode? focusNode) {
|
|
||||||
_focusNode = focusNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextField build() {
|
|
||||||
return TextField(
|
return TextField(
|
||||||
key: _key ?? const Key('TextFieldBuilder'),
|
key: widget.key,
|
||||||
onChanged: _onTextChange,
|
controller: _controller,
|
||||||
cursorColor: _cursorColor ?? AppColor.primaryColor,
|
cursorColor: widget.cursorColor,
|
||||||
controller: _textController,
|
autocorrect: widget.autocorrect,
|
||||||
autocorrect: false,
|
textInputAction: widget.textInputAction,
|
||||||
textInputAction: _textInputAction,
|
decoration: widget.decoration,
|
||||||
decoration: _inputDecoration,
|
maxLines: widget.maxLines,
|
||||||
maxLines: _maxLines,
|
minLines: widget.minLines,
|
||||||
minLines: _minLines,
|
keyboardAppearance: widget.keyboardAppearance,
|
||||||
keyboardAppearance: Brightness.light,
|
style: widget.textStyle,
|
||||||
style: _textStyle ?? const TextStyle(color: AppColor.textFieldTextColor),
|
obscureText: widget.obscureText,
|
||||||
obscureText: _obscureText ?? false,
|
keyboardType: widget.keyboardType,
|
||||||
keyboardType: _keyboardType,
|
autofocus: widget.autoFocus,
|
||||||
onSubmitted: _onTextSubmitted,
|
focusNode: widget.focusNode,
|
||||||
autofocus: _autoFocus ?? false,
|
textDirection: _textDirection,
|
||||||
focusNode: _focusNode,
|
readOnly: widget.readOnly,
|
||||||
|
mouseCursor: widget.mouseCursor,
|
||||||
|
onChanged: (value) {
|
||||||
|
widget.onTextChange?.call(value);
|
||||||
|
if (value.isNotEmpty) {
|
||||||
|
final directionByText = DirectionUtils.getDirectionByEndsText(value);
|
||||||
|
if (directionByText != _textDirection) {
|
||||||
|
setState(() {
|
||||||
|
_textDirection = directionByText;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSubmitted: widget.onTextSubmitted,
|
||||||
|
onTap: widget.onTap,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
if (widget.fromValue == null && widget.controller == null) {
|
||||||
|
_controller.dispose();
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart' as intl;
|
||||||
|
|
||||||
|
abstract class DirectionUtils {
|
||||||
|
|
||||||
|
static bool isDirectionRTLByLanguage(BuildContext context) => intl.Bidi.isRtlLanguage(Localizations.localeOf(context).languageCode);
|
||||||
|
|
||||||
|
static bool isDirectionRTLByEndsText(String text) => intl.Bidi.endsWithRtl(text);
|
||||||
|
|
||||||
|
static TextDirection getDirectionByLanguage(BuildContext context) => isDirectionRTLByLanguage(context) ? TextDirection.rtl : TextDirection.ltr;
|
||||||
|
|
||||||
|
static TextDirection getDirectionByEndsText(String text) => isDirectionRTLByEndsText(text) ? TextDirection.rtl : TextDirection.ltr;
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import 'dart:io';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
abstract class PlatformInfo {
|
abstract class PlatformInfo {
|
||||||
static bool get isWeb => kIsWeb;
|
static const bool isWeb = kIsWeb;
|
||||||
static bool get isLinux => !kIsWeb && Platform.isLinux;
|
static bool get isLinux => !kIsWeb && Platform.isLinux;
|
||||||
static bool get isWindows => !kIsWeb && Platform.isWindows;
|
static bool get isWindows => !kIsWeb && Platform.isWindows;
|
||||||
static bool get isMacOS => !kIsWeb && Platform.isMacOS;
|
static bool get isMacOS => !kIsWeb && Platform.isMacOS;
|
||||||
|
|||||||
@@ -296,6 +296,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
version: "4.0.2"
|
||||||
|
intl:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: intl
|
||||||
|
sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.17.0"
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ dependencies:
|
|||||||
# flutter_test from sdk depends on collection 1.17.0
|
# flutter_test from sdk depends on collection 1.17.0
|
||||||
collection: 1.17.0
|
collection: 1.17.0
|
||||||
|
|
||||||
|
# flutter_localizations depends on intl 0.17.0
|
||||||
|
intl: 0.17.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tmail_ui_user/features/base/widget/text_input_decoration_builder.dart';
|
import 'package:tmail_ui_user/features/base/widget/text_input_decoration_builder.dart';
|
||||||
|
|
||||||
typedef OnChangeInputAction = Function(String? value);
|
typedef OnChangeInputAction = Function(String value);
|
||||||
|
|
||||||
class TextInputFieldBuilder extends StatelessWidget {
|
class TextInputFieldBuilder extends StatelessWidget {
|
||||||
|
|
||||||
@@ -46,24 +47,23 @@ class TextInputFieldBuilder extends StatelessWidget {
|
|||||||
color: AppColor.colorContentEmail)),
|
color: AppColor.colorContentEmail)),
|
||||||
const SizedBox(height: 8)
|
const SizedBox(height: 8)
|
||||||
],
|
],
|
||||||
(TextFieldBuilder()
|
TextFieldBuilder(
|
||||||
..onChange((value) => onChangeInputAction?.call(value))
|
onTextChange: onChangeInputAction,
|
||||||
..textInputAction(TextInputAction.next)
|
textInputAction: TextInputAction.next,
|
||||||
..addController(editingController ?? TextEditingController())
|
controller: editingController,
|
||||||
..addFocusNode(focusNode)
|
focusNode: focusNode,
|
||||||
..textStyle(const TextStyle(color: Colors.black, fontSize: 16))
|
textStyle: const TextStyle(color: Colors.black, fontSize: 16),
|
||||||
..keyboardType(inputType ?? TextInputType.text)
|
keyboardType: inputType ?? TextInputType.text,
|
||||||
..minLines(minLines)
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..maxLines(maxLines)
|
minLines: minLines,
|
||||||
..textDecoration((TextInputDecorationBuilder()
|
maxLines: maxLines,
|
||||||
..setContentPadding(const EdgeInsets.symmetric(
|
decoration: (TextInputDecorationBuilder()
|
||||||
vertical: BuildUtils.isWeb ? 16 : 12,
|
..setContentPadding(const EdgeInsets.symmetric(vertical: PlatformInfo.isWeb ? 16 : 12, horizontal: 12))
|
||||||
horizontal: 12))
|
..setHintText(hint)
|
||||||
..setHintText(hint)
|
..setFillColor(backgroundColor)
|
||||||
..setFillColor(backgroundColor)
|
..setErrorText(error))
|
||||||
..setErrorText(error))
|
.build(),
|
||||||
.build()))
|
)
|
||||||
.build()
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@ import 'package:core/presentation/views/list/sliver_grid_delegate_fixed_height.d
|
|||||||
import 'package:core/presentation/views/responsive/responsive_widget.dart';
|
import 'package:core/presentation/views/responsive/responsive_widget.dart';
|
||||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:filesize/filesize.dart';
|
import 'package:filesize/filesize.dart';
|
||||||
@@ -490,16 +491,17 @@ class ComposerView extends GetWidget<ComposerController>
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Expanded(child: (TextFieldBuilder()
|
Expanded(child: TextFieldBuilder(
|
||||||
..key(const Key('subject_email_input'))
|
key: const Key('subject_email_input'),
|
||||||
..cursorColor(AppColor.colorTextButton)
|
cursorColor: AppColor.colorTextButton,
|
||||||
..maxLines(responsiveUtils.isMobile(context) ? null : 1)
|
maxLines: responsiveUtils.isMobile(context) ? null : 1,
|
||||||
..addFocusNode(controller.subjectEmailInputFocusNode)
|
focusNode: controller.subjectEmailInputFocusNode,
|
||||||
..onChange((value) => controller.setSubjectEmail(value))
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..textStyle(const TextStyle(color: Colors.black, fontSize: 15, fontWeight: FontWeight.normal))
|
onTextChange: controller.setSubjectEmail,
|
||||||
..textDecoration(const InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none))
|
textStyle: const TextStyle(color: Colors.black, fontSize: 15, fontWeight: FontWeight.normal),
|
||||||
..addController(controller.subjectEmailInputController))
|
decoration: const InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none),
|
||||||
.build())
|
controller: controller.subjectEmailInputController,
|
||||||
|
))
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:core/presentation/views/image/avatar_builder.dart';
|
|||||||
import 'package:core/presentation/views/responsive/responsive_widget.dart';
|
import 'package:core/presentation/views/responsive/responsive_widget.dart';
|
||||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:filesize/filesize.dart';
|
import 'package:filesize/filesize.dart';
|
||||||
@@ -690,16 +691,16 @@ class ComposerView extends GetWidget<ComposerController>
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Expanded(child: (TextFieldBuilder()
|
Expanded(child: TextFieldBuilder(
|
||||||
..key(const Key('subject_email_input'))
|
key: const Key('subject_email_input'),
|
||||||
..cursorColor(AppColor.colorTextButton)
|
cursorColor: AppColor.colorTextButton,
|
||||||
..addFocusNode(controller.subjectEmailInputFocusNode)
|
focusNode: controller.subjectEmailInputFocusNode,
|
||||||
..onChange((value) => controller.setSubjectEmail(value))
|
onTextChange: controller.setSubjectEmail,
|
||||||
..textStyle(const TextStyle(color: Colors.black, fontSize: 15, fontWeight: FontWeight.normal))
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..textDecoration(const InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none))
|
textStyle: const TextStyle(color: Colors.black, fontSize: 15, fontWeight: FontWeight.normal),
|
||||||
..addController(controller.subjectEmailInputController))
|
decoration: const InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none),
|
||||||
.build()
|
controller: controller.subjectEmailInputController,
|
||||||
)
|
))
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/presentation/views/button/icon_button_web.dart';
|
import 'package:core/presentation/views/button/icon_button_web.dart';
|
||||||
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
import 'package:core/utils/build_utils.dart';
|
import 'package:core/utils/build_utils.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -101,7 +102,7 @@ class InsertImageDialogBuilder {
|
|||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
fontWeight: FontWeight.w500)),
|
fontWeight: FontWeight.w500)),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
TextField(
|
TextFieldBuilder(
|
||||||
controller: _inputUrlController,
|
controller: _inputUrlController,
|
||||||
textInputAction: TextInputAction.done,
|
textInputAction: TextInputAction.done,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@@ -110,7 +111,7 @@ class InsertImageDialogBuilder {
|
|||||||
errorText: validateFailed,
|
errorText: validateFailed,
|
||||||
errorMaxLines: 2,
|
errorMaxLines: 2,
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
actionsPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
|
actionsPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ class ContactController extends BaseController {
|
|||||||
_deBouncerTime.value = text;
|
_deBouncerTime.value = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onSearchTextAction(String text) {
|
||||||
|
_deBouncerTime.value = text;
|
||||||
|
}
|
||||||
|
|
||||||
void clearAllTextInputSearchForm() {
|
void clearAllTextInputSearchForm() {
|
||||||
textInputSearchController?.clear();
|
textInputSearchController?.clear();
|
||||||
searchQuery.value = SearchQuery.initial();
|
searchQuery.value = SearchQuery.initial();
|
||||||
|
|||||||
@@ -78,29 +78,29 @@ class ContactView extends GetWidget<ContactController> {
|
|||||||
onCloseContactView: () => controller.closeContactView(context))
|
onCloseContactView: () => controller.closeContactView(context))
|
||||||
),
|
),
|
||||||
const Divider(color: AppColor.colorDividerComposer, height: 1),
|
const Divider(color: AppColor.colorDividerComposer, height: 1),
|
||||||
(SearchAppBarWidget(
|
SearchAppBarWidget(
|
||||||
_imagePaths,
|
imagePaths: _imagePaths,
|
||||||
controller.searchQuery.value,
|
searchQuery: controller.searchQuery.value,
|
||||||
controller.textInputSearchFocus,
|
searchFocusNode: controller.textInputSearchFocus,
|
||||||
controller.textInputSearchController,
|
searchInputController :controller.textInputSearchController,
|
||||||
hasBackButton: false,
|
hasBackButton: false,
|
||||||
hasSearchButton: true)
|
hasSearchButton: true,
|
||||||
..addPadding(EdgeInsets.zero)
|
padding: EdgeInsets.zero,
|
||||||
..setHeightSearchBar(44)
|
heightSearchBar: 44,
|
||||||
..setMargin(ContactUtils.getPaddingSearchInputForm(context, _responsiveUtils))
|
margin: ContactUtils.getPaddingSearchInputForm(context, _responsiveUtils),
|
||||||
..addDecoration(BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
color: AppColor.colorBgSearchBar))
|
color: AppColor.colorBgSearchBar),
|
||||||
..addIconClearText(SvgPicture.asset(
|
iconClearText: SvgPicture.asset(
|
||||||
_imagePaths.icClearTextSearch,
|
_imagePaths.icClearTextSearch,
|
||||||
width: 18,
|
width: 18,
|
||||||
height: 18,
|
height: 18,
|
||||||
fit: BoxFit.fill))
|
fit: BoxFit.fill),
|
||||||
..setHintText(AppLocalizations.of(context).hintSearchInputContact)
|
hintText: AppLocalizations.of(context).hintSearchInputContact,
|
||||||
..addOnClearTextSearchAction(() => controller.clearAllTextInputSearchForm())
|
onClearTextSearchAction: controller.clearAllTextInputSearchForm,
|
||||||
..addOnTextChangeSearchAction(controller.onTextSearchChange)
|
onTextChangeSearchAction: controller.onTextSearchChange,
|
||||||
..addOnSearchTextAction((query) => {}))
|
onSearchTextAction: controller.onSearchTextAction,
|
||||||
.build(),
|
),
|
||||||
Expanded(child: Obx(() {
|
Expanded(child: Obx(() {
|
||||||
if (controller.listContactSearched.isNotEmpty) {
|
if (controller.listContactSearched.isNotEmpty) {
|
||||||
return Container(
|
return Container(
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:core/presentation/views/list/tree_view.dart';
|
|||||||
import 'package:core/presentation/views/search/search_bar_view.dart';
|
import 'package:core/presentation/views/search/search_bar_view.dart';
|
||||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
import 'package:core/utils/build_utils.dart';
|
import 'package:core/utils/build_utils.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -171,23 +172,24 @@ class DestinationPickerView extends GetWidget<DestinationPickerController>
|
|||||||
Widget _buildCreateMailboxNameInput(BuildContext context) {
|
Widget _buildCreateMailboxNameInput(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
||||||
child: Obx(() => (TextFieldBuilder()
|
child: Obx(() => TextFieldBuilder(
|
||||||
..key(const Key('create_mailbox_name_input'))
|
key: const Key('create_mailbox_name_input'),
|
||||||
..onChange((value) => controller.setNewNameMailbox(value))
|
onTextChange: controller.setNewNameMailbox,
|
||||||
..keyboardType(TextInputType.visiblePassword)
|
keyboardType: TextInputType.visiblePassword,
|
||||||
..cursorColor(AppColor.colorTextButton)
|
cursorColor: AppColor.colorTextButton,
|
||||||
..addController(controller.nameInputController)
|
controller: controller.nameInputController,
|
||||||
..maxLines(1)
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..textStyle(const TextStyle(
|
maxLines: 1,
|
||||||
color: AppColor.colorNameEmail,
|
textStyle: const TextStyle(
|
||||||
fontSize: 16,
|
color: AppColor.colorNameEmail,
|
||||||
overflow: CommonTextStyle.defaultTextOverFlow))
|
fontSize: 16,
|
||||||
..addFocusNode(controller.nameInputFocusNode)
|
overflow: CommonTextStyle.defaultTextOverFlow),
|
||||||
..textDecoration((CreateMailboxNameInputDecorationBuilder()
|
focusNode: controller.nameInputFocusNode,
|
||||||
..setHintText(AppLocalizations.of(context).hint_input_create_new_mailbox)
|
decoration: (CreateMailboxNameInputDecorationBuilder()
|
||||||
..setErrorText(controller.getErrorInputNameString(context)))
|
..setHintText(AppLocalizations.of(context).hint_input_create_new_mailbox)
|
||||||
.build()))
|
..setErrorText(controller.getErrorInputNameString(context)))
|
||||||
.build())
|
.build(),
|
||||||
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,25 +556,30 @@ class DestinationPickerView extends GetWidget<DestinationPickerController>
|
|||||||
colorFilter: AppColor.colorTextButton.asFilter(),
|
colorFilter: AppColor.colorTextButton.asFilter(),
|
||||||
fit: BoxFit.fill),
|
fit: BoxFit.fill),
|
||||||
onTap: () => controller.disableSearch(context))),
|
onTap: () => controller.disableSearch(context))),
|
||||||
Expanded(child: (SearchAppBarWidget(
|
Expanded(child: SearchAppBarWidget(
|
||||||
_imagePaths,
|
imagePaths: _imagePaths,
|
||||||
controller.searchQuery.value,
|
searchQuery: controller.searchQuery.value,
|
||||||
controller.searchFocus,
|
searchFocusNode: controller.searchFocus,
|
||||||
controller.searchInputController,
|
searchInputController: controller.searchInputController,
|
||||||
hasBackButton: false,
|
hasBackButton: false,
|
||||||
hasSearchButton: true)
|
hasSearchButton: true,
|
||||||
..addPadding(EdgeInsets.zero)
|
padding: EdgeInsets.zero,
|
||||||
..setMargin(EdgeInsets.only(
|
margin: EdgeInsets.only(
|
||||||
right: AppUtils.isDirectionRTL(context) ? 0 : 16,
|
right: DirectionUtils.isDirectionRTLByLanguage(context) ? 0 : 16,
|
||||||
left: AppUtils.isDirectionRTL(context) ? 16 : 0,
|
left: DirectionUtils.isDirectionRTLByLanguage(context) ? 16 : 0),
|
||||||
))
|
decoration: const BoxDecoration(
|
||||||
..addDecoration(BoxDecoration(borderRadius: BorderRadius.circular(12), color: AppColor.colorBgSearchBar))
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
..addIconClearText(SvgPicture.asset(_imagePaths.icClearTextSearch, width: 18, height: 18, fit: BoxFit.fill))
|
color: AppColor.colorBgSearchBar),
|
||||||
..setHintText(AppLocalizations.of(context).hint_search_mailboxes)
|
iconClearText: SvgPicture.asset(
|
||||||
..addOnClearTextSearchAction(() => controller.clearSearchText())
|
_imagePaths.icClearTextSearch,
|
||||||
..addOnTextChangeSearchAction((query) => controller.searchMailbox(query))
|
width: 18,
|
||||||
..addOnSearchTextAction((query) => controller.searchMailbox(query)))
|
height: 18,
|
||||||
.build())
|
fit: BoxFit.fill),
|
||||||
|
hintText: AppLocalizations.of(context).hint_search_mailboxes,
|
||||||
|
onClearTextSearchAction: controller.clearSearchText,
|
||||||
|
onTextChangeSearchAction: controller.searchMailbox,
|
||||||
|
onSearchTextAction: controller.searchMailbox,
|
||||||
|
))
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
+16
-16
@@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
import 'package:core/utils/build_utils.dart';
|
import 'package:core/utils/direction_utils.dart';
|
||||||
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_input_decoration_builder.dart';
|
import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_input_decoration_builder.dart';
|
||||||
|
|
||||||
@@ -41,21 +42,20 @@ class IdentityInputFieldBuilder extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: AppColor.colorContentEmail)),
|
color: AppColor.colorContentEmail)),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
(TextFieldBuilder()
|
TextFieldBuilder(
|
||||||
..onChange((value) => onChangeInputNameAction?.call(value))
|
onTextChange: onChangeInputNameAction,
|
||||||
..textInputAction(TextInputAction.next)
|
textInputAction: TextInputAction.next,
|
||||||
..addController(editingController ?? TextEditingController())
|
autoFocus: true,
|
||||||
..autoFocus(true)
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..addFocusNode(focusNode)
|
controller: editingController,
|
||||||
..textStyle(const TextStyle(color: Colors.black, fontSize: 16))
|
focusNode: focusNode,
|
||||||
..keyboardType(inputType ?? TextInputType.text)
|
textStyle: const TextStyle(color: Colors.black, fontSize: 16),
|
||||||
..textDecoration((IdentityInputDecorationBuilder()
|
keyboardType: inputType ?? TextInputType.text,
|
||||||
..setContentPadding(const EdgeInsets.symmetric(
|
decoration: (IdentityInputDecorationBuilder()
|
||||||
vertical: BuildUtils.isWeb ? 16 : 12,
|
..setContentPadding(const EdgeInsets.symmetric(vertical: PlatformInfo.isWeb ? 16 : 12,horizontal: 12))
|
||||||
horizontal: 12))
|
..setErrorText(_error))
|
||||||
..setErrorText(_error))
|
.build(),
|
||||||
.build()))
|
)
|
||||||
.build()
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/presentation/resources/image_paths.dart';
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||||
import 'package:core/presentation/views/text/text_builder.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -30,9 +29,8 @@ abstract class BaseLoginView extends GetWidget<LoginController> {
|
|||||||
padding: const EdgeInsets.only(top: 11, bottom: 36, left: 58, right: 58),
|
padding: const EdgeInsets.only(top: 11, bottom: 36, left: 58, right: 58),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: responsiveUtils.getWidthLoginTextField(context),
|
width: responsiveUtils.getWidthLoginTextField(context),
|
||||||
child: CenterTextBuilder()
|
child: Text(
|
||||||
.key(const Key('login_message'))
|
loginState.viewState.fold(
|
||||||
.text(loginState.viewState.fold(
|
|
||||||
(failure) {
|
(failure) {
|
||||||
if (failure is LoginMissUrlAction) {
|
if (failure is LoginMissUrlAction) {
|
||||||
return AppLocalizations.of(context).requiredUrl;
|
return AppLocalizations.of(context).requiredUrl;
|
||||||
@@ -43,7 +41,7 @@ abstract class BaseLoginView extends GetWidget<LoginController> {
|
|||||||
} else if (failure is LoginSSONotAvailableAction) {
|
} else if (failure is LoginSSONotAvailableAction) {
|
||||||
return AppLocalizations.of(context).ssoNotAvailable;
|
return AppLocalizations.of(context).ssoNotAvailable;
|
||||||
} else if (failure is GetOIDCConfigurationFailure
|
} else if (failure is GetOIDCConfigurationFailure
|
||||||
|| failure is LoginCanNotVerifySSOConfigurationAction) {
|
|| failure is LoginCanNotVerifySSOConfigurationAction) {
|
||||||
return AppLocalizations.of(context).canNotVerifySSOConfiguration;
|
return AppLocalizations.of(context).canNotVerifySSOConfiguration;
|
||||||
} else if (failure is GetTokenOIDCFailure || failure is LoginCanNotGetTokenAction) {
|
} else if (failure is GetTokenOIDCFailure || failure is LoginCanNotGetTokenAction) {
|
||||||
return AppLocalizations.of(context).canNotGetToken;
|
return AppLocalizations.of(context).canNotGetToken;
|
||||||
@@ -58,15 +56,16 @@ abstract class BaseLoginView extends GetWidget<LoginController> {
|
|||||||
return AppLocalizations.of(context).loginInputSSOMessage;
|
return AppLocalizations.of(context).loginInputSSOMessage;
|
||||||
}
|
}
|
||||||
return AppLocalizations.of(context).loginInputUrlMessage;
|
return AppLocalizations.of(context).loginInputUrlMessage;
|
||||||
}))
|
}),
|
||||||
.textStyle(TextStyle(
|
key: const Key('login_message'),
|
||||||
fontSize: 15,
|
textAlign: TextAlign.center,
|
||||||
fontWeight: FontWeight.w400,
|
style: TextStyle(
|
||||||
color: loginState.viewState.fold(
|
fontSize: 15,
|
||||||
(failure) => AppColor.textFieldErrorBorderColor,
|
fontWeight: FontWeight.w400,
|
||||||
(success) => AppColor.colorNameEmail)))
|
color: loginState.viewState.fold(
|
||||||
.build()
|
(failure) => AppColor.textFieldErrorBorderColor,
|
||||||
)
|
(success) => AppColor.colorNameEmail)),
|
||||||
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:core/presentation/utils/responsive_utils.dart';
|
|||||||
import 'package:core/presentation/utils/style_utils.dart';
|
import 'package:core/presentation/utils/style_utils.dart';
|
||||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
import 'package:core/utils/build_utils.dart';
|
import 'package:core/utils/build_utils.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -112,23 +113,24 @@ class MailboxCreatorView extends GetWidget<MailboxCreatorController> {
|
|||||||
Widget _buildCreateMailboxNameInput(BuildContext context) {
|
Widget _buildCreateMailboxNameInput(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
||||||
child: Obx(() => (TextFieldBuilder()
|
child: Obx(() => TextFieldBuilder(
|
||||||
..key(const Key('create_mailbox_name_input'))
|
key: const Key('create_mailbox_name_input'),
|
||||||
..onChange((value) => controller.setNewNameMailbox(value))
|
onTextChange: controller.setNewNameMailbox,
|
||||||
..keyboardType(TextInputType.visiblePassword)
|
keyboardType: TextInputType.visiblePassword,
|
||||||
..cursorColor(AppColor.colorTextButton)
|
cursorColor: AppColor.colorTextButton,
|
||||||
..addController(controller.nameInputController)
|
controller: controller.nameInputController,
|
||||||
..maxLines(1)
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..textStyle(const TextStyle(
|
maxLines: 1,
|
||||||
color: AppColor.colorNameEmail,
|
textStyle: const TextStyle(
|
||||||
fontSize: 16,
|
color: AppColor.colorNameEmail,
|
||||||
overflow: CommonTextStyle.defaultTextOverFlow))
|
fontSize: 16,
|
||||||
..addFocusNode(controller.nameInputFocusNode)
|
overflow: CommonTextStyle.defaultTextOverFlow),
|
||||||
..textDecoration((CreateMailboxNameInputDecorationBuilder()
|
focusNode: controller.nameInputFocusNode,
|
||||||
..setHintText(AppLocalizations.of(context).hint_input_create_new_mailbox)
|
decoration: (CreateMailboxNameInputDecorationBuilder()
|
||||||
..setErrorText(controller.getErrorInputNameString(context)))
|
..setHintText(AppLocalizations.of(context).hint_input_create_new_mailbox)
|
||||||
.build()))
|
..setErrorText(controller.getErrorInputNameString(context)))
|
||||||
.build())
|
.build(),
|
||||||
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -356,13 +356,13 @@ class AdvancedSearchInputForm extends GetWidget<AdvancedFilterController>
|
|||||||
nextFocusNode?.requestFocus();
|
nextFocusNode?.requestFocus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: TextField(
|
child: TextFieldBuilder(
|
||||||
controller: textEditingController,
|
controller: textEditingController,
|
||||||
readOnly: isSelectFormList,
|
readOnly: isSelectFormList,
|
||||||
mouseCursor: mouseCursor,
|
mouseCursor: mouseCursor,
|
||||||
textInputAction: isSelectFormList ? TextInputAction.done : TextInputAction.next,
|
textInputAction: isSelectFormList ? TextInputAction.done : TextInputAction.next,
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
onSubmitted: (value) {
|
onTextSubmitted: (value) {
|
||||||
if (isSelectFormList) {
|
if (isSelectFormList) {
|
||||||
onTap?.call();
|
onTap?.call();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+14
-8
@@ -1,5 +1,11 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:core/core.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
|
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||||
|
import 'package:core/presentation/utils/style_utils.dart';
|
||||||
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
|
import 'package:core/utils/app_logger.dart';
|
||||||
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -66,8 +72,8 @@ class _TextFieldAutoCompleteEmailAddressState
|
|||||||
optionsViewBuilder: (context, onSelected, listEmailAddress) {
|
optionsViewBuilder: (context, onSelected, listEmailAddress) {
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.only(
|
margin: const EdgeInsets.only(
|
||||||
top: BuildUtils.isWeb ? 5 : 8,
|
top: PlatformInfo.isWeb ? 5 : 8,
|
||||||
bottom: 16),
|
bottom: 16),
|
||||||
height: _getHeightSuggestionBox(listEmailAddress.length, 65),
|
height: _getHeightSuggestionBox(listEmailAddress.length, 65),
|
||||||
width: maxWidthSuggestionBox,
|
width: maxWidthSuggestionBox,
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
@@ -134,7 +140,7 @@ class _TextFieldAutoCompleteEmailAddressState
|
|||||||
widget.nextFocusNode?.requestFocus();
|
widget.nextFocusNode?.requestFocus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: TextField(
|
child: TextFieldBuilder(
|
||||||
controller: tec,
|
controller: tec,
|
||||||
focusNode: fn,
|
focusNode: fn,
|
||||||
textInputAction: TextInputAction.next,
|
textInputAction: TextInputAction.next,
|
||||||
@@ -180,12 +186,12 @@ class _TextFieldAutoCompleteEmailAddressState
|
|||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
onChanged: (value) {
|
onTextChange: (value) {
|
||||||
if (value.trim().isNotEmpty) {
|
if (value.trim().isNotEmpty) {
|
||||||
onChanged?.call(value);
|
onChanged?.call(value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSubmitted: (tag) {
|
onTextSubmitted: (tag) {
|
||||||
if (tag.trim().isNotEmpty) {
|
if (tag.trim().isNotEmpty) {
|
||||||
onSubmitted?.call(tag);
|
onSubmitted?.call(tag);
|
||||||
fn.requestFocus();
|
fn.requestFocus();
|
||||||
@@ -334,7 +340,7 @@ class _TextFieldAutoCompleteEmailAddressState
|
|||||||
double _getHeightSuggestionBox(int countItem, double heightItem) {
|
double _getHeightSuggestionBox(int countItem, double heightItem) {
|
||||||
final maxHeightList = countItem * heightItem;
|
final maxHeightList = countItem * heightItem;
|
||||||
|
|
||||||
if (BuildUtils.isWeb) {
|
if (PlatformInfo.isWeb) {
|
||||||
return maxHeightList > 250 ? 250 : maxHeightList;
|
return maxHeightList > 250 ? 250 : maxHeightList;
|
||||||
} else {
|
} else {
|
||||||
if (_responsiveUtils.isLandscapeMobile(context)) {
|
if (_responsiveUtils.isLandscapeMobile(context)) {
|
||||||
@@ -346,7 +352,7 @@ class _TextFieldAutoCompleteEmailAddressState
|
|||||||
}
|
}
|
||||||
|
|
||||||
double get maxWidthSuggestionBox {
|
double get maxWidthSuggestionBox {
|
||||||
if (BuildUtils.isWeb) {
|
if (PlatformInfo.isWeb) {
|
||||||
if (_responsiveUtils.isTabletLarge(context)) {
|
if (_responsiveUtils.isTabletLarge(context)) {
|
||||||
return 300;
|
return 300;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:core/presentation/resources/image_paths.dart';
|
|||||||
import 'package:core/presentation/utils/style_utils.dart';
|
import 'package:core/presentation/utils/style_utils.dart';
|
||||||
import 'package:core/presentation/views/button/icon_button_web.dart';
|
import 'package:core/presentation/views/button/icon_button_web.dart';
|
||||||
import 'package:core/presentation/views/quick_search/quick_search_input_form.dart';
|
import 'package:core/presentation/views/quick_search/quick_search_input_form.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_portal/flutter_portal.dart';
|
import 'package:flutter_portal/flutter_portal.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
@@ -186,6 +187,7 @@ class SearchInputFormWidget extends StatelessWidget with AppLoaderMixin {
|
|||||||
controller: controller.searchInputController,
|
controller: controller.searchInputController,
|
||||||
focusNode: controller.searchFocus,
|
focusNode: controller.searchFocus,
|
||||||
textInputAction: TextInputAction.done,
|
textInputAction: TextInputAction.done,
|
||||||
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
onSubmitted: (keyword) => _invokeSearchEmailAction(context, keyword.trim()),
|
onSubmitted: (keyword) => _invokeSearchEmailAction(context, keyword.trim()),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:core/presentation/utils/html_transformer/html_utils.dart';
|
import 'package:core/presentation/utils/html_transformer/html_utils.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -409,22 +410,21 @@ class VacationView extends GetWidget<VacationController> with RichTextButtonMixi
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMessagePlainTextEditor(BuildContext context) {
|
Widget _buildMessagePlainTextEditor(BuildContext context) {
|
||||||
return (TextFieldBuilder()
|
return TextFieldBuilder(
|
||||||
..onChange((value) => controller.updateMessageBody(context, value))
|
onTextChange: (value) => controller.updateMessageBody(context, value),
|
||||||
..keyboardType(TextInputType.multiline)
|
keyboardType: TextInputType.multiline,
|
||||||
..addController(controller.messageTextController)
|
controller: controller.messageTextController,
|
||||||
..textStyle(const TextStyle(color: Colors.black, fontSize: 16))
|
textStyle: const TextStyle(color: Colors.black, fontSize: 16),
|
||||||
..minLines(10)
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..maxLines(null)
|
minLines: 10,
|
||||||
..textDecoration((TextInputDecorationBuilder()
|
maxLines: null,
|
||||||
|
decoration: (TextInputDecorationBuilder()
|
||||||
..setContentPadding(const EdgeInsets.all(16))
|
..setContentPadding(const EdgeInsets.all(16))
|
||||||
..setHintText(AppLocalizations.of(context).hintMessageBodyVacation)
|
..setHintText(AppLocalizations.of(context).hintMessageBodyVacation)
|
||||||
..setFillColor(Colors.white)
|
..setFillColor(Colors.white)
|
||||||
..setErrorText(controller.isVacationDeactivated
|
..setErrorText(controller.isVacationDeactivated ? null : controller.errorMessageBody.value))
|
||||||
? null
|
.build(),
|
||||||
: controller.errorMessageBody.value))
|
);
|
||||||
.build()))
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMessageHtmlTextEditor(BuildContext context) {
|
Widget _buildMessageHtmlTextEditor(BuildContext context) {
|
||||||
|
|||||||
+16
-16
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
import 'package:core/utils/build_utils.dart';
|
import 'package:core/utils/direction_utils.dart';
|
||||||
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_decoration_builder.dart';
|
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_decoration_builder.dart';
|
||||||
|
|
||||||
@@ -25,20 +26,19 @@ class RulesFilterInputField extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return (TextFieldBuilder()
|
return TextFieldBuilder(
|
||||||
..onChange((value) => onChangeAction?.call(value))
|
onTextChange: onChangeAction,
|
||||||
..textInputAction(TextInputAction.next)
|
textInputAction: TextInputAction.next,
|
||||||
..addController(editingController ?? TextEditingController())
|
controller: editingController,
|
||||||
..textStyle(const TextStyle(color: Colors.black, fontSize: 16))
|
textStyle: const TextStyle(color: Colors.black, fontSize: 16),
|
||||||
..keyboardType(TextInputType.text)
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..addFocusNode(focusNode)
|
keyboardType: TextInputType.text,
|
||||||
..textDecoration((RulesFilterInputDecorationBuilder()
|
focusNode: focusNode,
|
||||||
..setContentPadding(const EdgeInsets.symmetric(
|
decoration: (RulesFilterInputDecorationBuilder()
|
||||||
vertical: BuildUtils.isWeb ? 16 : 12,
|
..setContentPadding(const EdgeInsets.symmetric(vertical: PlatformInfo.isWeb ? 16 : 12, horizontal: 12))
|
||||||
horizontal: 12))
|
..setHintText(hintText)
|
||||||
..setHintText(hintText)
|
..setErrorText(errorText))
|
||||||
..setErrorText(errorText))
|
.build(),
|
||||||
.build()))
|
);
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -642,6 +642,14 @@ class SearchEmailController extends BaseController
|
|||||||
_deBouncerTime.value = text;
|
_deBouncerTime.value = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onTextSearchSubmitted(BuildContext context, String text) {
|
||||||
|
final query = text.trim();
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
saveRecentSearch(RecentSearch.now(query));
|
||||||
|
submitSearchAction(context, query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void setTextInputSearchForm(String value) {
|
void setTextInputSearchForm(String value) {
|
||||||
textInputSearchController.text = value;
|
textInputSearchController.text = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:core/presentation/views/background/background_widget_builder.dar
|
|||||||
import 'package:core/presentation/views/button/icon_button_web.dart';
|
import 'package:core/presentation/views/button/icon_button_web.dart';
|
||||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
import 'package:core/utils/build_utils.dart';
|
import 'package:core/utils/build_utils.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -117,29 +118,21 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
|||||||
tooltip: AppLocalizations.of(context).back,
|
tooltip: AppLocalizations.of(context).back,
|
||||||
onTap: () => controller.closeSearchView(context)
|
onTap: () => controller.closeSearchView(context)
|
||||||
),
|
),
|
||||||
Expanded(child: (TextFieldBuilder()
|
Expanded(child: TextFieldBuilder(
|
||||||
..onChange(controller.onTextSearchChange)
|
onTextChange: controller.onTextSearchChange,
|
||||||
..textInputAction(TextInputAction.search)
|
textInputAction: TextInputAction.search,
|
||||||
..addController(controller.textInputSearchController)
|
controller: controller.textInputSearchController,
|
||||||
..addFocusNode(controller.textInputSearchFocus)
|
focusNode: controller.textInputSearchFocus,
|
||||||
..textStyle(const TextStyle(color: Colors.black, fontSize: 16))
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..keyboardType(TextInputType.text)
|
textStyle: const TextStyle(color: Colors.black, fontSize: 16),
|
||||||
..onSubmitted((value) {
|
keyboardType: TextInputType.text,
|
||||||
final query = value.trim();
|
onTextSubmitted: (text) => controller.onTextSearchSubmitted(context, text),
|
||||||
if (query.isNotEmpty) {
|
decoration: InputDecoration(
|
||||||
controller.saveRecentSearch(RecentSearch.now(query));
|
contentPadding: const EdgeInsets.all(12),
|
||||||
controller.submitSearchAction(context, query);
|
hintText: AppLocalizations.of(context).search_emails,
|
||||||
}
|
hintStyle: const TextStyle(color: AppColor.loginTextFieldHintColor, fontSize: 16),
|
||||||
})
|
border: InputBorder.none),
|
||||||
..maxLines(1)
|
)),
|
||||||
..textDecoration(InputDecoration(
|
|
||||||
contentPadding: const EdgeInsets.all(12),
|
|
||||||
hintText: AppLocalizations.of(context).search_emails,
|
|
||||||
hintStyle: const TextStyle(
|
|
||||||
color: AppColor.loginTextFieldHintColor,
|
|
||||||
fontSize: 16),
|
|
||||||
border: InputBorder.none)))
|
|
||||||
.build()),
|
|
||||||
Obx(() {
|
Obx(() {
|
||||||
if (controller.currentSearchText.isNotEmpty) {
|
if (controller.currentSearchText.isNotEmpty) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -207,6 +207,13 @@ class SearchMailboxController extends BaseMailboxController with MailboxActionHa
|
|||||||
_deBouncerTime.value = text;
|
_deBouncerTime.value = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onTextSearchSubmitted(BuildContext context, String text) {
|
||||||
|
final query = text.trim();
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
submitSearchAction(context, query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void setTextInputSearchForm(String value) {
|
void setTextInputSearchForm(String value) {
|
||||||
textInputSearchController.text = value;
|
textInputSearchController.text = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:core/presentation/extensions/color_extension.dart';
|
|||||||
import 'package:core/presentation/views/button/icon_button_web.dart';
|
import 'package:core/presentation/views/button/icon_button_web.dart';
|
||||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
import 'package:core/utils/build_utils.dart';
|
import 'package:core/utils/build_utils.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:focused_menu_custom/modals.dart';
|
import 'package:focused_menu_custom/modals.dart';
|
||||||
@@ -138,33 +139,28 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTextFieldSearchInput(BuildContext context) {
|
Widget _buildTextFieldSearchInput(BuildContext context) {
|
||||||
return (TextFieldBuilder()
|
return TextFieldBuilder(
|
||||||
..onChange(controller.onTextSearchChange)
|
onTextChange: controller.onTextSearchChange,
|
||||||
..textInputAction(TextInputAction.search)
|
textInputAction: TextInputAction.search,
|
||||||
..autoFocus(true)
|
autoFocus: true,
|
||||||
..addController(controller.textInputSearchController)
|
controller: controller.textInputSearchController,
|
||||||
..textStyle(const TextStyle(
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
color: Colors.black,
|
textStyle: const TextStyle(
|
||||||
|
color: Colors.black,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.normal),
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
onTextSubmitted: (text) => controller.onTextSearchSubmitted(context, text),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
hintText: AppLocalizations.of(context).searchForMailboxes,
|
||||||
|
hintStyle: const TextStyle(
|
||||||
|
color: AppColor.loginTextFieldHintColor,
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
fontWeight: FontWeight.normal))
|
fontWeight: FontWeight.normal),
|
||||||
..keyboardType(TextInputType.text)
|
border: InputBorder.none
|
||||||
..onSubmitted((value) {
|
),
|
||||||
final query = value.trim();
|
);
|
||||||
if (query.isNotEmpty) {
|
|
||||||
controller.submitSearchAction(context, query);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
..maxLines(1)
|
|
||||||
..textDecoration(InputDecoration(
|
|
||||||
contentPadding: EdgeInsets.zero,
|
|
||||||
hintText: AppLocalizations.of(context).searchForMailboxes,
|
|
||||||
hintStyle: const TextStyle(
|
|
||||||
color: AppColor.loginTextFieldHintColor,
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: FontWeight.normal),
|
|
||||||
border: InputBorder.none
|
|
||||||
)
|
|
||||||
)).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMailboxListView(BuildContext context) {
|
Widget _buildMailboxListView(BuildContext context) {
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
|
||||||
import 'package:core/core.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
|
import 'package:core/presentation/views/button/icon_button_web.dart';
|
||||||
|
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||||
|
import 'package:core/utils/direction_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
||||||
@@ -9,93 +13,61 @@ typedef OnClearTextSearchAction = Function();
|
|||||||
typedef OnTextChangeSearchAction = Function(String);
|
typedef OnTextChangeSearchAction = Function(String);
|
||||||
typedef OnSearchTextAction = Function(String);
|
typedef OnSearchTextAction = Function(String);
|
||||||
|
|
||||||
class SearchAppBarWidget {
|
class SearchAppBarWidget extends StatelessWidget {
|
||||||
OnCancelSearchPressed? _onCancelSearchPressed;
|
|
||||||
OnTextChangeSearchAction? _onTextChangeSearchAction;
|
|
||||||
OnClearTextSearchAction? _onClearTextSearchAction;
|
|
||||||
OnSearchTextAction? _onSearchTextAction;
|
|
||||||
|
|
||||||
final ImagePaths _imagePaths;
|
final ImagePaths imagePaths;
|
||||||
final SearchQuery? _searchQuery;
|
final SearchQuery? searchQuery;
|
||||||
final TextEditingController? _searchInputController;
|
final TextEditingController? searchInputController;
|
||||||
final FocusNode? _searchFocusNode;
|
final FocusNode? searchFocusNode;
|
||||||
final List<String>? suggestionSearch;
|
final List<String>? suggestionSearch;
|
||||||
final bool hasBackButton;
|
final bool hasBackButton;
|
||||||
final bool hasSearchButton;
|
final bool hasSearchButton;
|
||||||
|
final double? heightSearchBar;
|
||||||
|
final Decoration? decoration;
|
||||||
|
final EdgeInsets? padding;
|
||||||
|
final EdgeInsets? margin;
|
||||||
|
final String? hintText;
|
||||||
|
final Widget? iconClearText;
|
||||||
|
final OnCancelSearchPressed? onCancelSearchPressed;
|
||||||
|
final OnTextChangeSearchAction? onTextChangeSearchAction;
|
||||||
|
final OnClearTextSearchAction? onClearTextSearchAction;
|
||||||
|
final OnSearchTextAction? onSearchTextAction;
|
||||||
|
|
||||||
double? _heightSearchBar;
|
const SearchAppBarWidget({
|
||||||
Decoration? _decoration;
|
super.key,
|
||||||
EdgeInsets? _padding;
|
required this.imagePaths,
|
||||||
EdgeInsets? _margin;
|
required this.hasBackButton,
|
||||||
String? _hintText;
|
required this.hasSearchButton,
|
||||||
Widget? _iconClearText;
|
this.searchQuery,
|
||||||
|
this.searchInputController,
|
||||||
|
this.searchFocusNode,
|
||||||
|
this.suggestionSearch,
|
||||||
|
this.heightSearchBar,
|
||||||
|
this.decoration,
|
||||||
|
this.padding,
|
||||||
|
this.margin,
|
||||||
|
this.hintText,
|
||||||
|
this.iconClearText,
|
||||||
|
this.onCancelSearchPressed,
|
||||||
|
this.onTextChangeSearchAction,
|
||||||
|
this.onClearTextSearchAction,
|
||||||
|
this.onSearchTextAction
|
||||||
|
});
|
||||||
|
|
||||||
SearchAppBarWidget(
|
@override
|
||||||
this._imagePaths,
|
Widget build(BuildContext context) {
|
||||||
this._searchQuery,
|
|
||||||
this._searchFocusNode,
|
|
||||||
this._searchInputController,
|
|
||||||
{
|
|
||||||
this.hasBackButton = true,
|
|
||||||
this.suggestionSearch,
|
|
||||||
this.hasSearchButton = false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
void addOnCancelSearchPressed(OnCancelSearchPressed onCancelSearchPressed) {
|
|
||||||
_onCancelSearchPressed = onCancelSearchPressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addOnTextChangeSearchAction(OnTextChangeSearchAction onTextChangeSearchAction) {
|
|
||||||
_onTextChangeSearchAction = onTextChangeSearchAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addOnClearTextSearchAction(OnClearTextSearchAction onClearTextSearchAction) {
|
|
||||||
_onClearTextSearchAction = onClearTextSearchAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addOnSearchTextAction(OnSearchTextAction onSearchTextAction) {
|
|
||||||
_onSearchTextAction = onSearchTextAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setHeightSearchBar(double heightSearchBar) {
|
|
||||||
_heightSearchBar = heightSearchBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addDecoration(Decoration decoration) {
|
|
||||||
_decoration = decoration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addPadding(EdgeInsets padding) {
|
|
||||||
_padding = padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMargin(EdgeInsets margin) {
|
|
||||||
_margin = margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setHintText(String text) {
|
|
||||||
_hintText = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addIconClearText(Widget? icon) {
|
|
||||||
_iconClearText = icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget build() {
|
|
||||||
return Container(
|
return Container(
|
||||||
key: const Key('search_app_bar_widget'),
|
key: key ?? const Key('search_app_bar_widget'),
|
||||||
height: _heightSearchBar,
|
height: heightSearchBar,
|
||||||
decoration: _decoration,
|
decoration: decoration,
|
||||||
padding: _padding ?? EdgeInsets.zero,
|
padding: padding ?? EdgeInsets.zero,
|
||||||
margin: _margin,
|
margin: margin,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
if (hasBackButton) _buildBackButton(),
|
if (hasBackButton) _buildBackButton(),
|
||||||
if (hasSearchButton) _buildSearchButton(),
|
if (hasSearchButton) _buildSearchButton(),
|
||||||
Expanded(child: _buildSearchInputForm()),
|
Expanded(child: _buildSearchInputForm(context)),
|
||||||
if (suggestionSearch?.isNotEmpty == true
|
if (suggestionSearch?.isNotEmpty == true || (searchQuery != null && searchQuery!.value.isNotEmpty))
|
||||||
|| (_searchQuery != null && _searchQuery!.value.isNotEmpty))
|
|
||||||
_buildClearTextSearchButton(),
|
_buildClearTextSearchButton(),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@@ -104,47 +76,48 @@ class SearchAppBarWidget {
|
|||||||
|
|
||||||
Widget _buildBackButton() {
|
Widget _buildBackButton() {
|
||||||
return buildIconWeb(
|
return buildIconWeb(
|
||||||
icon: SvgPicture.asset(
|
icon: SvgPicture.asset(
|
||||||
_imagePaths.icBack,
|
imagePaths.icBack,
|
||||||
colorFilter: AppColor.colorTextButton.asFilter(),
|
colorFilter: AppColor.colorTextButton.asFilter(),
|
||||||
fit: BoxFit.fill),
|
fit: BoxFit.fill),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_searchInputController?.clear();
|
searchInputController?.clear();
|
||||||
if (_onCancelSearchPressed != null) {
|
if (onCancelSearchPressed != null) {
|
||||||
_onCancelSearchPressed!();
|
onCancelSearchPressed!();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildClearTextSearchButton() {
|
Widget _buildClearTextSearchButton() {
|
||||||
return buildIconWeb(
|
return buildIconWeb(
|
||||||
icon: _iconClearText ?? SvgPicture.asset(_imagePaths.icComposerClose, width: 18, height: 18, fit: BoxFit.fill),
|
icon: iconClearText ?? SvgPicture.asset(imagePaths.icComposerClose, width: 18, height: 18, fit: BoxFit.fill),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_searchInputController?.clear();
|
searchInputController?.clear();
|
||||||
_onClearTextSearchAction?.call();
|
onClearTextSearchAction?.call();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSearchInputForm() {
|
Widget _buildSearchInputForm(BuildContext context) {
|
||||||
return (TextFieldBuilder()
|
return TextFieldBuilder(
|
||||||
..key(const Key('search_input_form'))
|
key: const Key('search_input_form'),
|
||||||
..textInputAction(TextInputAction.done)
|
textInputAction: TextInputAction.done,
|
||||||
..onChange((value) => _onTextChangeSearchAction?.call(value))
|
onTextChange: onTextChangeSearchAction,
|
||||||
..onSubmitted((value) => _onSearchTextAction?.call(value))
|
onTextSubmitted: onSearchTextAction,
|
||||||
..cursorColor(AppColor.colorTextButton)
|
cursorColor: AppColor.colorTextButton,
|
||||||
..autoFocus(true)
|
textDirection: DirectionUtils.getDirectionByLanguage(context),
|
||||||
..addFocusNode(_searchFocusNode)
|
autoFocus: true,
|
||||||
..textStyle(const TextStyle(color: AppColor.colorNameEmail, fontSize: 17))
|
focusNode: searchFocusNode,
|
||||||
..textDecoration(InputDecoration(
|
textStyle: const TextStyle(color: AppColor.colorNameEmail, fontSize: 17),
|
||||||
border: InputBorder.none,
|
decoration: InputDecoration(
|
||||||
focusedBorder: InputBorder.none,
|
border: InputBorder.none,
|
||||||
enabledBorder: InputBorder.none,
|
focusedBorder: InputBorder.none,
|
||||||
contentPadding: EdgeInsets.zero,
|
enabledBorder: InputBorder.none,
|
||||||
hintText: _hintText,
|
contentPadding: EdgeInsets.zero,
|
||||||
hintStyle: const TextStyle(color: AppColor.colorHintSearchBar, fontSize: 17.0),
|
hintText: hintText,
|
||||||
labelStyle: const TextStyle(color: AppColor.colorHintSearchBar, fontSize: 17.0)))
|
hintStyle: const TextStyle(color: AppColor.colorHintSearchBar, fontSize: 17.0),
|
||||||
..addController(_searchInputController))
|
labelStyle: const TextStyle(color: AppColor.colorHintSearchBar, fontSize: 17.0)),
|
||||||
.build();
|
controller: searchInputController,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSearchButton() {
|
Widget _buildSearchButton() {
|
||||||
@@ -154,10 +127,10 @@ class SearchAppBarWidget {
|
|||||||
minSize: 40,
|
minSize: 40,
|
||||||
iconPadding: EdgeInsets.zero,
|
iconPadding: EdgeInsets.zero,
|
||||||
icon: SvgPicture.asset(
|
icon: SvgPicture.asset(
|
||||||
_imagePaths.icSearchBar,
|
imagePaths.icSearchBar,
|
||||||
fit: BoxFit.fill
|
fit: BoxFit.fill
|
||||||
),
|
),
|
||||||
onTap: () => _onSearchTextAction?.call(_searchInputController?.text ?? '')
|
onTap: () => onSearchTextAction?.call(searchInputController?.text ?? '')
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user