fix : ui change's

This commit is contained in:
2025-07-09 14:54:28 +03:30
parent d51e0240bb
commit 0b921fa917
27 changed files with 611 additions and 1004 deletions

View File

@@ -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,

View File

@@ -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),
);
}
}

View File

@@ -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)),
],
);

View File

@@ -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();
}
}