fix : ui change's
This commit is contained in:
@@ -74,6 +74,9 @@ class $AssetsIconsGen {
|
||||
/// File path: assets/icons/clock.svg
|
||||
SvgGenImage get clock => const SvgGenImage('assets/icons/clock.svg');
|
||||
|
||||
/// File path: assets/icons/close_circle.svg
|
||||
SvgGenImage get closeCircle => const SvgGenImage('assets/icons/close_circle.svg');
|
||||
|
||||
/// File path: assets/icons/close_square.svg
|
||||
SvgGenImage get closeSquare => const SvgGenImage('assets/icons/close_square.svg');
|
||||
|
||||
@@ -259,6 +262,7 @@ class $AssetsIconsGen {
|
||||
clipboardEye,
|
||||
clipboardTask,
|
||||
clock,
|
||||
closeCircle,
|
||||
closeSquare,
|
||||
convertCube,
|
||||
cube,
|
||||
@@ -395,6 +399,9 @@ class $AssetsVecGen {
|
||||
/// File path: assets/vec/clock.svg.vec
|
||||
SvgGenImage get clockSvg => const SvgGenImage.vec('assets/vec/clock.svg.vec');
|
||||
|
||||
/// File path: assets/vec/close_circle.svg.vec
|
||||
SvgGenImage get closeCircleSvg => const SvgGenImage.vec('assets/vec/close_circle.svg.vec');
|
||||
|
||||
/// File path: assets/vec/close_square.svg.vec
|
||||
SvgGenImage get closeSquareSvg => const SvgGenImage.vec('assets/vec/close_square.svg.vec');
|
||||
|
||||
@@ -580,6 +587,7 @@ class $AssetsVecGen {
|
||||
clipboardEyeSvg,
|
||||
clipboardTaskSvg,
|
||||
clockSvg,
|
||||
closeCircleSvg,
|
||||
closeSquareSvg,
|
||||
convertCubeSvg,
|
||||
cubeSvg,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_core/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_core/presentation/common/app_fonts.dart';
|
||||
import 'package:rasadyar_core/presentation/utils/color_utils.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ROutlinedElevated extends StatefulWidget {
|
||||
ROutlinedElevated({
|
||||
@@ -16,19 +14,17 @@ class ROutlinedElevated extends StatefulWidget {
|
||||
this.radius,
|
||||
this.textStyle,
|
||||
this.child,
|
||||
this.width = 150.0,
|
||||
this.height = 56.0,
|
||||
this.width,
|
||||
this.height,
|
||||
});
|
||||
|
||||
final String? text;
|
||||
final VoidCallback? onPressed;
|
||||
final double width;
|
||||
final double height;
|
||||
final double? width;
|
||||
final double? height;
|
||||
Color? foregroundColor;
|
||||
Color? backgroundColor;
|
||||
|
||||
Color? borderColor;
|
||||
|
||||
Color? disabledBackgroundColor;
|
||||
Color? pressedBackgroundColor;
|
||||
double? radius;
|
||||
@@ -40,64 +36,92 @@ class ROutlinedElevated extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ROutlinedElevatedState extends State<ROutlinedElevated> {
|
||||
final WidgetStatesController _statesController = WidgetStatesController();
|
||||
final GlobalKey _widgetKey = GlobalKey();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_getWidgetHeight();
|
||||
});
|
||||
}
|
||||
|
||||
void _getWidgetHeight() {
|
||||
final RenderBox? renderBox = _widgetKey.currentContext?.findRenderObject() as RenderBox?;
|
||||
if (renderBox != null) {
|
||||
final height = renderBox.size.height;
|
||||
debugPrint('ارتفاع ویجت بعد از رندر شدن: $height');
|
||||
} else {
|
||||
debugPrint('ویجت هنوز رندر نشده است');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_statesController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return OutlinedButton(
|
||||
onPressed: widget.onPressed,
|
||||
style: ButtonStyle(
|
||||
side: WidgetStateProperty.resolveWith<BorderSide?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return BorderSide(
|
||||
color: widget.borderColor ?? AppColor.blueNormal,
|
||||
width: 2,
|
||||
);
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return BorderSide(
|
||||
color: widget.borderColor ?? AppColor.blueNormal.withAlpha(38),
|
||||
width: 2,
|
||||
);
|
||||
}
|
||||
return BorderSide(
|
||||
color: widget.borderColor ?? AppColor.blueNormal,
|
||||
width: 2,
|
||||
);
|
||||
}),
|
||||
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
if (widget.pressedBackgroundColor != null) {
|
||||
return widget.pressedBackgroundColor;
|
||||
}
|
||||
return widget.backgroundColor?.pressedColor ?? AppColor.blueNormal;
|
||||
} else if (states.contains(WidgetState.hovered)) {
|
||||
return widget.backgroundColor?.hoverColor ??
|
||||
AppColor.blueNormal.hoverColor;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return widget.backgroundColor?.disabledColor ?? Colors.transparent;
|
||||
}
|
||||
return widget.backgroundColor;
|
||||
}),
|
||||
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.white;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return AppColor.blueNormal.withAlpha(38);
|
||||
}
|
||||
return AppColor.blueNormal;
|
||||
}),
|
||||
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(widget.radius ?? 8),
|
||||
),
|
||||
),
|
||||
fixedSize: WidgetStatePropertyAll(Size(widget.width, widget.height)),
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
textStyle: WidgetStatePropertyAll(
|
||||
widget.textStyle ??
|
||||
AppFonts.yekan24.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
return ConstrainedBox(
|
||||
constraints: BoxConstraints.tightFor(
|
||||
width: widget.width ?? 150.w,
|
||||
height: widget.height ?? 40.h,
|
||||
),
|
||||
child: OutlinedButton(
|
||||
key: _widgetKey,
|
||||
statesController: _statesController,
|
||||
onPressed: widget.onPressed,
|
||||
style: ButtonStyle(
|
||||
side: WidgetStateProperty.resolveWith<BorderSide?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return BorderSide(color: widget.borderColor ?? AppColor.blueNormal, width: 2);
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return BorderSide(
|
||||
color: widget.borderColor ?? AppColor.blueNormal.withAlpha(38),
|
||||
width: 2,
|
||||
);
|
||||
}
|
||||
return BorderSide(color: widget.borderColor ?? AppColor.blueNormal, width: 2);
|
||||
}),
|
||||
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
if (widget.pressedBackgroundColor != null) {
|
||||
return widget.pressedBackgroundColor;
|
||||
}
|
||||
return widget.backgroundColor?.pressedColor ?? widget.borderColor?.pressedColor;
|
||||
} else if (states.contains(WidgetState.hovered)) {
|
||||
return widget.backgroundColor?.hoverColor ?? AppColor.blueNormal.hoverColor;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return widget.backgroundColor?.disabledColor ?? Colors.transparent;
|
||||
}
|
||||
return widget.backgroundColor;
|
||||
}),
|
||||
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.white;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return AppColor.blueNormal.withAlpha(38);
|
||||
}
|
||||
return widget.foregroundColor ?? widget.borderColor ?? AppColor.blueNormal;
|
||||
}),
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(widget.radius ?? 8)),
|
||||
),
|
||||
fixedSize: WidgetStatePropertyAll(Size(widget.width ?? 150.w, widget.height ?? 56.h)),
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
textStyle: WidgetStateProperty.resolveWith<TextStyle?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return widget.textStyle?.copyWith(color: Colors.white) ??
|
||||
AppFonts.yekan20.copyWith(color: Colors.white);
|
||||
}
|
||||
return widget.textStyle ?? AppFonts.yekan20.copyWith(color: AppColor.blueNormal);
|
||||
}),
|
||||
),
|
||||
child: Text(widget.text ?? ''),
|
||||
),
|
||||
child: widget.child ?? Text(widget.text!, style: widget.textStyle),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class EmptyWidget extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(),
|
||||
Assets.images.placeHolder.image(width: 170.w,height: 170.h),
|
||||
Assets.vec.emptySvg.svg(width: 170.w,height: 170.h),
|
||||
Text('داده ای یافت نشد!', style: AppFonts.yekan20.copyWith(color: AppColor.textColor)),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -37,40 +39,69 @@ class RTextField extends StatefulWidget {
|
||||
final VoidCallback? onTap;
|
||||
final List<TextInputFormatter>? inputFormatters;
|
||||
final Widget? suffix;
|
||||
final FocusNode? focusNode;
|
||||
final AutovalidateMode? autoValidateMode;
|
||||
final TextAlign? textAlign;
|
||||
final TextCapitalization textCapitalization;
|
||||
final Color? cursorColor;
|
||||
final bool? autocorrect;
|
||||
final bool? enableSuggestions;
|
||||
final TextInputAction? textInputAction;
|
||||
final double? height;
|
||||
|
||||
const RTextField({
|
||||
super.key,
|
||||
// 🔹 Core
|
||||
required this.controller,
|
||||
this.label,
|
||||
this.hintText,
|
||||
this.initText,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.onTap,
|
||||
this.height,
|
||||
|
||||
// 🔸 Behavior
|
||||
this.obscure = false,
|
||||
this.readonly = false,
|
||||
this.enabled = true,
|
||||
this.maxLength,
|
||||
this.minLines,
|
||||
this.maxLines = 1,
|
||||
this.suffixIcon,
|
||||
this.prefixIcon,
|
||||
this.boxConstraints,
|
||||
this.variant = RTextFieldVariant.normal,
|
||||
this.filled = false,
|
||||
this.filledColor,
|
||||
this.showCounter = false,
|
||||
this.isDense = false,
|
||||
this.textInputAction,
|
||||
this.keyboardType,
|
||||
this.focusNode,
|
||||
|
||||
// ⚙️ Input styling
|
||||
this.textAlign,
|
||||
this.textCapitalization = TextCapitalization.none,
|
||||
this.cursorColor,
|
||||
this.autocorrect,
|
||||
this.enableSuggestions,
|
||||
this.style,
|
||||
this.hintStyle,
|
||||
this.labelStyle,
|
||||
this.errorStyle,
|
||||
this.padding,
|
||||
this.validator,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.borderColor,
|
||||
this.inputFormatters,
|
||||
this.onTap,
|
||||
|
||||
// 🎨 Decorations
|
||||
this.suffixIcon,
|
||||
this.prefixIcon,
|
||||
this.suffix,
|
||||
this.boxConstraints,
|
||||
|
||||
// 📐 Layout & appearance
|
||||
this.borderColor,
|
||||
this.filled = false,
|
||||
this.filledColor,
|
||||
this.padding,
|
||||
this.variant = RTextFieldVariant.normal,
|
||||
|
||||
// 📋 Form validation
|
||||
this.validator,
|
||||
this.autoValidateMode,
|
||||
this.inputFormatters,
|
||||
this.showCounter = false,
|
||||
this.isDense = false,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -92,6 +123,27 @@ class RTextField extends StatefulWidget {
|
||||
|
||||
class _RTextFieldState extends State<RTextField> {
|
||||
late bool obscure;
|
||||
late TextDirection textDirection;
|
||||
|
||||
Timer? _debounceTimer;
|
||||
|
||||
TextDirection _detectDirection(String text) {
|
||||
final isPersian = RegExp(r'[\u0600-\u06FF]').hasMatch(text);
|
||||
return isPersian ? TextDirection.rtl : TextDirection.ltr;
|
||||
}
|
||||
|
||||
void _debouncedUpdateTextDirection() {
|
||||
if (_debounceTimer?.isActive ?? false) _debounceTimer!.cancel();
|
||||
|
||||
_debounceTimer = Timer(const Duration(milliseconds: 300), () {
|
||||
final newDirection = _detectDirection(widget.controller.text);
|
||||
if (newDirection != textDirection) {
|
||||
setState(() {
|
||||
textDirection = newDirection;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -100,82 +152,106 @@ class _RTextFieldState extends State<RTextField> {
|
||||
widget.controller.text = widget.initText!;
|
||||
}
|
||||
obscure = widget.obscure;
|
||||
|
||||
textDirection = _detectDirection(
|
||||
widget.controller.text.isNotEmpty ? widget.controller.text : widget.initText ?? 'سلام',
|
||||
);
|
||||
|
||||
widget.controller.addListener(_debouncedUpdateTextDirection);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant RTextField oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.initText != null && widget.initText != oldWidget.initText) {
|
||||
if (widget.initText != null && widget.controller.text != widget.initText) {
|
||||
widget.controller.text = widget.initText!;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildSuffixIcon() {
|
||||
if (widget.suffixIcon != null) return widget.suffixIcon!;
|
||||
if (!widget._isPassword) return const SizedBox.shrink();
|
||||
Widget? _buildSuffixIcon() {
|
||||
if (widget._isPassword || widget._passwordNoBorder) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
obscure = !obscure;
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
obscure ? CupertinoIcons.eye : CupertinoIcons.eye_slash,
|
||||
color: AppColor.darkGreyDarkActive,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return widget.suffixIcon;
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
obscure = !obscure;
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
obscure ? CupertinoIcons.eye : CupertinoIcons.eye_slash,
|
||||
color: AppColor.darkGreyDarkActive,
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: widget.height,
|
||||
child: Padding(
|
||||
padding: widget.padding ?? EdgeInsets.zero,
|
||||
child: TextFormField(
|
||||
controller: widget.controller,
|
||||
focusNode: widget.focusNode,
|
||||
textAlign: widget.textAlign ?? TextAlign.start,
|
||||
readOnly: widget.readonly,
|
||||
minLines: widget.minLines,
|
||||
maxLines: widget.maxLines,
|
||||
onChanged: widget.onChanged,
|
||||
validator: widget.validator,
|
||||
inputFormatters: widget.inputFormatters,
|
||||
enabled: widget.enabled,
|
||||
obscureText: obscure,
|
||||
onTap: widget.onTap,
|
||||
onTapOutside: (_) => FocusScope.of(context).unfocus(),
|
||||
onFieldSubmitted: widget.onSubmitted,
|
||||
maxLength: widget.maxLength,
|
||||
textDirection: textDirection,
|
||||
style: widget.style,
|
||||
keyboardType: widget.keyboardType,
|
||||
autovalidateMode: widget.autoValidateMode ?? AutovalidateMode.disabled,
|
||||
cursorColor: widget.cursorColor,
|
||||
textCapitalization: widget.textCapitalization,
|
||||
autocorrect: widget.autocorrect ?? true,
|
||||
enableSuggestions: widget.enableSuggestions ?? true,
|
||||
textInputAction: widget.textInputAction,
|
||||
decoration: InputDecoration(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
errorStyle: widget.errorStyle,
|
||||
errorMaxLines: 1,
|
||||
isDense: widget.isDense,
|
||||
suffix: widget.suffix,
|
||||
suffixIcon: _buildSuffixIcon(),
|
||||
suffixIconConstraints: widget.boxConstraints,
|
||||
prefixIcon: widget.prefixIcon,
|
||||
prefixIconConstraints: widget.boxConstraints,
|
||||
hintText: widget.hintText,
|
||||
labelText: widget.label,
|
||||
alignLabelWithHint: true,
|
||||
labelStyle: AppFonts.yekan14
|
||||
.copyWith(color: AppColor.lightGreyDarkActive)
|
||||
.merge(widget.labelStyle),
|
||||
filled: widget.filled || widget._noBorder || widget._passwordNoBorder,
|
||||
fillColor: widget.filledColor,
|
||||
counter: widget.showCounter ? null : const SizedBox(),
|
||||
hintStyle: widget.hintStyle,
|
||||
enabledBorder: widget._inputBorder,
|
||||
focusedBorder: widget._inputBorder,
|
||||
border: widget._inputBorder,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: widget.padding ?? EdgeInsets.zero,
|
||||
child: TextFormField(
|
||||
controller: widget.controller,
|
||||
readOnly: widget.readonly,
|
||||
minLines: widget.minLines,
|
||||
maxLines: widget.maxLines,
|
||||
onChanged: widget.onChanged,
|
||||
validator: widget.validator,
|
||||
inputFormatters: widget.inputFormatters,
|
||||
enabled: widget.enabled,
|
||||
obscureText: obscure,
|
||||
onTap: widget.onTap,
|
||||
onTapOutside: (_) => FocusScope.of(context).unfocus(),
|
||||
onFieldSubmitted: widget.onSubmitted,
|
||||
maxLength: widget.maxLength,
|
||||
textDirection: TextDirection.rtl,
|
||||
style: widget.style,
|
||||
keyboardType: widget.keyboardType,
|
||||
decoration: InputDecoration(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
errorStyle: widget.errorStyle,
|
||||
errorMaxLines: 1,
|
||||
isDense: widget.isDense,
|
||||
suffix: widget.suffix,
|
||||
suffixIcon: _buildSuffixIcon(),
|
||||
suffixIconConstraints: widget.boxConstraints,
|
||||
prefixIcon: widget.prefixIcon,
|
||||
prefixIconConstraints: widget.boxConstraints,
|
||||
hintText: widget.hintText,
|
||||
labelText: widget.label,
|
||||
alignLabelWithHint: true,
|
||||
labelStyle: AppFonts.yekan14
|
||||
.copyWith(color: AppColor.lightGreyDarkActive)
|
||||
.merge(widget.labelStyle),
|
||||
filled: widget.filled || widget._noBorder || widget._passwordNoBorder,
|
||||
fillColor: widget.filledColor,
|
||||
counter: widget.showCounter ? null : const SizedBox(),
|
||||
hintStyle: widget.hintStyle,
|
||||
enabledBorder: widget._inputBorder,
|
||||
focusedBorder: widget._inputBorder,
|
||||
border: widget._inputBorder,
|
||||
),
|
||||
),
|
||||
);
|
||||
void dispose() {
|
||||
_debounceTimer?.cancel();
|
||||
widget.controller.removeListener(_debouncedUpdateTextDirection);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user